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 self._data['sessions'] = sessions
116 client = ExchangeClientFactory(session_name, collab_name, None, self.debug_mode)
117 reactor.connectTCP(ip_address, port, client)
118 g_display.show_status("connecting")
120 g_display.update_collab_view()
122 def add_session(self, session_path):
123 sessions = self._data['sessions']
125 session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1]
126 sessions[session_name] = {}
127 sessions[session_name]['path'] = session_path
128 sessions[session_name]['collabs'] = {}
129 sessions[session_name]['collabs'][self._data['user']] = {}
130 sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
131 sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
133 self._data['sessions'] = sessions
135 self.rescan_session(session_name)
137 def rescan_session(self, session_name):
138 sessions = self._data['sessions']
140 session_path = sessions[session_name]['path']
141 sessions[session_name]['collabs'][self._data['user']]['snaps'] = self._scan_snapshots(session_path)
142 sessions[session_name]['collabs'][self._data['user']]['sounds'] = self._scan_sounds(session_path)
144 self._data['sessions'] = sessions
146 g_display.update_snap_view()
148 print self._data['sessions']
150 def create_session(self, session_path):
152 os.mkdir(session_path)
153 os.mkdir(session_path+"/sounds")
155 raise_error("Could not create session directory", g_display.window)
158 sessions = self._data['sessions']
160 session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ]
161 sessions[session_name] = {}
162 sessions[session_name]['path'] = session_path
163 sessions[session_name]['collabs'] = {}
164 sessions[session_name]['collabs'][self._data['user']] = {}
165 sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
166 sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
168 self._data['sessions'] = sessions
169 print self._data['sessions']
171 def get_session_path(self, session):
172 sessions = self._data['sessions']
173 return sessions[session]['path']
176 return self._data['user']
178 def set_user(self, username):
179 self._data['user'] = username
181 def get_collab_ip(self, session, collab):
182 sessions = self._data['sessions']
183 return sessions[session]['collabs'][collab]['ip']
188 def get_sessions(self):
189 sessions = self._data['sessions']
190 sess = sessions.keys()
194 def get_collabs(self, session):
196 sessions = self._data['sessions']
197 collabs = sessions[session]['collabs'].keys()
203 def get_snaps(self, session, collab):
204 if session and collab:
205 sessions = self._data['sessions']
206 snaps = sessions[session]['collabs'][collab]['snaps']
212 def get_sounds(self, session, collab):
213 if session and collab:
214 sessions = self._data['sessions']
215 sounds = sessions[session]['collabs'][self._data['user']]['sounds']
221 def _scan_snapshots(self, session):
223 files = os.listdir(session)
224 pattern = re.compile(r'\.ardour$')
226 if pattern.search(file):
227 snaps.append(file[0:-7])
231 def _scan_sounds(self, session):
233 files = os.listdir(session+'/sounds')
234 pattern = re.compile(r'\.peak$')
236 if not pattern.search(file):
240 def __init__(self, *args):
241 self._data = shelve.open(os.path.expanduser('~/.session_exchange'), 'c')
243 self.debug_mode = False
244 if len(self._data.keys()) < 1:
245 self._data['sessions'] = {}
246 self._data['user'] = ''
250 from twisted.protocols.basic import FileSender
251 class FileSenderLimited(FileSender):
252 def beginFileTransfer(self, file, consumer, limit, transform = None):
254 self.consumer = consumer
255 self.CHUNK_SIZE = limit
256 self.transform = transform
258 self.consumer.registerProducer(self, False)
259 self.deferred = defer.Deferred()
262 def resumeProducing(self):
264 chunk = self.file.read(self.CHUNK_SIZE)
267 chunk = self.transform(chunk)
269 self.consumer.write(chunk)
270 self.lastSent = chunk[-1]
272 self.consumer.unregisterProducer()
273 self.deferred.callback(self.lastSent)
276 from twisted.protocols.basic import LineReceiver
277 class ExchangeServer (LineReceiver):
281 def error(self, message):
282 self.sendLine("ERROR")
283 self.sendLine(message)
284 self.transport.loseConnection()
286 def connectionLost(self, reason):
287 print "server: connection lost: ", reason
289 def connectionMade(self):
290 print "server: connection made"
292 def lineReceived(self, data):
293 print "server: ", data
295 if self.state == "SESSION":
296 if g_data.get_sessions().count(data):
297 self.session_name = data
301 self.error(data + " doesn't exist on server")
302 elif self.state == "SNAPSHOT":
303 if g_data.get_snaps(self.session_name, g_data.get_user()).count(data):
304 filename = g_data.get_session_path(self.session_name)+data+'.ardour'
306 self.sendLine(str(os.stat(filename).st_size))
308 self.file = open(filename, 'r')
309 file_sender = FileSender()
310 cb = file_sender.beginFileTransfer(self.file, self.transport)
311 cb.addCallback(self.file_done)
313 self.error("snapshot: " + data + " doesn't exist on server")
314 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
315 if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
316 filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
318 if self.state == "SOUNDFILE":
319 self.sendLine(str(os.stat(filename).st_size))
320 else: #SOUNDFILE_HEADER
321 header_size = get_header_size(filename)
323 self.sendLine(str(header_size))
325 self.error('soundfile: ' + data + 'doesn\'t have "data" chunk')
327 self.file = open(filename, 'r')
328 if self.state == "SOUNDFILE":
329 file_sender = FileSender()
330 cb = file_sender.beginFileTransfer(self.file, self.transport)
331 else: # SOUNDFILE_HEADER
332 file_sender = FileSenderLimited()
333 cb = file_sender.beginFileTransfer(self.file, self.transport, header_size)
334 cb.addCallback(self.file_done)
336 self.error("soundfile: " + data + "doesn't exist on server")
337 elif self.state == "SOUNDFILE_SIZE":
338 if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
339 filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
341 self.sendLine(str(os.stat(filename).st_size))
343 elif data == "SESSION":
344 self.state = "SESSION"
345 elif data == "SNAPS":
347 for snap in g_data.get_snaps(self.session_name, g_data.get_user()):
351 elif data == "SNAPSHOT":
352 self.state = "SNAPSHOT"
353 elif data == "SOUNDFILE":
354 self.state = "SOUNDFILE"
355 elif data == "SOUNDFILE_HEADER":
356 self.state = "SOUNDFILE_HEADER"
357 elif data == "SOUNDFILE_SIZE":
358 self.state = "SOUNDFILE_SIZE"
360 def file_done(self, data):
361 print "server: file done"
365 class ExchangeServerFactory(protocol.ServerFactory):
366 protocol = ExchangeServer
371 class ExchangeClient (LineReceiver):
372 def __init__(self, session_name, collab_name, snap_name, debug_mode):
373 self.session_name = session_name
374 self.collab_name = collab_name
375 self.snap_name = snap_name
376 self.debug_mode = debug_mode
379 def connectionLost(self, reason):
380 g_display.show_status("Connection lost")
382 def connectionMade(self):
383 g_display.show_status("Connection made")
384 self.state = "SESSION"
385 self.sendLine("SESSION")
386 self.sendLine(self.session_name)
388 def rawDataReceived(self, data):
389 self.file.write(data)
390 self.received += len(data)
391 print self.received, self.filesize
392 if self.received >= self.filesize:
395 g_data.rescan_session(self.session_name)
396 if self.state == "SNAPSHOT":
397 self.sounds = get_sound_list(self.filename)
401 self.state = "SOUNDFILE_HEADER"
402 self.sendLine("SOUNDFILE_HEADER")
404 self.state = "SOUNDFILE"
405 self.sendLine("SOUNDFILE")
406 self.sendLine(self.sounds[self.sound_index])
408 self.transport.loseConnection()
409 elif self.state == "SOUNDFILE":
410 self.sound_index += 1
411 if self.sound_index > len(self.sounds)-1:
412 self.transport.loseConnection()
414 self.sendLine("SOUNDFILE")
415 self.sendLine(self.sounds[self.sound_index])
416 elif self.state == "SOUNDFILE_HEADER":
417 self.state = "SOUNDFILE_SIZE"
418 self.sendLine("SOUNDFILE_SIZE")
419 self.sendLine(self.sounds[self.sound_index])
421 def lineReceived(self, data):
422 print "client: ", data
427 if self.state == "SESSION":
429 self.state = "SNAPSHOT"
430 self.sendLine("SNAPSHOT")
431 self.sendLine(self.snap_name)
434 self.sendLine("SNAPS")
435 elif self.state == "SNAPS":
436 self.transport.loseConnection()
437 elif self.state == "SNAPSHOT":
439 self.filename = g_data.get_session_path(self.session_name)+'/'+self.snap_name+'.ardour'
440 self.file = open(self.filename, 'w')
442 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
444 self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index]
445 self.file = open(self.filename, 'w')
447 elif self.state == "ERROR":
448 raise_error(data, g_display.window)
449 elif self.state == "SNAPS":
450 g_data.add_snap(self.session_name, self.collab_name, data)
451 elif self.state == "SNAPSHOT":
452 self.filesize = int(data)
453 elif self.state == "SOUNDFILE":
454 self.filesize = int(data)
455 elif self.state == "SOUNDFILE_HEADER":
456 self.filesize = int(data)
457 elif self.state == "SOUNDFILE_SIZE":
458 append_empty_data(self.filename, int(data))
459 self.sound_index += 1
460 if self.sound_index > len(self.sounds)-1:
461 self.transport.loseConnection()
463 self.state = "SOUNDFILE_HEADER"
464 self.sendLine("SOUNDFILE_HEADER")
465 self.sendLine(self.sounds[self.sound_index])
467 class ExchangeClientFactory(protocol.ClientFactory):
468 def buildProtocol(self, addr):
469 return ExchangeClient(self.session_name, self.collab_name, self.snap_name, self.debug_mode)
471 def clientConnectionFailed(self, connector, reason):
472 raise_error('Connection failed: ' + reason.getErrorMessage(), g_display.window)
473 g_display.show_status('Connection failed')
475 def __init__(self, session_name, collab_name, snap_name, debug_mode):
476 self.session_name = session_name
477 self.collab_name = collab_name
478 self.snap_name = snap_name
479 self.debug_mode = debug_mode
481 class HelperWin(object):
482 def delete_me(self, window):
485 class Preferences(HelperWin):
487 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
488 self.window.set_title('Preferences')
489 self.window.connect('destroy', self.delete_me)
490 self.window.set_position(gtk.WIN_POS_MOUSE)
492 main_box = gtk.VBox()
493 self.window.add(main_box)
496 label1 = gtk.Label("User")
497 self.user = gtk.Entry()
498 self.user.set_text(g_data.get_user())
499 hbox1.pack_start(label1)
500 hbox1.pack_start(self.user)
501 main_box.pack_start(hbox1)
503 ok_btn = gtk.Button("Ok")
504 ok_btn.connect('clicked', self.ok_clicked)
505 main_box.pack_start(ok_btn)
507 self.window.show_all()
509 def ok_clicked(self, btn):
510 g_data.set_user(self.user.get_text())
511 self.window.hide_all()
514 self.window.show_all()
516 class AddCollaborator(HelperWin):
517 def __init__(self, session):
518 self.session_name = session
520 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
521 self.window.set_title('Fetch Session')
522 self.window.connect('destroy', self.delete_me)
523 self.window.set_position(gtk.WIN_POS_MOUSE)
525 main_box = gtk.VBox()
526 self.window.add(main_box)
529 label0 = gtk.Label("Collaborator")
530 self.collab = gtk.Entry()
531 self.collab.connect('key-release-event', self.key_press)
532 hbox0.pack_start(label0)
533 hbox0.pack_start(self.collab)
534 main_box.pack_start(hbox0)
537 label1 = gtk.Label("IP Address")
538 self.address = gtk.Entry()
539 self.address.connect('key-release-event', self.key_press)
540 hbox1.pack_start(label1)
541 hbox1.pack_start(self.address)
542 main_box.pack_start(hbox1)
545 label2 = gtk.Label("Port Number")
546 self.port = gtk.Entry()
547 self.port.connect('key-release-event', self.key_press)
548 self.port.set_text(str(g_data.port))
549 hbox2.pack_start(label2)
550 hbox2.pack_start(self.port)
551 main_box.pack_start(hbox2)
554 label3 = gtk.Label("Username")
555 label3.set_sensitive(False)
556 self.username = gtk.Entry()
557 self.username.set_sensitive(False)
558 hbox3.pack_start(label3)
559 hbox3.pack_start(self.username)
560 main_box.pack_start(hbox3)
563 label4 = gtk.Label("Password")
564 label4.set_sensitive(False)
565 self.password = gtk.Entry()
566 self.password.set_sensitive(False)
567 hbox4.pack_start(label4)
568 hbox4.pack_start(self.password)
569 main_box.pack_start(hbox4)
571 self.ok_btn = gtk.Button(gtk.STOCK_OK)
572 self.ok_btn.set_use_stock(True)
573 self.ok_btn.connect('clicked', self.ok_clicked)
574 self.ok_btn.set_sensitive(False)
575 main_box.pack_start(self.ok_btn)
577 self.window.show_all()
579 def key_press(self, event, data):
580 if self.collab.get_text() and self.address.get_text() and self.port.get_text():
581 self.ok_btn.set_sensitive(True)
583 self.ok_btn.set_sensitive(False)
586 def ok_clicked(self, btn):
587 self.window.hide_all()
588 g_data.add_collab(self.session_name, self.collab.get_text(), self.address.get_text(), int(self.port.get_text()))
589 self.collab.set_text('')
590 self.address.set_text('')
591 self.port.set_text('')
592 self.username.set_text('')
593 self.password.set_text('')
596 self.window.show_all()
598 class ArdourShareWindow(object):
599 def menuitem_cb(self, window, action, widget):
600 print self, window, action, widget
602 def add_collaborator_cb(self, window, action, widget):
604 self.add_session = AddCollaborator(self.session)
606 def fetch_snapshot_cb(self, window, action, widget):
607 if self.session and self.collab and self.collab != g_data.get_user():
608 client = ExchangeClientFactory(self.session, self.collab, self.snap, g_data.debug_mode)
609 reactor.connectTCP(g_data.get_collab_ip(self.session, self.collab), g_data.port, client)
611 def preferences_cb(self, window, action, widget):
612 self.preferences = Preferences()
614 def add_session_ok_file_btn_clicked(self, w):
615 filename = self.file_sel.get_filename()
616 if filename.endswith(".ardour"):
617 g_data.add_session(filename[0:filename.rfind("/")+1])
618 self.update_session_view()
620 raise_error("Not an Ardour session", self.window)
621 self.file_sel.destroy()
623 def add_session_cb(self, window, action, widget):
624 if g_data.get_user():
625 self.file_sel = gtk.FileSelection("Add Session...")
626 self.file_sel.ok_button.connect("clicked", self.add_session_ok_file_btn_clicked)
627 self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
628 self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
631 raise_error("Set the user name in the preferences first", self.window)
633 def create_session_cb(self, window, action, widget):
634 if g_data.get_user():
635 self.file_sel = gtk.FileSelection("Create Session...")
636 self.file_sel.ok_button.connect("clicked", self.create_file_ok_btn_clicked)
637 self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
638 self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
641 raise_error("Set the user name in the preferences first", self.window)
643 def create_file_ok_btn_clicked(self, w):
644 filename = self.file_sel.get_filename()
645 if len(filename) > 0:
646 g_data.create_session(filename)
647 self.update_session_view()
649 raise_error("Not an Ardour session", self.window)
650 self.file_sel.destroy()
652 def update_session_view(self):
653 self.session_model.clear()
654 for session in g_data.get_sessions():
655 self.session_model.set(self.session_model.append(), 0, session)
657 def update_collab_view(self):
658 self.collab_model.clear()
659 for collab in g_data.get_collabs(self.session):
660 self.collab_model.set(self.collab_model.append(), 0, collab)
662 def update_snap_view(self):
663 self.snap_model.clear()
664 for snap in g_data.get_snaps(self.session, self.collab):
665 self.snap_model.set(self.snap_model.append(), 0, snap)
667 def cb_session_selection_changed(self, selection_object):
669 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
671 self.session = self.session_model[x][0]
672 self.selected_type = "session"
673 self.update_collab_view()
675 def cb_collab_selection_changed(self, selection_object):
677 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
679 self.collab = self.collab_model[x][0]
680 self.selected_type = "collab"
681 self.update_snap_view()
683 def cb_snap_selection_changed(self, selection_object):
685 selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
687 self.snap = self.snap_model[x][0]
688 self.selected_type = "snap"
690 def delete_cb(self, window, action, widget):
691 if self.selected_type == "session":
692 g_data.delete_session(self.session)
696 elif self.selected_type == "collab":
697 g_data.delete_collab(self.session, self.collab)
700 elif self.selected_type == "snap":
701 g_data.delete_snap(self.session, self.collab, self.snap)
704 self.update_session_view()
705 self.update_collab_view()
706 self.update_snap_view()
707 self.selected_type = ""
709 def show_status(self, text):
710 mid = self.status_bar.push(self._status_cid, text)
712 self.status_bar.remove(self._status_cid, self._status_mid)
713 self._status_mid = mid
716 self.selected_type = ""
718 self.collab = g_data.get_user()
725 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
726 self.window.set_title('Session Exchange')
727 self.window.set_size_request(400, 200)
728 self.window.connect('destroy', lambda win: gtk.main_quit())
729 self.window.set_position(gtk.WIN_POS_MOUSE)
731 accel_group = gtk.AccelGroup()
732 self.window.add_accel_group(accel_group)
734 main_box = gtk.VBox()
735 self.window.add(main_box)
738 ('/_File', None, None, 0, '<Branch>'),
739 ('/File/_Add Session...','<control>A', self.add_session_cb, 0, ''),
740 ('/File/Create _Session...', '<control>S', self.create_session_cb, 0, ''),
741 ('/File/sep1', None, None, 0, '<Separator>'),
742 ('/File/_Quit', '<control>Q', gtk.main_quit, 0, '<StockItem>', gtk.STOCK_QUIT),
743 ('/_Edit', None, None, 0, '<Branch>' ),
744 ('/Edit/Cu_t', '<control>X', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_CUT),
745 ('/Edit/_Copy', '<control>C', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_COPY),
746 ('/Edit/_Paste', '<control>V', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_PASTE),
747 ('/Edit/_Delete', None, self.delete_cb, 0, '<StockItem>', gtk.STOCK_DELETE),
748 ('/Edit/sep1', None, None, 0, '<Separator>'),
749 ('/Edit/Add Colla_borator...','<control>B', self.add_collaborator_cb,0,''),
750 ('/Edit/_Fetch Snapshot','<control>F', self.fetch_snapshot_cb,0,''),
751 ('/Edit/sep1', None, None, 0, '<Separator>'),
752 ('/Edit/_Preferences...','<control>P', self.preferences_cb, 0, '')
755 #need to hold a reference to the item_factory or the menubar will disappear.
756 self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group)
757 self.item_factory.create_items(menu_items, self.window)
758 main_box.pack_start(self.item_factory.get_widget('<main>'), gtk.FALSE)
762 pane1.pack2(pane2, gtk.TRUE, gtk.FALSE)
764 scroll1 = gtk.ScrolledWindow()
765 scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
766 pane1.pack1(scroll1, gtk.TRUE, gtk.FALSE)
767 scroll2 = gtk.ScrolledWindow()
768 scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
769 pane2.pack1(scroll2, gtk.TRUE, gtk.FALSE)
770 scroll3 = gtk.ScrolledWindow()
771 scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
772 pane2.pack2(scroll3, gtk.TRUE, gtk.FALSE)
774 self.session_model = gtk.ListStore(gobject.TYPE_STRING)
775 view1 = gtk.TreeView(self.session_model)
776 column1 = gtk.TreeViewColumn('Sessions', gtk.CellRendererText(), text=0)
777 view1.append_column(column1)
778 self.session_selection = view1.get_selection()
779 self.session_selection.connect("changed", self.cb_session_selection_changed)
782 self.update_session_view()
784 self.collab_model = gtk.ListStore(gobject.TYPE_STRING)
785 view2 = gtk.TreeView(self.collab_model)
786 column2 = gtk.TreeViewColumn('Collaborators', gtk.CellRendererText(), text=0)
787 view2.append_column(column2)
788 self.collab_selection = view2.get_selection()
789 self.collab_selection.connect("changed", self.cb_collab_selection_changed)
792 self.snap_model = gtk.ListStore(gobject.TYPE_STRING)
793 view3 = gtk.TreeView(self.snap_model)
794 column3 = gtk.TreeViewColumn('Snapshots', gtk.CellRendererText(), text=0)
795 view3.append_column(column3)
796 self.snap_selection = view3.get_selection()
797 self.snap_selection.connect("changed", self.cb_snap_selection_changed)
800 main_box.pack_start(pane1, gtk.TRUE, gtk.TRUE)
802 self.status_bar = gtk.Statusbar()
803 main_box.pack_start(self.status_bar, gtk.FALSE)
804 self._status_cid = self.status_bar.get_context_id('display')
805 self._status_mid = ''
807 self.window.show_all()
812 -n, --no-server Only act as a client
813 -p, --port <port number> Defaults to 8970
814 -d, --debug Infers audio files. For debugging Ardour.
815 -v, --version Version
821 opts, args = getopt.getopt(sys.argv[1:], "hp:ndv", ["help", "port=", "no-server", "debug", "version"])
822 except getopt.GetoptError:
827 if o in ("-h", "--help"):
829 if o in ("-d", "--debug"):
830 g_display.window.set_title('Session Exchange: Debug Mode')
831 g_data.debug_mode = True
832 if o in ("-p", "--port"):
834 if o in ("-n", "--no-server"):
836 if o in ("-v", "--version"):
842 reactor.listenTCP(g_data.port, ExchangeServerFactory())
843 except twisted.internet.error.CannotListenError:
844 print "Can not listen on a port number under 1024 unless run as root"
853 g_display = ArdourShareWindow()
855 if __name__ == '__main__':