View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002700 | ardour | bugs | public | 2009-05-27 19:28 | 2010-04-24 10:31 |
Reporter | zorgzorg2 | Assigned To | |||
Priority | normal | Severity | major | Reproducibility | always |
Status | new | Resolution | open | ||
Summary | 0002700: ardour2-session-exchange crashes of session retrieval | ||||
Description | ardour2-session-exchange crashes of session retrieval. It appears several parts of the code were outdated and/or buggy | ||||
Additional Information | Here is a patch that seems to work for me. | ||||
Tags | No tags attached. | ||||
2009-05-27 19:28
|
ardour2-session-exchange.patch (8,571 bytes)
--- /usr/bin/ardour2-session_exchange.py 2009-04-19 19:45:31.000000000 +0200 +++ exchange.py 2009-05-27 21:25:43.000000000 +0200 @@ -3,7 +3,7 @@ # Session Exchange # By Taybin Rutkin # Copyright 2004, under the GPL - +# Modified by Martin Raspaud, 2009 VERSION='0.1.1' #twisted libraries @@ -61,6 +61,16 @@ dialog.run() dialog.destroy() +def session_name_from_path(session_path): + if session_path[len(session_path)-1] == '/': + return session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1] + else: + return session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ] + + + +# Generic data object for the session exchange +# contains sessions, collabs, and snapshots class Data(object): def delete_snap(self, session, collab, snap): sessions = self._data['sessions'] @@ -100,10 +110,13 @@ g_display.update_collab_view() + + # adds a session to the list def add_session(self, session_path): sessions = self._data['sessions'] - session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1] + session_name = session_name_from_path(session_path) + #session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1] sessions[session_name] = {} sessions[session_name]['path'] = session_path sessions[session_name]['collabs'] = {} @@ -131,14 +144,16 @@ def create_session(self, session_path): try: os.mkdir(session_path) - os.mkdir(session_path+"/sounds") + session_name = session_name_from_path(session_path) + #session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ] + audiofiles_path = session_path+'/interchange/'+session_name+'/audiofiles' + os.makedirs(audiofiles_path) except OSError: raise_error("Could not create session directory", g_display.window) return sessions = self._data['sessions'] - session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ] sessions[session_name] = {} sessions[session_name]['path'] = session_path sessions[session_name]['collabs'] = {} @@ -209,9 +224,11 @@ print file[0:-7] return snaps - def _scan_sounds(self, session): + + def _scan_sounds(self, session_path): sounds = [] - files = os.listdir(session+'/sounds') + session_name = session_name_from_path(session_path) + files = os.listdir(session_path+'/interchange/'+session_name+'/audiofiles') pattern = re.compile(r'\.peak$') for file in files: if not pattern.search(file): @@ -237,7 +254,8 @@ self.transform = transform self.consumer.registerProducer(self, False) - self.deferred = defer.Deferred() + if not self.deferred: + self.deferred = twisted.internet.defer.Deferred() return self.deferred def resumeProducing(self): @@ -251,6 +269,8 @@ self.lastSent = chunk[-1] self.file = None self.consumer.unregisterProducer() + if not self.deferred: + self.deferred = twisted.internet.defer.Deferred() self.deferred.callback(self.lastSent) self.deferred = None @@ -271,8 +291,7 @@ print "server: connection made" def lineReceived(self, data): - print "server: ", data - + print "server: '"+ data +"'" if self.state == "SESSION": if g_data.get_sessions().count(data): self.session_name = data @@ -283,7 +302,6 @@ elif self.state == "SNAPSHOT": if g_data.get_snaps(self.session_name, g_data.get_user()).count(data): filename = g_data.get_session_path(self.session_name)+data+'.ardour' - print filename self.sendLine(str(os.stat(filename).st_size)) self.sendLine("OK") self.file = open(filename, 'r') @@ -294,8 +312,8 @@ self.error("snapshot: " + data + " doesn't exist on server") elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER": if g_data.get_sounds(self.session_name, g_data.get_user()).count(data): - filename = g_data.get_session_path(self.session_name)+"/sounds/"+data - print filename + #filename = g_data.get_session_path(self.session_name)+"/sounds/"+data + filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+data if self.state == "SOUNDFILE": self.sendLine(str(os.stat(filename).st_size)) else: #SOUNDFILE_HEADER @@ -313,12 +331,14 @@ file_sender = FileSenderLimited() cb = file_sender.beginFileTransfer(self.file, self.transport, header_size) cb.addCallback(self.file_done) + elif data == "SOUNDFILE_SIZE": + self.state = "SOUNDFILE_SIZE" else: - self.error("soundfile: " + data + "doesn't exist on server") + self.error("soundfile: " + data + " doesn't exist on server") elif self.state == "SOUNDFILE_SIZE": if g_data.get_sounds(self.session_name, g_data.get_user()).count(data): - filename = g_data.get_session_path(self.session_name)+"/sounds/"+data - print filename + #filename = g_data.get_session_path(self.session_name)+"/sounds/"+data + filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+data self.sendLine(str(os.stat(filename).st_size)) self.state = "IDLE" elif data == "SESSION": @@ -335,9 +355,7 @@ self.state = "SOUNDFILE" elif data == "SOUNDFILE_HEADER": self.state = "SOUNDFILE_HEADER" - elif data == "SOUNDFILE_SIZE": - self.state = "SOUNDFILE_SIZE" - + def file_done(self, data): print "server: file done" self.file.close() @@ -406,6 +424,7 @@ self.state = "ERROR" elif data == "OK": if self.state == "SESSION": + print "snap name ='"+self.snap_name+"'" if self.snap_name: self.state = "SNAPSHOT" self.sendLine("SNAPSHOT") @@ -422,7 +441,8 @@ self.received = 0 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER": self.setRawMode() - self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index] + #self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index] + self.filename = g_data.get_session_path(self.session_name)+'/interchange/'+self.session_name+'/audiofiles/'+self.sounds[self.sound_index] self.file = open(self.filename, 'w') self.received = 0 elif self.state == "ERROR": @@ -436,7 +456,8 @@ elif self.state == "SOUNDFILE_HEADER": self.filesize = int(data) elif self.state == "SOUNDFILE_SIZE": - append_empty_data(self.filename, int(data)) + print "SOUNDFILE_SIZE = " + data + append_empty_data(self,self.filename, int(data)) self.sound_index += 1 if self.sound_index > len(self.sounds)-1: self.transport.loseConnection() @@ -459,6 +480,8 @@ self.snap_name = snap_name self.debug_mode = debug_mode +# GUI stuff + class HelperWin(object): def delete_me(self, window): self = 0 @@ -574,6 +597,7 @@ def show_all(self): self.window.show_all() + class ArdourShareWindow(object): def menuitem_cb(self, window, action, widget): print self, window, action, widget @@ -733,21 +757,21 @@ #need to hold a reference to the item_factory or the menubar will disappear. self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group) self.item_factory.create_items(menu_items, self.window) - main_box.pack_start(self.item_factory.get_widget('<main>'), gtk.FALSE) + main_box.pack_start(self.item_factory.get_widget('<main>'), False) pane1 = gtk.HPaned() pane2 = gtk.HPaned() - pane1.pack2(pane2, gtk.TRUE, gtk.FALSE) + pane1.pack2(pane2, True, False) scroll1 = gtk.ScrolledWindow() scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - pane1.pack1(scroll1, gtk.TRUE, gtk.FALSE) + pane1.pack1(scroll1, True, False) scroll2 = gtk.ScrolledWindow() scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - pane2.pack1(scroll2, gtk.TRUE, gtk.FALSE) + pane2.pack1(scroll2, True, False) scroll3 = gtk.ScrolledWindow() scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - pane2.pack2(scroll3, gtk.TRUE, gtk.FALSE) + pane2.pack2(scroll3, True, False) self.session_model = gtk.ListStore(gobject.TYPE_STRING) view1 = gtk.TreeView(self.session_model) @@ -775,10 +799,10 @@ self.snap_selection.connect("changed", self.cb_snap_selection_changed) scroll3.add(view3) - main_box.pack_start(pane1, gtk.TRUE, gtk.TRUE) + main_box.pack_start(pane1, True, True) self.status_bar = gtk.Statusbar() - main_box.pack_start(self.status_bar, gtk.FALSE) + main_box.pack_start(self.status_bar, False) self._status_cid = self.status_bar.get_context_id('display') self._status_mid = '' |
2009-05-29 18:08
|
exchange2.py (27,437 bytes)
#! /usr/bin/python # Session Exchange # By Taybin Rutkin # Copyright 2004, under the GPL # Modified by Martin Raspaud, 2009 VERSION='0.1.1' #twisted libraries from twisted.internet import gtk2reactor gtk2reactor.install() from twisted.internet import reactor, protocol import twisted.internet.error #pygtk libraries import gobject import gtk #standard python2.2 libraries import getopt import os import os.path import re import shelve import string import sys import xml.dom.pulldom def get_header_size(filename): size = 0 file = open(filename, 'r') while True: chunk = file.read(4) size += 4 if chunk == "data": file.close() return size + 4 #include the size chunk after "data" if not chunk: file.close() return None def append_empty_data(self, filename, size): file = open(filename, 'a') file.seek(size-1) file.write('\x00') file.close() def get_sound_list(snapshot): doc = xml.dom.pulldom.parse(snapshot) seen = {} soundlist = [] for event, node in doc: if event=='START_ELEMENT' and node.nodeName=='Source': soundlist.append(str(node.getAttribute('name'))) return soundlist def raise_error(string, parent): dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, string) dialog.run() dialog.destroy() def session_name_from_path(session_path): if session_path[len(session_path)-1] == '/': return session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1] else: return session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ] # Generic data object for the session exchange # contains sessions, collabs, and snapshots class Data(object): def delete_snap(self, session, collab, snap): sessions = self._data['sessions'] sessions[session]['collabs'][collab]['snaps'].remove(snap) self._data['sessions'] = sessions def delete_collab(self,session, collab): sessions = self._data['sessions'] del sessions[session]['collabs'][collab] self._data['sessions'] = sessions def delete_session(self, session): sessions = self._data['sessions'] del sessions[session] self._data['sessions'] = sessions def add_snap(self, session_name, collab_name, snap_name): sessions = self._data['sessions'] sessions[session_name]['collabs'][collab_name]['snaps'].append(snap_name) sessions[session_name]['collabs'][collab_name]['snaps'].sort() self._data['sessions'] = sessions g_display.update_snap_view() def add_collab(self, session_name, collab_name, ip_address, port): sessions = self._data['sessions'] sessions[session_name]['collabs'][collab_name] = {} sessions[session_name]['collabs'][collab_name]['snaps'] = [] sessions[session_name]['collabs'][collab_name]['sounds'] = [] sessions[session_name]['collabs'][collab_name]['ip'] = ip_address sessions[session_name]['collabs'][collab_name]['port'] = port self._data['sessions'] = sessions client = ExchangeClientFactory(session_name, collab_name, None, self.debug_mode) reactor.connectTCP(ip_address, port, client) g_display.show_status("connecting") g_display.update_collab_view() # adds a session to the list def add_session(self, session_path): sessions = self._data['sessions'] session_name = session_name_from_path(session_path) #session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1] sessions[session_name] = {} sessions[session_name]['path'] = session_path sessions[session_name]['collabs'] = {} sessions[session_name]['collabs'][self._data['user']] = {} sessions[session_name]['collabs'][self._data['user']]['snaps'] = [] sessions[session_name]['collabs'][self._data['user']]['sounds'] = [] self._data['sessions'] = sessions self.rescan_session(session_name) def rescan_session(self, session_name): sessions = self._data['sessions'] session_path = sessions[session_name]['path'] sessions[session_name]['collabs'][self._data['user']]['snaps'] = self._scan_snapshots(session_path) sessions[session_name]['collabs'][self._data['user']]['sounds'] = self._scan_sounds(session_path) self._data['sessions'] = sessions g_display.update_snap_view() print self._data['sessions'] def create_session(self, session_path): try: os.mkdir(session_path) session_name = session_name_from_path(session_path) #session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ] audiofiles_path = session_path+'/interchange/'+session_name+'/audiofiles' os.makedirs(audiofiles_path) except OSError: raise_error("Could not create session directory", g_display.window) return sessions = self._data['sessions'] sessions[session_name] = {} sessions[session_name]['path'] = session_path sessions[session_name]['collabs'] = {} sessions[session_name]['collabs'][self._data['user']] = {} sessions[session_name]['collabs'][self._data['user']]['snaps'] = [] sessions[session_name]['collabs'][self._data['user']]['sounds'] = [] self._data['sessions'] = sessions print self._data['sessions'] def get_session_path(self, session): sessions = self._data['sessions'] return sessions[session]['path'] def get_user(self): return self._data['user'] def set_user(self, username): self._data['user'] = username def get_collab_ip(self, session, collab): sessions = self._data['sessions'] return sessions[session]['collabs'][collab]['ip'] def close(self): self._data.close() def get_sessions(self): sessions = self._data['sessions'] sess = sessions.keys() sess.sort() return sess def get_collabs(self, session): if session: sessions = self._data['sessions'] collabs = sessions[session]['collabs'].keys() collabs.sort() return collabs else: return [] def get_snaps(self, session, collab): if session and collab: sessions = self._data['sessions'] snaps = sessions[session]['collabs'][collab]['snaps'] snaps.sort() return snaps else: return [] def get_sounds(self, session, collab): if session and collab: sessions = self._data['sessions'] sounds = sessions[session]['collabs'][self._data['user']]['sounds'] sounds.sort() return sounds else: return [] def _scan_snapshots(self, session): snaps = [] files = os.listdir(session) pattern = re.compile(r'\.ardour$') for file in files: if pattern.search(file): snaps.append(file[0:-7]) print file[0:-7] return snaps def _scan_sounds(self, session_path): sounds = [] session_name = session_name_from_path(session_path) files = os.listdir(session_path+'/interchange/'+session_name+'/audiofiles') pattern = re.compile(r'\.peak$') for file in files: if not pattern.search(file): sounds.append(file) return sounds def __init__(self, *args): self._data = shelve.open(os.path.expanduser('~/.session_exchange'), 'c') self.port = 8970 self.debug_mode = False if len(self._data.keys()) < 1: self._data['sessions'] = {} self._data['user'] = '' self._collabs = {} from twisted.protocols.basic import FileSender class FileSenderLimited(FileSender): def beginFileTransfer(self, file, consumer, limit, transform = None): self.file = file self.consumer = consumer self.CHUNK_SIZE = limit self.transform = transform self.consumer.registerProducer(self, False) if not self.deferred: self.deferred = twisted.internet.defer.Deferred() return self.deferred def resumeProducing(self): chunk = '' chunk = self.file.read(self.CHUNK_SIZE) if self.transform: chunk = self.transform(chunk) self.consumer.write(chunk) self.lastSent = chunk[-1] self.file = None self.consumer.unregisterProducer() if not self.deferred: self.deferred = twisted.internet.defer.Deferred() self.deferred.callback(self.lastSent) self.deferred = None from twisted.protocols.basic import LineReceiver class ExchangeServer (LineReceiver): def __init__(self): self.state = "IDLE" def error(self, message): self.sendLine("ERROR") self.sendLine(message) self.transport.loseConnection() def connectionLost(self, reason): print "server: connection lost: ", reason def connectionMade(self): print "server: connection made" def lineReceived(self, data): print "server: '"+ data +"'" if self.state == "SESSION": if g_data.get_sessions().count(data): self.session_name = data self.state = "IDLE" self.sendLine("OK") else: self.error(data + " doesn't exist on server") elif self.state == "SNAPSHOT": if g_data.get_snaps(self.session_name, g_data.get_user()).count(data): filename = g_data.get_session_path(self.session_name)+data+'.ardour' self.sendLine(str(os.stat(filename).st_size)) self.sendLine("OK") self.file = open(filename, 'r') file_sender = FileSender() cb = file_sender.beginFileTransfer(self.file, self.transport) cb.addCallback(self.file_done) else: self.error("snapshot: " + data + " doesn't exist on server") elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER": if g_data.get_sounds(self.session_name, g_data.get_user()).count(data): #filename = g_data.get_session_path(self.session_name)+"/sounds/"+data filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+data if self.state == "SOUNDFILE": self.sendLine(str(os.stat(filename).st_size)) else: #SOUNDFILE_HEADER header_size = get_header_size(filename) if header_size: self.sendLine(str(header_size)) else: self.error('soundfile: ' + data + 'doesn\'t have "data" chunk') self.sendLine("OK") self.file = open(filename, 'r') if self.state == "SOUNDFILE": file_sender = FileSender() cb = file_sender.beginFileTransfer(self.file, self.transport) else: # SOUNDFILE_HEADER file_sender = FileSenderLimited() cb = file_sender.beginFileTransfer(self.file, self.transport, header_size) cb.addCallback(self.file_done) elif data == "SOUNDFILE_SIZE": self.state = "SOUNDFILE_SIZE" else: self.error("soundfile: " + data + " doesn't exist on server") elif self.state == "SOUNDFILE_SIZE": if g_data.get_sounds(self.session_name, g_data.get_user()).count(data): #filename = g_data.get_session_path(self.session_name)+"/sounds/"+data filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+data self.sendLine(str(os.stat(filename).st_size)) self.state = "IDLE" elif data == "SESSION": self.state = "SESSION" elif data == "SNAPS": self.state = "SNAPS" for snap in g_data.get_snaps(self.session_name, g_data.get_user()): self.sendLine(snap) self.sendLine("OK") self.state = "IDLE" elif data == "SNAPSHOT": self.state = "SNAPSHOT" elif data == "SOUNDFILE": self.state = "SOUNDFILE" elif data == "SOUNDFILE_HEADER": self.state = "SOUNDFILE_HEADER" def file_done(self, data): print "server: file done" self.file.close() self.state = "IDLE" class ExchangeServerFactory(protocol.ServerFactory): protocol = ExchangeServer def __init__(self): pass class ExchangeClient (LineReceiver): def __init__(self, session_name, collab_name, snap_name, debug_mode): self.session_name = session_name self.collab_name = collab_name self.snap_name = snap_name self.debug_mode = debug_mode self.state = "IDLE" def connectionLost(self, reason): g_display.show_status("Connection lost") def connectionMade(self): g_display.show_status("Connection made") self.state = "SESSION" self.sendLine("SESSION") self.sendLine(self.session_name) def rawDataReceived(self, data): self.file.write(data) self.received += len(data) print self.received, self.filesize if self.received >= self.filesize: self.setLineMode() self.file.close() g_data.rescan_session(self.session_name) if self.state == "SNAPSHOT": self.sounds = get_sound_list(self.filename) if len(self.sounds): self.sound_index = 0 if self.debug_mode: self.state = "SOUNDFILE_HEADER" self.sendLine("SOUNDFILE_HEADER") else: self.state = "SOUNDFILE" self.sendLine("SOUNDFILE") self.sendLine(self.sounds[self.sound_index]) else: self.transport.loseConnection() elif self.state == "SOUNDFILE": self.sound_index += 1 if self.sound_index > len(self.sounds)-1: self.transport.loseConnection() else: self.sendLine("SOUNDFILE") self.sendLine(self.sounds[self.sound_index]) elif self.state == "SOUNDFILE_HEADER": self.state = "SOUNDFILE_SIZE" self.sendLine("SOUNDFILE_SIZE") self.sendLine(self.sounds[self.sound_index]) def lineReceived(self, data): print "client: ", data if data == "ERROR": self.state = "ERROR" elif data == "OK": if self.state == "SESSION": print "snap name ='"+self.snap_name+"'" if self.snap_name: self.state = "SNAPSHOT" self.sendLine("SNAPSHOT") self.sendLine(self.snap_name) else: self.state = "SNAPS" self.sendLine("SNAPS") elif self.state == "SNAPS": self.transport.loseConnection() elif self.state == "SNAPSHOT": self.setRawMode() self.filename = g_data.get_session_path(self.session_name)+'/'+self.snap_name+'.ardour' self.file = open(self.filename, 'w') self.received = 0 elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER": self.setRawMode() #self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index] self.filename = g_data.get_session_path(self.session_name)+'/interchange/'+self.session_name+'/audiofiles/'+self.sounds[self.sound_index] self.file = open(self.filename, 'w') self.received = 0 elif self.state == "ERROR": raise_error(data, g_display.window) elif self.state == "SNAPS": g_data.add_snap(self.session_name, self.collab_name, data) elif self.state == "SNAPSHOT": self.filesize = int(data) elif self.state == "SOUNDFILE": self.filesize = int(data) elif self.state == "SOUNDFILE_HEADER": self.filesize = int(data) elif self.state == "SOUNDFILE_SIZE": print "SOUNDFILE_SIZE = " + data append_empty_data(self,self.filename, int(data)) self.sound_index += 1 if self.sound_index > len(self.sounds)-1: self.transport.loseConnection() else: self.state = "SOUNDFILE_HEADER" self.sendLine("SOUNDFILE_HEADER") self.sendLine(self.sounds[self.sound_index]) class ExchangeClientFactory(protocol.ClientFactory): def buildProtocol(self, addr): return ExchangeClient(self.session_name, self.collab_name, self.snap_name, self.debug_mode) def clientConnectionFailed(self, connector, reason): raise_error('Connection failed: ' + reason.getErrorMessage(), g_display.window) g_display.show_status('Connection failed') def __init__(self, session_name, collab_name, snap_name, debug_mode): self.session_name = session_name self.collab_name = collab_name self.snap_name = snap_name self.debug_mode = debug_mode # GUI stuff class HelperWin(object): def delete_me(self, window): self = 0 class Preferences(HelperWin): def __init__(self): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title('Preferences') self.window.connect('destroy', self.delete_me) main_box = gtk.VBox() self.window.add(main_box) hbox1 = gtk.HBox() label1 = gtk.Label("User") self.user = gtk.Entry() self.user.set_text(g_data.get_user()) hbox1.pack_start(label1) hbox1.pack_start(self.user) main_box.pack_start(hbox1) ok_btn = gtk.Button("Ok") ok_btn.connect('clicked', self.ok_clicked) main_box.pack_start(ok_btn) self.window.show_all() def ok_clicked(self, btn): g_data.set_user(self.user.get_text()) self.window.hide_all() def show_all(self): self.window.show_all() class AddCollaborator(HelperWin): def __init__(self, session): self.session_name = session self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title('Fetch Session') self.window.connect('destroy', self.delete_me) main_box = gtk.VBox() self.window.add(main_box) hbox0 = gtk.HBox() label0 = gtk.Label("Collaborator") self.collab = gtk.Entry() self.collab.connect('key-release-event', self.key_press) hbox0.pack_start(label0) hbox0.pack_start(self.collab) main_box.pack_start(hbox0) hbox1 = gtk.HBox() label1 = gtk.Label("IP Address") self.address = gtk.Entry() self.address.connect('key-release-event', self.key_press) hbox1.pack_start(label1) hbox1.pack_start(self.address) main_box.pack_start(hbox1) hbox2 = gtk.HBox() label2 = gtk.Label("Port Number") self.port = gtk.Entry() self.port.connect('key-release-event', self.key_press) self.port.set_text(str(g_data.port)) hbox2.pack_start(label2) hbox2.pack_start(self.port) main_box.pack_start(hbox2) hbox3 = gtk.HBox() label3 = gtk.Label("Username") label3.set_sensitive(False) self.username = gtk.Entry() self.username.set_sensitive(False) hbox3.pack_start(label3) hbox3.pack_start(self.username) main_box.pack_start(hbox3) hbox4 = gtk.HBox() label4 = gtk.Label("Password") label4.set_sensitive(False) self.password = gtk.Entry() self.password.set_sensitive(False) hbox4.pack_start(label4) hbox4.pack_start(self.password) main_box.pack_start(hbox4) self.ok_btn = gtk.Button(gtk.STOCK_OK) self.ok_btn.set_use_stock(True) self.ok_btn.connect('clicked', self.ok_clicked) self.ok_btn.set_sensitive(False) main_box.pack_start(self.ok_btn) self.window.show_all() def key_press(self, event, data): if self.collab.get_text() and self.address.get_text() and self.port.get_text(): self.ok_btn.set_sensitive(True) else: self.ok_btn.set_sensitive(False) return True def ok_clicked(self, btn): self.window.hide_all() g_data.add_collab(self.session_name, self.collab.get_text(), self.address.get_text(), int(self.port.get_text())) self.collab.set_text('') self.address.set_text('') self.port.set_text('') self.username.set_text('') self.password.set_text('') def show_all(self): self.window.show_all() class ArdourShareWindow(object): def menuitem_cb(self, window, action, widget): print self, window, action, widget def add_collaborator_cb(self, window, action, widget): if self.session: self.add_session = AddCollaborator(self.session) def fetch_snapshot_cb(self, window, action, widget): if self.session and self.collab and self.collab != g_data.get_user(): client = ExchangeClientFactory(self.session, self.collab, self.snap, g_data.debug_mode) reactor.connectTCP(g_data.get_collab_ip(self.session, self.collab), g_data.port, client) def preferences_cb(self, window, action, widget): self.preferences = Preferences() def add_session_ok_file_btn_clicked(self, w): filename = self.file_sel.get_filename() if filename.endswith(".ardour"): g_data.add_session(filename[0:filename.rfind("/")+1]) self.update_session_view() else: raise_error("Not an Ardour session", self.window) self.file_sel.destroy() def add_session_cb(self, window, action, widget): if g_data.get_user(): self.file_sel = gtk.FileSelection("Add Session...") self.file_sel.ok_button.connect("clicked", self.add_session_ok_file_btn_clicked) self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy()) self.file_sel.connect("destroy", lambda w: self.file_sel.destroy()) self.file_sel.show() else: raise_error("Set the user name in the preferences first", self.window) def create_session_cb(self, window, action, widget): if g_data.get_user(): self.file_sel = gtk.FileSelection("Create Session...") self.file_sel.ok_button.connect("clicked", self.create_file_ok_btn_clicked) self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy()) self.file_sel.connect("destroy", lambda w: self.file_sel.destroy()) self.file_sel.show() else: raise_error("Set the user name in the preferences first", self.window) def create_file_ok_btn_clicked(self, w): filename = self.file_sel.get_filename() if len(filename) > 0: g_data.create_session(filename) self.update_session_view() else: raise_error("Not an Ardour session", self.window) self.file_sel.destroy() def update_session_view(self): self.session_model.clear() for session in g_data.get_sessions(): self.session_model.set(self.session_model.append(), 0, session) def update_collab_view(self): self.collab_model.clear() for collab in g_data.get_collabs(self.session): self.collab_model.set(self.collab_model.append(), 0, collab) def update_snap_view(self): self.snap_model.clear() for snap in g_data.get_snaps(self.session, self.collab): self.snap_model.set(self.snap_model.append(), 0, snap) def cb_session_selection_changed(self, selection_object): selected = [] selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path)) for x in selected: self.session = self.session_model[x][0] self.selected_type = "session" self.update_collab_view() def cb_collab_selection_changed(self, selection_object): selected = [] selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path)) for x in selected: self.collab = self.collab_model[x][0] self.selected_type = "collab" self.update_snap_view() def cb_snap_selection_changed(self, selection_object): selected = [] selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path)) for x in selected: self.snap = self.snap_model[x][0] self.selected_type = "snap" def delete_cb(self, window, action, widget): if self.selected_type == "session": g_data.delete_session(self.session) self.session = "" self.collab = "" self.snap = "" elif self.selected_type == "collab": g_data.delete_collab(self.session, self.collab) self.collab = "" self.snap = "" elif self.selected_type == "snap": g_data.delete_snap(self.session, self.collab, self.snap) self.snap = "" self.update_session_view() self.update_collab_view() self.update_snap_view() self.selected_type = "" def show_status(self, text): mid = self.status_bar.push(self._status_cid, text) if self._status_mid: self.status_bar.remove(self._status_cid, self._status_mid) self._status_mid = mid def __init__(self): self.selected_type = "" self.session = "" self.collab = g_data.get_user() self.snap = "" self.preferences = 0 self.add_collab = 0 self.add_session = 0 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_title('Session Exchange') self.window.set_size_request(400, 200) self.window.connect('destroy', lambda win: gtk.main_quit()) accel_group = gtk.AccelGroup() self.window.add_accel_group(accel_group) main_box = gtk.VBox() self.window.add(main_box) menu_items = ( ('/_File', None, None, 0, '<Branch>'), ('/File/_Add Session...','<control>A', self.add_session_cb, 0, ''), ('/File/Create _Session...', '<control>S', self.create_session_cb, 0, ''), ('/File/sep1', None, None, 0, '<Separator>'), ('/File/_Quit', '<control>Q', gtk.main_quit, 0, '<StockItem>', gtk.STOCK_QUIT), ('/_Edit', None, None, 0, '<Branch>' ), ('/Edit/Cu_t', '<control>X', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_CUT), ('/Edit/_Copy', '<control>C', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_COPY), ('/Edit/_Paste', '<control>V', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_PASTE), ('/Edit/_Delete', None, self.delete_cb, 0, '<StockItem>', gtk.STOCK_DELETE), ('/Edit/sep1', None, None, 0, '<Separator>'), ('/Edit/Add Colla_borator...','<control>B', self.add_collaborator_cb,0,''), ('/Edit/_Fetch Snapshot','<control>F', self.fetch_snapshot_cb,0,''), ('/Edit/sep1', None, None, 0, '<Separator>'), ('/Edit/_Preferences...','<control>P', self.preferences_cb, 0, '') ) #need to hold a reference to the item_factory or the menubar will disappear. self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group) self.item_factory.create_items(menu_items, self.window) main_box.pack_start(self.item_factory.get_widget('<main>'), False) pane1 = gtk.HPaned() pane2 = gtk.HPaned() pane1.pack2(pane2, True, False) scroll1 = gtk.ScrolledWindow() scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) pane1.pack1(scroll1, True, False) scroll2 = gtk.ScrolledWindow() scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) pane2.pack1(scroll2, True, False) scroll3 = gtk.ScrolledWindow() scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) pane2.pack2(scroll3, True, False) self.session_model = gtk.ListStore(gobject.TYPE_STRING) view1 = gtk.TreeView(self.session_model) column1 = gtk.TreeViewColumn('Sessions', gtk.CellRendererText(), text=0) view1.append_column(column1) self.session_selection = view1.get_selection() self.session_selection.connect("changed", self.cb_session_selection_changed) scroll1.add(view1) self.update_session_view() self.collab_model = gtk.ListStore(gobject.TYPE_STRING) view2 = gtk.TreeView(self.collab_model) column2 = gtk.TreeViewColumn('Collaborators', gtk.CellRendererText(), text=0) view2.append_column(column2) self.collab_selection = view2.get_selection() self.collab_selection.connect("changed", self.cb_collab_selection_changed) scroll2.add(view2) self.snap_model = gtk.ListStore(gobject.TYPE_STRING) view3 = gtk.TreeView(self.snap_model) column3 = gtk.TreeViewColumn('Snapshots', gtk.CellRendererText(), text=0) view3.append_column(column3) self.snap_selection = view3.get_selection() self.snap_selection.connect("changed", self.cb_snap_selection_changed) scroll3.add(view3) main_box.pack_start(pane1, True, True) self.status_bar = gtk.Statusbar() main_box.pack_start(self.status_bar, False) self._status_cid = self.status_bar.get_context_id('display') self._status_mid = '' self.window.show_all() def print_help(): print """ -h, --help -n, --no-server Only act as a client -p, --port <port number> Defaults to 8970 -d, --debug Infers audio files. For debugging Ardour. -v, --version Version """ sys.exit(2) def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hp:ndv", ["help", "port=", "no-server", "debug", "version"]) except getopt.GetoptError: print_help() server = True for o, a in opts: if o in ("-h", "--help"): print_help() if o in ("-d", "--debug"): g_display.window.set_title('Session Exchange: Debug Mode') g_data.debug_mode = True if o in ("-p", "--port"): g_data.port = int(a) if o in ("-n", "--no-server"): server = False if o in ("-v", "--version"): print VERSION sys.exit(2) if (server): try: reactor.listenTCP(g_data.port, ExchangeServerFactory()) except twisted.internet.error.CannotListenError: print "Can not listen on a port number under 1024 unless run as root" sys.exit(2) reactor.run() g_data.close() # global objects g_data = Data() g_display = ArdourShareWindow() if __name__ == '__main__': main() |