5 # Copyright 2004-2005, under the GPL
10 from twisted.internet import gtk2reactor
12 from twisted.internet import reactor, protocol
13 import twisted.internet.error
19 #standard python2.2 libraries
27 import xml.dom.minidom
29 def get_header_size(filename):
31 file = open(filename, 'r')
37 return size + 4 #include the size chunk after "data"
42 def append_empty_data(self, filename, size):
43 file = open(filename, 'a')
48 def get_sound_list(snapshot):
49 doc = xml.dom.minidom.parse(snapshot)
52 playlists_tag = doc.getElementsByTagName('Playlists')
53 playlists = playlists_tag[0].getElementsByTagName('Playlist')
54 for play in playlists:
55 regions = play.getElementsByTagName('Region')
56 for region in regions:
57 regionlist.append(region.getAttribute('source-0'))
58 regionlist.append(region.getAttribute('source-1'))
59 regionlist.append(region.getAttribute('source-2'))
60 regionlist.append(region.getAttribute('source-3'))
61 regionlist.append(region.getAttribute('source-4'))
62 regionlist.append(region.getAttribute('source-5'))
65 sources = doc.getElementsByTagName('Source')
66 for source in sources:
67 sourcelist[source.getAttribute('id')] = str(source.getAttribute('name'))
71 if sourcelist.has_key(id):
72 soundlist.append(sourcelist[id])
76 def raise_error(string, parent):
77 dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
78 gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, string)
84 def delete_snap(self, session, collab, snap):
85 sessions = self._data['sessions']
86 sessions[session]['collabs'][collab]['snaps'].remove(snap)
87 self._data['sessions'] = sessions
89 def delete_collab(self,session, collab):
90 sessions = self._data['sessions']
91 del sessions[session]['collabs'][collab]
92 self._data['sessions'] = sessions
94 def delete_session(self, session):
95 sessions = self._data['sessions']
97 self._data['sessions'] = sessions
99 def add_snap(self, session_name, collab_name, snap_name):
100 sessions = self._data['sessions']
101 sessions[session_name]['collabs'][collab_name]['snaps'].append(snap_name)
102 sessions[session_name]['collabs'][collab_name]['snaps'].sort()
103 self._data['sessions'] = sessions
105 g_display.update_snap_view()
107 def add_collab(self, session_name, collab_name, ip_address, port):
108 sessions = self._data['sessions']
109 sessions[session_name]['collabs'][collab_name] = {}
110 sessions[session_name]['collabs'][collab_name]['snaps'] = []
111 sessions[session_name]['collabs'][collab_name]['sounds'] = []
112 sessions[session_name]['collabs'][collab_name]['ip'] = ip_address
113 sessions[session_name]['collabs'][collab_name]['port'] = port
114 sessions[session_name]['collabs'][collab_name]['v2paths'] = true
115 self._data['sessions'] = sessions
117 client = ExchangeClientFactory(session_name, collab_name, None, self.debug_mode)
118 reactor.connectTCP(ip_address, port, client)
119 g_display.show_status("connecting")
121 g_display.update_collab_view()
123 def add_session(self, session_path):
124 sessions = self._data['sessions']
126 session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1]
127 sessions[session_name] = {}
128 sessions[session_name]['path'] = session_path
129 sessions[session_name]['collabs'] = {}
130 sessions[session_name]['collabs'][self._data['user']] = {}
131 sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
132 sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
133 if os.path.test (os.path.join (session_path,'sounds')):
134 sessions[session_name]['collabs'][collab_name]['v2paths'] = False
136 sessions[session_name]['collabs'][collab_name]['v2paths'] = True
138 self._data['sessions'] = sessions
140 self.rescan_session(session_name)
142 def rescan_session(self, session_name):
143 sessions = self._data['sessions']
145 session_path = sessions[session_name]['path']
146 sessions[session_name]['collabs'][self._data['user']]['snaps'] = self._scan_snapshots(session_path)
147 sessions[session_name]['collabs'][self._data['user']]['sounds'] = self._scan_sounds(session_path)
149 self._data['sessions'] = sessions
151 g_display.update_snap_view()
153 print self._data['sessions']
155 def create_session(self, session_path):
157 os.mkdir(session_path)
158 os.mkdir(os.path.join (session_path,'interchange',session_name,'audiofiles'))
161 raise_error("Could not create session directory", g_display.window)
164 sessions = self._data['sessions']
166 session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ]
167 sessions[session_name] = {}
168 sessions[session_name]['path'] = session_path
169 sessions[session_name]['collabs'] = {}
170 sessions[session_name]['collabs'][self._data['user']] = {}
171 sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
172 sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
174 self._data['sessions'] = sessions
175 print self._data['sessions']
177 def get_session_path(self, session):
178 sessions = self._data['sessions']
179 return sessions[session]['path']
182 return self._data['user']
184 def set_user(self, username):
185 self._data['user'] = username
187 def get_collab_ip(self, session, collab):
188 sessions = self._data['sessions']
189 return sessions[session]['collabs'][collab]['ip']
194 def get_sessions(self):
195 sessions = self._data['sessions']
196 sess = sessions.keys()
200 def get_collabs(self, session):
202 sessions = self._data['sessions']
203 collabs = sessions[session]['collabs'].keys()
209 def get_snaps(self, session, collab):
210 if session and collab:
211 sessions = self._data['sessions']
212 snaps = sessions[session]['collabs'][collab]['snaps']
218 def get_sounds(self, session, collab):
219 if session and collab:
220 sessions = self._data['sessions']
221 sounds = sessions[session]['collabs'][self._data['user']]['sounds']
227 def _scan_snapshots(self, session):
229 files = os.listdir(session)
230 pattern = re.compile(r'\.ardour$')
232 if pattern.search(file):
233 snaps.append(file[0:-7])
237 def _scan_sounds(self, session):
240 files = os.listdir(os.path.join (session,'interchange', session, 'audiofiles'))
242 files = os.listdir(os.path.join (session,'sounds'))
243 pattern = re.compile(r'\.peak$')
245 if not pattern.search(file):
249 def __init__(self, *args):
250 self._data = shelve.open(os.path.expanduser('~/.session_exchange'), 'c')
252 self.debug_mode = False
253 if len(self._data.keys()) < 1:
254 self._data['sessions'] = {}
255 self._data['user'] = ''
259 from twisted.protocols.basic import FileSender
260 class FileSenderLimited(FileSender):
261 def beginFileTransfer(self, file, consumer, limit, transform = None):
263 self.consumer = consumer
264 self.CHUNK_SIZE = limit
265 self.transform = transform
267 self.consumer.registerProducer(self, False)
268 self.deferred = defer.Deferred()
271 def resumeProducing(self):
273 chunk = self.file.read(self.CHUNK_SIZE)
276 chunk = self.transform(chunk)
278 self.consumer.write(chunk)
279 self.lastSent = chunk[-1]
281 self.consumer.unregisterProducer()
282 self.deferred.callback(self.lastSent)
285 from twisted.protocols.basic import LineReceiver
286 class ExchangeServer (LineReceiver):
290 def error(self, message):
291 self.sendLine("ERROR")
292 self.sendLine(message)
293 self.transport.loseConnection()
295 def connectionLost(self, reason):
296 print "server: connection lost: ", reason
298 def connectionMade(self):
299 print "server: connection made"
301 def lineReceived(self, data):
302 print "server: ", data
304 if self.state == "SESSION":
305 if g_data.get_sessions().count(data):
306 self.session_name = data
310 self.error(data + " doesn't exist on server")
311 elif self.state == "SNAPSHOT":
312 if g_data.get_snaps(self.session_name, g_data.get_user()).count(data):
313 filename = g_data.get_session_path(self.session_name)+data+'.ardour'
315 self.sendLine(str(os.stat(filename).st_size))
317 self.file = open(filename, 'r')
318 file_sender = FileSender()
319 cb = file_sender.beginFileTransfer(self.file, self.transport)
320 cb.addCallback(self.file_done)
322 self.error("snapshot: " + data + " doesn't exist on server")
323 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
324 if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
325 filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
327 if self.state == "SOUNDFILE":
328 self.sendLine(str(os.stat(filename).st_size))
329 else: #SOUNDFILE_HEADER
330 header_size = get_header_size(filename)
332 self.sendLine(str(header_size))
334 self.error('soundfile: ' + data + 'doesn\'t have "data" chunk')
336 self.file = open(filename, 'r')
337 if self.state == "SOUNDFILE":
338 file_sender = FileSender()
339 cb = file_sender.beginFileTransfer(self.file, self.transport)
340 else: # SOUNDFILE_HEADER
341 file_sender = FileSenderLimited()
342 cb = file_sender.beginFileTransfer(self.file, self.transport, header_size)
343 cb.addCallback(self.file_done)
345 self.error("soundfile: " + data + "doesn't exist on server")
346 elif self.state == "SOUNDFILE_SIZE":
347 if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
348 filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
350 self.sendLine(str(os.stat(filename).st_size))
352 elif data == "SESSION":
353 self.state = "SESSION"
354 elif data == "SNAPS":
356 for snap in g_data.get_snaps(self.session_name, g_data.get_user()):
360 elif data == "SNAPSHOT":
361 self.state = "SNAPSHOT"
362 elif data == "SOUNDFILE":
363 self.state = "SOUNDFILE"
364 elif data == "SOUNDFILE_HEADER":
365 self.state = "SOUNDFILE_HEADER"
366 elif data == "SOUNDFILE_SIZE":
367 self.state = "SOUNDFILE_SIZE"
369 def file_done(self, data):
370 print "server: file done"
374 class ExchangeServerFactory(protocol.ServerFactory):
375 protocol = ExchangeServer
380 class ExchangeClient (LineReceiver):
381 def __init__(self, session_name, collab_name, snap_name, debug_mode):
382 self.session_name = session_name
383 self.collab_name = collab_name
384 self.snap_name = snap_name
385 self.debug_mode = debug_mode
388 def connectionLost(self, reason):
389 g_display.show_status("Connection lost")
391 def connectionMade(self):
392 g_display.show_status("Connection made")
393 self.state = "SESSION"
394 self.sendLine("SESSION")
395 self.sendLine(self.session_name)
397 def rawDataReceived(self, data):
398 self.file.write(data)
399 self.received += len(data)
400 print self.received, self.filesize
401 if self.received >= self.filesize:
404 g_data.rescan_session(self.session_name)
405 if self.state == "SNAPSHOT":
406 self.sounds = get_sound_list(self.filename)
410 self.state = "SOUNDFILE_HEADER"
411 self.sendLine("SOUNDFILE_HEADER")
413 self.state = "SOUNDFILE"
414 self.sendLine("SOUNDFILE")
415 self.sendLine(self.sounds[self.sound_index])
417 self.transport.loseConnection()
418 elif self.state == "SOUNDFILE":
419 self.sound_index += 1
420 if self.sound_index > len(self.sounds)-1:
421 self.transport.loseConnection()
423 self.sendLine("SOUNDFILE")
424 self.sendLine(self.sounds[self.sound_index])
425 elif self.state == "SOUNDFILE_HEADER":
426 self.state = "SOUNDFILE_SIZE"
427 self.sendLine("SOUNDFILE_SIZE")
428 self.sendLine(self.sounds[self.sound_index])
430 def lineReceived(self, data):
431 print "client: ", data
436 if self.state == "SESSION":
438 self.state = "SNAPSHOT"
439 self.sendLine("SNAPSHOT")
440 self.sendLine(self.snap_name)
443 self.sendLine("SNAPS")
444 elif self.state == "SNAPS":
445 self.transport.loseConnection()
446 elif self.state == "SNAPSHOT":
448 self.filename = g_data.get_session_path(self.session_name)+'/'+self.snap_name+'.ardour'
449 self.file = open(self.filename, 'w')
451 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
453 self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index]
454 self.file = open(self.filename, 'w')
456 elif self.state == "ERROR":
457 raise_error(data, g_display.window)
458 elif self.state == "SNAPS":
459 g_data.add_snap(self.session_name, self.collab_name, data)
460 elif self.state == "SNAPSHOT":
461 self.filesize = int(data)
462 elif self.state == "SOUNDFILE":
463 self.filesize = int(data)
464 elif self.state == "SOUNDFILE_HEADER":
465 self.filesize = int(data)
466 elif self.state == "SOUNDFILE_SIZE":
467 append_empty_data(self.filename, int(data))
468 self.sound_index += 1
469 if self.sound_index > len(self.sounds)-1:
470 self.transport.loseConnection()
472 self.state = "SOUNDFILE_HEADER"
473 self.sendLine("SOUNDFILE_HEADER")
474 self.sendLine(self.sounds[self.sound_index])
476 class ExchangeClientFactory(protocol.ClientFactory):
477 def buildProtocol(self, addr):
478 return ExchangeClient(self.session_name, self.collab_name, self.snap_name, self.debug_mode)
480 def clientConnectionFailed(self, connector, reason):
481 raise_error('Connection failed: ' + reason.getErrorMessage(), g_display.window)
482 g_display.show_status('Connection failed')
484 def __init__(self, session_name, collab_name, snap_name, debug_mode):
485 self.session_name = session_name
486 self.collab_name = collab_name
487 self.snap_name = snap_name
488 self.debug_mode = debug_mode
490 class HelperWin(object):
491 def delete_me(self, window):
494 class Preferences(HelperWin):
496 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
497 self.window.set_title('Preferences')
498 self.window.connect('destroy', self.delete_me)
499 self.window.set_position(gtk.WIN_POS_MOUSE)
501 main_box = gtk.VBox()
502 self.window.add(main_box)
505 label1 = gtk.Label("User")
506 self.user = gtk.Entry()
507 self.user.set_text(g_data.get_user())
508 hbox1.pack_start(label1)
509 hbox1.pack_start(self.user)
510 main_box.pack_start(hbox1)
512 ok_btn = gtk.Button("Ok")
513 ok_btn.connect('clicked', self.ok_clicked)
514 main_box.pack_start(ok_btn)
516 self.window.show_all()
518 def ok_clicked(self, btn):
519 g_data.set_user(self.user.get_text())
520 self.window.hide_all()
523 self.window.show_all()
525 class AddCollaborator(HelperWin):
526 def __init__(self, session):
527 self.session_name = session
529 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
530 self.window.set_title('Fetch Session')
531 self.window.connect('destroy', self.delete_me)
532 self.window.set_position(gtk.WIN_POS_MOUSE)
534 main_box = gtk.VBox()
535 self.window.add(main_box)
538 label0 = gtk.Label("Collaborator")
539 self.collab = gtk.Entry()
540 self.collab.connect('key-release-event', self.key_press)
541 hbox0.pack_start(label0)
542 hbox0.pack_start(self.collab)
543 main_box.pack_start(hbox0)
546 label1 = gtk.Label("IP Address")
547 self.address = gtk.Entry()
548 self.address.connect('key-release-event', self.key_press)
549 hbox1.pack_start(label1)
550 hbox1.pack_start(self.address)
551 main_box.pack_start(hbox1)
554 label2 = gtk.Label("Port Number")
555 self.port = gtk.Entry()
556 self.port.connect('key-release-event', self.key_press)
557 self.port.set_text(str(g_data.port))
558 hbox2.pack_start(label2)
559 hbox2.pack_start(self.port)
560 main_box.pack_start(hbox2)
563 label3 = gtk.Label("Username")
564 label3.set_sensitive(False)
565 self.username = gtk.Entry()
566 self.username.set_sensitive(False)
567 hbox3.pack_start(label3)
568 hbox3.pack_start(self.username)
569 main_box.pack_start(hbox3)
572 label4 = gtk.Label("Password")
573 label4.set_sensitive(False)
574 self.password = gtk.Entry()
575 self.password.set_sensitive(False)
576 hbox4.pack_start(label4)
577 hbox4.pack_start(self.password)
578 main_box.pack_start(hbox4)
580 self.ok_btn = gtk.Button(gtk.STOCK_OK)
581 self.ok_btn.set_use_stock(True)
582 self.ok_btn.connect('clicked', self.ok_clicked)
583 self.ok_btn.set_sensitive(False)
584 main_box.pack_start(self.ok_btn)
586 self.window.show_all()
588 def key_press(self, event, data):
589 if self.collab.get_text() and self.address.get_text() and self.port.get_text():
590 self.ok_btn.set_sensitive(True)
592 self.ok_btn.set_sensitive(False)
595 def ok_clicked(self, btn):
596 self.window.hide_all()
597 g_data.add_collab(self.session_name, self.collab.get_text(), self.address.get_text(), int(self.port.get_text()))
598 self.collab.set_text('')
599 self.address.set_text('')
600 self.port.set_text('')
601 self.username.set_text('')
602 self.password.set_text('')
605 self.window.show_all()
607 class ArdourShareWindow(object):
608 def menuitem_cb(self, window, action, widget):
609 print self, window, action, widget
611 def add_collaborator_cb(self, window, action, widget):
613 self.add_session = AddCollaborator(self.session)
615 def fetch_snapshot_cb(self, window, action, widget):
616 if self.session and self.collab and self.collab != g_data.get_user():
617 client = ExchangeClientFactory(self.session, self.collab, self.snap, g_data.debug_mode)
618 reactor.connectTCP(g_data.get_collab_ip(self.session, self.collab), g_data.port, client)
620 def preferences_cb(self, window, action, widget):
621 self.preferences = Preferences()
623 def add_session_ok_file_btn_clicked(self, w):
624 filename = self.file_sel.get_filename()
625 if filename.endswith(".ardour"):
626 g_data.add_session(filename[0:filename.rfind("/")+1])
627 self.update_session_view()
629 raise_error("Not an Ardour session", self.window)
630 self.file_sel.destroy()
632 def add_session_cb(self, window, action, widget):
633 if g_data.get_user():
634 self.file_sel = gtk.FileSelection("Add Session...")
635 self.file_sel.ok_button.connect("clicked", self.add_session_ok_file_btn_clicked)
636 self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
637 self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
640 raise_error("Set the user name in the preferences first", self.window)
642 def create_session_cb(self, window, action, widget):
643 if g_data.get_user():
644 self.file_sel = gtk.FileSelection("Create Session...")
645 self.file_sel.ok_button.connect("clicked", self.create_file_ok_btn_clicked)
646 self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
647 self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
650 raise_error("Set the user name in the preferences first", self.window)
652 def create_file_ok_btn_clicked(self, w):
653 filename = self.file_sel.get_filename()
654 if len(filename) > 0:
655 g_data.create_session(filename)
656 self.update_session_view()
658 raise_error("Not an Ardour session", self.window)
659 self.file_sel.destroy()
661 def update_session_view(self):
662 self.session_model.clear()
663 for session in g_data.get_sessions():
664 self.session_model.set(self.session_model.append(), 0, session)
666 def update_collab_view(self):
667 self.collab_model.clear()
668 for collab in g_data.get_collabs(self.session):
669 self.collab_model.set(self.collab_model.append(), 0, collab)
671 def update_snap_view(self):
672 self.snap_model.clear()
673 for snap in g_data.get_snaps(self.session, self.collab):
674 self.snap_model.set(self.snap_model.append(), 0, snap)
676 def cb_session_selection_changed(self, selection_object):
678 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
680 self.session = self.session_model[x][0]
681 self.selected_type = "session"
682 self.update_collab_view()
684 def cb_collab_selection_changed(self, selection_object):
686 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
688 self.collab = self.collab_model[x][0]
689 self.selected_type = "collab"
690 self.update_snap_view()
692 def cb_snap_selection_changed(self, selection_object):
694 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
696 self.snap = self.snap_model[x][0]
697 self.selected_type = "snap"
699 def delete_cb(self, window, action, widget):
700 if self.selected_type == "session":
701 g_data.delete_session(self.session)
705 elif self.selected_type == "collab":
706 g_data.delete_collab(self.session, self.collab)
709 elif self.selected_type == "snap":
710 g_data.delete_snap(self.session, self.collab, self.snap)
713 self.update_session_view()
714 self.update_collab_view()
715 self.update_snap_view()
716 self.selected_type = ""
718 def show_status(self, text):
719 mid = self.status_bar.push(self._status_cid, text)
721 self.status_bar.remove(self._status_cid, self._status_mid)
722 self._status_mid = mid
725 self.selected_type = ""
727 self.collab = g_data.get_user()
734 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
735 self.window.set_title('Session Exchange')
736 self.window.set_size_request(400, 200)
737 self.window.connect('destroy', lambda win: gtk.main_quit())
738 self.window.set_position(gtk.WIN_POS_MOUSE)
740 accel_group = gtk.AccelGroup()
741 self.window.add_accel_group(accel_group)
743 main_box = gtk.VBox()
744 self.window.add(main_box)
747 ('/_File', None, None, 0, '<Branch>'),
748 ('/File/_Add Session...','<control>A', self.add_session_cb, 0, ''),
749 ('/File/Create _Session...', '<control>S', self.create_session_cb, 0, ''),
750 ('/File/sep1', None, None, 0, '<Separator>'),
751 ('/File/_Quit', '<control>Q', gtk.main_quit, 0, '<StockItem>', gtk.STOCK_QUIT),
752 ('/_Edit', None, None, 0, '<Branch>' ),
753 ('/Edit/Cu_t', '<control>X', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_CUT),
754 ('/Edit/_Copy', '<control>C', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_COPY),
755 ('/Edit/_Paste', '<control>V', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_PASTE),
756 ('/Edit/_Delete', None, self.delete_cb, 0, '<StockItem>', gtk.STOCK_DELETE),
757 ('/Edit/sep1', None, None, 0, '<Separator>'),
758 ('/Edit/Add Colla_borator...','<control>B', self.add_collaborator_cb,0,''),
759 ('/Edit/_Fetch Snapshot','<control>F', self.fetch_snapshot_cb,0,''),
760 ('/Edit/sep1', None, None, 0, '<Separator>'),
761 ('/Edit/_Preferences...','<control>P', self.preferences_cb, 0, '')
764 #need to hold a reference to the item_factory or the menubar will disappear.
765 self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group)
766 self.item_factory.create_items(menu_items, self.window)
767 main_box.pack_start(self.item_factory.get_widget('<main>'), False)
771 pane1.pack2(pane2, True, False)
773 scroll1 = gtk.ScrolledWindow()
774 scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
775 pane1.pack1(scroll1, True, False)
776 scroll2 = gtk.ScrolledWindow()
777 scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
778 pane2.pack1(scroll2, True, False)
779 scroll3 = gtk.ScrolledWindow()
780 scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
781 pane2.pack2(scroll3, True, False)
783 self.session_model = gtk.ListStore(gobject.TYPE_STRING)
784 view1 = gtk.TreeView(self.session_model)
785 column1 = gtk.TreeViewColumn('Sessions', gtk.CellRendererText(), text=0)
786 view1.append_column(column1)
787 self.session_selection = view1.get_selection()
788 self.session_selection.connect("changed", self.cb_session_selection_changed)
791 self.update_session_view()
793 self.collab_model = gtk.ListStore(gobject.TYPE_STRING)
794 view2 = gtk.TreeView(self.collab_model)
795 column2 = gtk.TreeViewColumn('Collaborators', gtk.CellRendererText(), text=0)
796 view2.append_column(column2)
797 self.collab_selection = view2.get_selection()
798 self.collab_selection.connect("changed", self.cb_collab_selection_changed)
801 self.snap_model = gtk.ListStore(gobject.TYPE_STRING)
802 view3 = gtk.TreeView(self.snap_model)
803 column3 = gtk.TreeViewColumn('Snapshots', gtk.CellRendererText(), text=0)
804 view3.append_column(column3)
805 self.snap_selection = view3.get_selection()
806 self.snap_selection.connect("changed", self.cb_snap_selection_changed)
809 main_box.pack_start(pane1, True, True)
811 self.status_bar = gtk.Statusbar()
812 main_box.pack_start(self.status_bar, False)
813 self._status_cid = self.status_bar.get_context_id('display')
814 self._status_mid = ''
816 self.window.show_all()
821 -n, --no-server Only act as a client
822 -p, --port <port number> Defaults to 8970
823 -d, --debug Infers audio files. For debugging Ardour.
824 -v, --version Version
830 opts, args = getopt.getopt(sys.argv[1:], "hp:ndv", ["help", "port=", "no-server", "debug", "version"])
831 except getopt.GetoptError:
836 if o in ("-h", "--help"):
838 if o in ("-d", "--debug"):
839 g_display.window.set_title('Session Exchange: Debug Mode')
840 g_data.debug_mode = True
841 if o in ("-p", "--port"):
843 if o in ("-n", "--no-server"):
845 if o in ("-v", "--version"):
851 reactor.listenTCP(g_data.port, ExchangeServerFactory())
852 except twisted.internet.error.CannotListenError:
853 print "Can not listen on a port number under 1024 unless run as root"
862 g_display = ArdourShareWindow()
864 if __name__ == '__main__':