Package _Framework :: Module SessionComponent
[hide private]
[frames] | no frames]

Source Code for Module _Framework.SessionComponent

  1  #Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/_Framework/SessionComponent.py 
  2  import Live 
  3  from CompoundComponent import CompoundComponent 
  4  from SceneComponent import SceneComponent 
  5  from SubjectSlot import subject_slot 
  6  from ScrollComponent import ScrollComponent 
  7  from Util import in_range, product 
8 9 -class SessionComponent(CompoundComponent):
10 """ 11 Class encompassing several scene to cover a defined section of 12 Live's session. It controls the session ring and the set of tracks 13 controlled by a given mixer. 14 """ 15 __subject_events__ = ('offset',) 16 _linked_session_instances = [] 17 _minimal_track_offset = -1 18 _minimal_scene_offset = -1 19 _highlighting_callback = None 20 _session_component_ends_initialisation = True 21 scene_component_type = SceneComponent 22
23 - def __init__(self, num_tracks = 0, num_scenes = 0, *a, **k):
24 super(SessionComponent, self).__init__(*a, **k) 25 raise num_tracks >= 0 or AssertionError 26 if not num_scenes >= 0: 27 raise AssertionError 28 self._track_offset = -1 29 self._scene_offset = -1 30 self._num_tracks = num_tracks 31 self._num_scenes = num_scenes 32 self._vertical_banking, self._horizontal_banking = self.register_components(ScrollComponent(), ScrollComponent()) 33 self._vertical_banking.can_scroll_up = self._can_bank_up 34 self._vertical_banking.can_scroll_down = self._can_bank_down 35 self._vertical_banking.scroll_up = self._bank_up 36 self._vertical_banking.scroll_down = self._bank_down 37 self._horizontal_banking.can_scroll_up = self._can_bank_left 38 self._horizontal_banking.can_scroll_down = self._can_bank_right 39 self._horizontal_banking.scroll_up = self._bank_left 40 self._horizontal_banking.scroll_down = self._bank_right 41 self._track_banking_increment = 1 42 self._stop_all_button = None 43 self._next_scene_button = None 44 self._prev_scene_button = None 45 self._stop_track_clip_buttons = None 46 self._stop_track_clip_value = 127 47 self._stop_track_clip_slots = self.register_slot_manager() 48 self._highlighting_callback = None 49 self._show_highlight = num_tracks > 0 and num_scenes > 0 50 self._mixer = None 51 self._track_slots = self.register_slot_manager() 52 self._selected_scene = self.register_component(self._create_scene()) 53 self._scenes = self.register_components(*[ self._create_scene() for _ in xrange(num_scenes) ]) 54 self._session_component_ends_initialisation and self._end_initialisation()
55
56 - def _end_initialisation(self):
57 self.on_selected_scene_changed() 58 self.set_offsets(0, 0)
59
60 - def _create_scene(self):
61 return self.scene_component_type(num_slots=self._num_tracks, tracks_to_use_callback=self.tracks_to_use)
62
63 - def disconnect(self):
64 if self._is_linked(): 65 self._unlink() 66 super(CompoundComponent, self).disconnect()
67
68 - def set_highlighting_callback(self, callback):
69 if not (not callback or callable(callback)): 70 raise AssertionError 71 self._highlighting_callback = self._highlighting_callback != callback and callback 72 self._do_show_highlight()
73
74 - def scene(self, index):
75 raise in_range(index, 0, len(self._scenes)) or AssertionError 76 return self._scenes[index]
77
78 - def selected_scene(self):
79 return self._selected_scene
80
81 - def set_scene_bank_buttons(self, down_button, up_button):
82 self.set_scene_bank_up_button(up_button) 83 self.set_scene_bank_down_button(down_button)
84
85 - def set_scene_bank_up_button(self, button):
86 self._bank_up_button = button 87 self._vertical_banking.set_scroll_up_button(button)
88
89 - def set_scene_bank_down_button(self, button):
90 self._bank_down_button = button 91 self._vertical_banking.set_scroll_down_button(button)
92
93 - def set_track_bank_buttons(self, right_button, left_button):
94 self.set_track_bank_left_button(left_button) 95 self.set_track_bank_right_button(right_button)
96
97 - def set_track_bank_left_button(self, button):
98 self._bank_left_button = button 99 self._horizontal_banking.set_scroll_up_button(button)
100
101 - def set_track_bank_right_button(self, button):
102 self._bank_right_button = button 103 self._horizontal_banking.set_scroll_down_button(button)
104
105 - def set_stop_all_clips_button(self, button):
106 self._stop_all_button = button 107 self._on_stop_all_value.subject = button 108 self._update_stop_all_clips_button()
109
110 - def set_stop_track_clip_buttons(self, buttons):
111 self._stop_track_clip_slots.disconnect() 112 self._stop_track_clip_buttons = buttons 113 if self._stop_track_clip_buttons != None: 114 for index, button in enumerate(self._stop_track_clip_buttons): 115 if button: 116 self._stop_track_clip_slots.register_slot(button, self._on_stop_track_value, 'value', extra_kws={'identify_sender': True}) 117 self._on_fired_slot_index_changed(index)
118
119 - def set_track_banking_increment(self, increment):
120 raise increment > 0 or AssertionError 121 self._track_banking_increment = increment
122
123 - def set_stop_track_clip_value(self, value):
124 raise in_range(value, 0, 128) or AssertionError 125 self._stop_track_clip_value = value
126
127 - def set_select_buttons(self, next_button, prev_button):
128 self.set_select_next_button(next_button) 129 self.set_select_prev_button(prev_button)
130
131 - def set_select_next_button(self, next_button):
132 self._next_scene_button = next_button 133 self._on_next_scene_value.subject = next_button 134 self._update_select_buttons()
135
136 - def set_select_prev_button(self, prev_button):
137 self._prev_scene_button = prev_button 138 self._on_prev_scene_value.subject = prev_button 139 self._update_select_buttons()
140
141 - def set_clip_launch_buttons(self, buttons):
142 raise not buttons or buttons.width() == self._num_tracks and buttons.height() == self._num_scenes or AssertionError 143 if buttons: 144 for button, (x, y) in buttons.iterbuttons(): 145 scene = self.scene(y) 146 slot = scene.clip_slot(x) 147 slot.set_launch_button(button) 148 149 else: 150 for x, y in product(xrange(self._num_tracks), xrange(self._num_scenes)): 151 scene = self.scene(y) 152 slot = scene.clip_slot(x) 153 slot.set_launch_button(None)
154
155 - def set_scene_launch_buttons(self, buttons):
156 raise not buttons or buttons.width() == self._num_scenes and buttons.height() == 1 or AssertionError 157 if buttons: 158 for button, (x, _) in buttons.iterbuttons(): 159 scene = self.scene(x) 160 scene.set_launch_button(button) 161 162 else: 163 for x in xrange(self._num_scenes): 164 scene = self.scene(x) 165 scene.set_launch_button(None)
166
167 - def set_mixer(self, mixer):
168 """ Sets the MixerComponent to be controlled by this session """ 169 self._mixer = mixer 170 if self._mixer != None: 171 self._mixer.set_track_offset(self.track_offset())
172
173 - def set_offsets(self, track_offset, scene_offset):
174 if not track_offset >= 0: 175 raise AssertionError 176 raise scene_offset >= 0 or AssertionError 177 track_increment = 0 178 scene_increment = 0 179 self._is_linked() and SessionComponent._perform_offset_change(track_offset - self._track_offset, scene_offset - self._scene_offset) 180 else: 181 if len(self.tracks_to_use()) > track_offset: 182 track_increment = track_offset - self._track_offset 183 if len(self.song().scenes) > scene_offset: 184 scene_increment = scene_offset - self._scene_offset 185 self._change_offsets(track_increment, scene_increment)
186
187 - def set_show_highlight(self, show_highlight):
188 if self._show_highlight != show_highlight: 189 self._show_highlight = show_highlight 190 self._do_show_highlight()
191
192 - def on_enabled_changed(self):
193 self.update() 194 self._do_show_highlight()
195
196 - def update(self):
197 if self._allow_updates: 198 self._update_select_buttons() 199 self._update_stop_track_clip_buttons() 200 self._update_stop_all_clips_button() 201 else: 202 self._update_requests += 1
203
205 if self.is_enabled(): 206 for index in xrange(self._num_tracks): 207 self._on_fired_slot_index_changed(index)
208
209 - def on_scene_list_changed(self):
210 if not self._update_scene_offset(): 211 self._reassign_scenes()
212
213 - def on_track_list_changed(self):
214 num_tracks = len(self.tracks_to_use()) 215 new_track_offset = self.track_offset() 216 if new_track_offset >= num_tracks: 217 new_track_offset = num_tracks - 1 218 new_track_offset -= new_track_offset % self._track_banking_increment 219 self._reassign_tracks() 220 self.set_offsets(new_track_offset, self.scene_offset())
221
223 self._update_scene_offset() 224 if self._selected_scene != None: 225 self._selected_scene.set_scene(self.song().view.selected_scene)
226
227 - def width(self):
228 return self._num_tracks
229
230 - def height(self):
231 return len(self._scenes)
232
233 - def track_offset(self):
234 return self._track_offset
235
236 - def scene_offset(self):
237 return self._scene_offset
238
239 - def tracks_to_use(self):
240 list_of_tracks = None 241 if self._mixer != None: 242 list_of_tracks = self._mixer.tracks_to_use() 243 else: 244 list_of_tracks = self.song().visible_tracks 245 return list_of_tracks
246 249 252
253 - def _can_bank_down(self):
254 return len(self.song().scenes) > self._get_minimal_scene_offset() + 1
255
256 - def _can_bank_up(self):
257 return self._get_minimal_scene_offset() > 0
258
259 - def _can_bank_right(self):
260 return len(self.tracks_to_use()) > self._get_minimal_track_offset() + 1
261
262 - def _can_bank_left(self):
263 return self._get_minimal_track_offset() > 0
264
265 - def _bank_up(self):
266 return self.set_offsets(self.track_offset(), max(0, self.scene_offset() - 1))
267
268 - def _bank_down(self):
269 return self.set_offsets(self.track_offset(), self.scene_offset() + 1)
270
271 - def _bank_right(self):
272 return self.set_offsets(self.track_offset() + self._track_banking_increment, self.scene_offset())
273
274 - def _bank_left(self):
275 return self.set_offsets(max(self.track_offset() - self._track_banking_increment, 0), self.scene_offset())
276
278 pass
279
280 - def _update_select_buttons(self):
281 selected_scene = self.song().view.selected_scene 282 if self._next_scene_button != None: 283 self._next_scene_button.set_light(selected_scene != self.song().scenes[-1]) 284 if self._prev_scene_button != None: 285 self._next_scene_button.set_light(selected_scene != self.song().scenes[0])
286
287 - def _update_scene_offset(self):
288 offset_corrected = False 289 num_scenes = len(self.song().scenes) 290 if self.scene_offset() >= num_scenes: 291 self.set_offsets(self.track_offset(), num_scenes - 1) 292 offset_corrected = True 293 return offset_corrected
294
295 - def _change_offsets(self, track_increment, scene_increment):
296 if not track_increment != 0: 297 offsets_changed = scene_increment != 0 298 offsets_changed and self._track_offset += track_increment 299 self._scene_offset += scene_increment 300 raise self._track_offset >= 0 or AssertionError 301 if not self._scene_offset >= 0: 302 raise AssertionError 303 if self._mixer != None: 304 self._mixer.set_track_offset(self.track_offset()) 305 self._reassign_tracks() 306 self._reassign_scenes() 307 self.notify_offset() 308 self.width() > 0 and self.height() > 0 and self._do_show_highlight()
309
310 - def _reassign_scenes(self):
311 scenes = self.song().scenes 312 for index in range(len(self._scenes)): 313 scene_index = self._scene_offset + index 314 if len(scenes) > scene_index: 315 self._scenes[index].set_scene(scenes[scene_index]) 316 self._scenes[index].set_track_offset(self._track_offset) 317 else: 318 self._scenes[index].set_scene(None) 319 320 if self._selected_scene != None: 321 self._selected_scene.set_track_offset(self._track_offset) 322 self._vertical_banking.update()
323
324 - def _reassign_tracks(self):
325 self._track_slots.disconnect() 326 tracks_to_use = self.tracks_to_use() 327 for index in range(self._num_tracks): 328 listener = lambda index = index: self._on_fired_slot_index_changed(index) 329 if self._track_offset + index < len(tracks_to_use): 330 track = tracks_to_use[self._track_offset + index] 331 if track in self.song().tracks: 332 self._track_slots.register_slot(track, listener, 'fired_slot_index') 333 listener() 334 335 self._horizontal_banking.update()
336 337 @subject_slot('value')
338 - def _on_stop_all_value(self, value):
340
341 - def _stop_all_value(self, value):
342 if self.is_enabled(): 343 if value is not 0 or not self._stop_all_button.is_momentary(): 344 self.song().stop_all_clips()
345 346 @subject_slot('value')
347 - def _on_next_scene_value(self, value):
348 if self.is_enabled(): 349 if value is not 0 or not self._next_scene_button.is_momentary(): 350 selected_scene = self.song().view.selected_scene 351 all_scenes = self.song().scenes 352 if selected_scene != all_scenes[-1]: 353 index = list(all_scenes).index(selected_scene) 354 self.song().view.selected_scene = all_scenes[index + 1]
355 356 @subject_slot('value')
357 - def _on_prev_scene_value(self, value):
358 if self.is_enabled(): 359 if value is not 0 or not self._prev_scene_button.is_momentary(): 360 selected_scene = self.song().view.selected_scene 361 all_scenes = self.song().scenes 362 if selected_scene != all_scenes[0]: 363 index = list(all_scenes).index(selected_scene) 364 self.song().view.selected_scene = all_scenes[index - 1]
365 366 @subject_slot('value')
367 - def _on_stop_track_value(self, value, sender):
368 if self.is_enabled(): 369 if value is not 0 or not sender.is_momentary(): 370 tracks = self.tracks_to_use() 371 track_index = list(self._stop_track_clip_buttons).index(sender) + self.track_offset() 372 if in_range(track_index, 0, len(tracks)) and tracks[track_index] in self.song().tracks: 373 tracks[track_index].stop_all_clips()
374
375 - def _do_show_highlight(self):
376 if self._highlighting_callback != None: 377 return_tracks = self.song().return_tracks 378 if len(return_tracks) > 0: 379 include_returns = return_tracks[0] in self.tracks_to_use() 380 self._show_highlight and self._highlighting_callback(self._track_offset, self._scene_offset, self.width(), self.height(), include_returns) 381 else: 382 self._highlighting_callback(-1, -1, -1, -1, include_returns)
383
384 - def _on_fired_slot_index_changed(self, index):
385 tracks_to_use = self.tracks_to_use() 386 track_index = index + self.track_offset() 387 if self.is_enabled() and self._stop_track_clip_buttons != None: 388 if index < len(self._stop_track_clip_buttons): 389 button = self._stop_track_clip_buttons[index] 390 if button != None: 391 track_index < len(tracks_to_use) and tracks_to_use[track_index].clip_slots and tracks_to_use[track_index].fired_slot_index == -2 and button.send_value(self._stop_track_clip_value) 392 else: 393 button.turn_off()
394
395 - def _is_linked(self):
397 401 405 406 @staticmethod
407 - def _perform_offset_change(track_increment, scene_increment):
408 """ Performs the given offset changes on all linked instances """ 409 if not len(SessionComponent._linked_session_instances) > 0: 410 raise AssertionError 411 scenes = Live.Application.get_application().get_document().scenes 412 instances_covering_session = 0 413 found_negative_offset = False 414 minimal_track_offset = -1 415 minimal_scene_offset = -1 416 for instance in SessionComponent._linked_session_instances: 417 new_track_offset = instance.track_offset() + track_increment 418 new_scene_offset = instance.scene_offset() + scene_increment 419 if new_track_offset >= 0 and new_scene_offset >= 0: 420 if new_track_offset < len(instance.tracks_to_use()) and new_scene_offset < len(scenes): 421 instances_covering_session += 1 422 if minimal_track_offset < 0: 423 minimal_track_offset = new_track_offset 424 else: 425 minimal_track_offset = min(minimal_track_offset, new_track_offset) 426 if minimal_scene_offset < 0: 427 minimal_scene_offset = new_scene_offset 428 else: 429 minimal_scene_offset = min(minimal_scene_offset, new_scene_offset) 430 else: 431 found_negative_offset = True 432 break 433 434 SessionComponent._minimal_track_offset = not found_negative_offset and instances_covering_session > 0 and minimal_track_offset 435 SessionComponent._minimal_scene_offset = minimal_scene_offset 436 for instance in SessionComponent._linked_session_instances: 437 instance._change_offsets(track_increment, scene_increment)
438