~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to tools/session_exchange.py

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
 
 
3
# Session Exchange
 
4
# By Taybin Rutkin
 
5
# Copyright 2004-2005, under the GPL
 
6
 
 
7
VERSION='0.1.2'
 
8
 
 
9
#twisted libraries
 
10
from twisted.internet import gtk2reactor
 
11
gtk2reactor.install()
 
12
from twisted.internet import reactor, protocol
 
13
import twisted.internet.error
 
14
 
 
15
#pygtk libraries
 
16
import gobject
 
17
import gtk
 
18
 
 
19
#standard python2.2 libraries
 
20
import getopt
 
21
import os
 
22
import os.path
 
23
import re
 
24
import shelve
 
25
import string
 
26
import sys
 
27
import xml.dom.minidom
 
28
 
 
29
v2paths = True
 
30
 
 
31
def get_header_size(filename):
 
32
        size = 0
 
33
        file = open(filename, 'r')
 
34
        while True:
 
35
                chunk = file.read(4)
 
36
                size += 4
 
37
                if chunk == "data":
 
38
                        file.close()
 
39
                        return size + 4        #include the size chunk after "data"
 
40
                if not chunk:
 
41
                        file.close()
 
42
                        return None
 
43
 
 
44
def append_empty_data(self, filename, size):
 
45
        file = open(filename, 'a')
 
46
        file.seek(size-1)
 
47
        file.write('\x00')
 
48
        file.close()
 
49
        
 
50
def get_sound_list(snapshot):
 
51
        doc = xml.dom.minidom.parse(snapshot)
 
52
        
 
53
        regionlist = []
 
54
        playlists_tag = doc.getElementsByTagName('Playlists')
 
55
        playlists = playlists_tag[0].getElementsByTagName('Playlist')
 
56
        for play in playlists:
 
57
                regions = play.getElementsByTagName('Region')
 
58
                for region in regions:
 
59
                        regionlist.append(region.getAttribute('source-0'))
 
60
                        regionlist.append(region.getAttribute('source-1'))
 
61
                        regionlist.append(region.getAttribute('source-2'))
 
62
                        regionlist.append(region.getAttribute('source-3'))
 
63
                        regionlist.append(region.getAttribute('source-4'))
 
64
                        regionlist.append(region.getAttribute('source-5'))
 
65
        
 
66
        sourcelist = {}
 
67
        sources = doc.getElementsByTagName('Source')
 
68
        for source in sources:
 
69
                sourcelist[source.getAttribute('id')] = str(source.getAttribute('name'))
 
70
 
 
71
        soundlist = []
 
72
        for id in regionlist:
 
73
                if sourcelist.has_key(id):
 
74
                        soundlist.append(sourcelist[id])
 
75
        
 
76
        return soundlist
 
77
 
 
78
def raise_error(string, parent):
 
79
        dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
 
80
        gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, string)
 
81
        
 
82
        dialog.run()
 
83
        dialog.destroy()
 
84
 
 
85
class Data(object):
 
86
        def delete_snap(self, session, collab, snap):
 
87
                sessions = self._data['sessions']
 
88
                sessions[session]['collabs'][collab]['snaps'].remove(snap)
 
89
                self._data['sessions'] = sessions
 
90
        
 
91
        def delete_collab(self,session, collab):
 
92
                sessions = self._data['sessions']
 
93
                del sessions[session]['collabs'][collab]
 
94
                self._data['sessions'] = sessions
 
95
        
 
96
        def delete_session(self, session):
 
97
                sessions = self._data['sessions']
 
98
                del sessions[session]
 
99
                self._data['sessions'] = sessions
 
100
        
 
101
        def add_snap(self, session_name, collab_name, snap_name):
 
102
                sessions = self._data['sessions']
 
103
                sessions[session_name]['collabs'][collab_name]['snaps'].append(snap_name)
 
104
                sessions[session_name]['collabs'][collab_name]['snaps'].sort()
 
105
                self._data['sessions'] = sessions
 
106
                
 
107
                g_display.update_snap_view()
 
108
        
 
109
        def add_collab(self, session_name, collab_name, ip_address, port):
 
110
                sessions = self._data['sessions']
 
111
                sessions[session_name]['collabs'][collab_name] = {}
 
112
                sessions[session_name]['collabs'][collab_name]['snaps'] = []
 
113
                sessions[session_name]['collabs'][collab_name]['sounds'] = []
 
114
                sessions[session_name]['collabs'][collab_name]['ip'] = ip_address
 
115
                sessions[session_name]['collabs'][collab_name]['port'] = port
 
116
                sessions[session_name]['collabs'][collab_name]['v2paths'] = True
 
117
                self._data['sessions'] = sessions
 
118
                
 
119
                client = ExchangeClientFactory(session_name, collab_name, None, self.debug_mode)
 
120
                reactor.connectTCP(ip_address, port, client)
 
121
                g_display.show_status("connecting")
 
122
                
 
123
                g_display.update_collab_view()
 
124
        
 
125
        def add_session(self, session_path):
 
126
                sessions = self._data['sessions']
 
127
                
 
128
                session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1]
 
129
                sessions[session_name] = {}
 
130
                sessions[session_name]['path'] = session_path 
 
131
                sessions[session_name]['collabs'] = {}
 
132
                sessions[session_name]['collabs'][self._data['user']] = {}
 
133
                sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
 
134
                sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
 
135
                if os.path.isdir (os.path.join (session_path,'sounds')):
 
136
                        sessions[session_name]['collabs'][self._data['user']]['v2paths'] = False
 
137
                        v2paths = False
 
138
                else:
 
139
                        sessions[session_name]['collabs'][self._data['user']]['v2paths'] = True
 
140
                
 
141
                self._data['sessions'] = sessions
 
142
                
 
143
                self.rescan_session(session_name)
 
144
 
 
145
        def rescan_session(self, session_name):
 
146
                sessions = self._data['sessions']
 
147
                
 
148
                session_path = sessions[session_name]['path']
 
149
                sessions[session_name]['collabs'][self._data['user']]['snaps'] = self._scan_snapshots(session_path)
 
150
                sessions[session_name]['collabs'][self._data['user']]['sounds'] = self._scan_sounds(session_name)
 
151
                
 
152
                self._data['sessions'] = sessions
 
153
                
 
154
                g_display.update_snap_view()
 
155
                
 
156
                print self._data['sessions']
 
157
        
 
158
        def create_session(self, session_path):
 
159
                sessions = self._data['sessions']
 
160
 
 
161
                session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ]
 
162
                try:
 
163
                        os.mkdir(session_path)
 
164
                        os.mkdir(os.path.join (session_path,'interchange'))
 
165
                        os.mkdir(os.path.join (session_path,'interchange',session_name))
 
166
                        os.mkdir(os.path.join (session_path,'interchange',session_name,'audiofiles'))
 
167
                except OSError:
 
168
                        raise_error("Could not create session directory", g_display.window)
 
169
                        return
 
170
                
 
171
                sessions[session_name] = {}
 
172
                sessions[session_name]['path'] = session_path
 
173
                sessions[session_name]['collabs'] = {}
 
174
                sessions[session_name]['collabs'][self._data['user']] = {}
 
175
                sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
 
176
                sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
 
177
                
 
178
                self._data['sessions'] = sessions
 
179
                print self._data['sessions']
 
180
        
 
181
        def get_session_path(self, session):
 
182
                sessions = self._data['sessions']
 
183
                return sessions[session]['path']
 
184
        
 
185
        def get_user(self):
 
186
                return self._data['user']
 
187
        
 
188
        def set_user(self, username):
 
189
                self._data['user'] = username
 
190
        
 
191
        def get_collab_ip(self, session, collab):
 
192
                sessions = self._data['sessions']
 
193
                return sessions[session]['collabs'][collab]['ip']
 
194
        
 
195
        def close(self):
 
196
                self._data.close()
 
197
        
 
198
        def get_sessions(self):
 
199
                sessions = self._data['sessions']
 
200
                sess = sessions.keys()
 
201
                sess.sort()
 
202
                return sess
 
203
        
 
204
        def get_collabs(self, session):
 
205
                if session:
 
206
                        sessions = self._data['sessions']
 
207
                        collabs = sessions[session]['collabs'].keys()
 
208
                        collabs.sort()
 
209
                        return collabs
 
210
                else:
 
211
                        return []
 
212
        
 
213
        def get_snaps(self, session, collab):
 
214
                if session and collab:
 
215
                        sessions = self._data['sessions']
 
216
                        snaps = sessions[session]['collabs'][collab]['snaps']
 
217
                        snaps.sort()
 
218
                        return snaps
 
219
                else:
 
220
                        return []
 
221
        
 
222
        def get_sounds(self, session, collab):
 
223
                if session and collab:
 
224
                        sessions = self._data['sessions']
 
225
                        sounds = sessions[session]['collabs'][self._data['user']]['sounds']
 
226
                        sounds.sort()
 
227
                        return sounds
 
228
                else:
 
229
                        return []
 
230
                
 
231
        def _scan_snapshots(self, session):
 
232
                snaps = []
 
233
                files = os.listdir(session)
 
234
                pattern = re.compile(r'\.ardour$')
 
235
                for file in files:
 
236
                        if pattern.search(file):
 
237
                                snaps.append(file[0:-7])
 
238
                                print file[0:-7]
 
239
                return snaps
 
240
        
 
241
        def _scan_sounds(self, session):
 
242
                sessions = self._data['sessions']
 
243
 
 
244
                sounds = []
 
245
                if v2paths:
 
246
                        print session
 
247
                        print os.path.join (sessions[session]['path'],'interchange', session, 'audiofiles')
 
248
                        files = os.listdir(os.path.join (sessions[session]['path'],'interchange', session, 'audiofiles'))
 
249
                else:
 
250
                        files = os.listdir(os.path.join (session,'sounds'))
 
251
                pattern = re.compile(r'\.peak$')
 
252
                for file in files:
 
253
                        if not pattern.search(file):
 
254
                                sounds.append(file)
 
255
                return sounds
 
256
        
 
257
        def __init__(self, *args):
 
258
                self._data = shelve.open(os.path.expanduser('~/.session_exchange'), 'c')
 
259
                self.port = 8970
 
260
                self.debug_mode = False
 
261
                if len(self._data.keys()) < 1:
 
262
                        self._data['sessions'] = {}
 
263
                        self._data['user'] = ''
 
264
                
 
265
                self._collabs = {}
 
266
 
 
267
from twisted.protocols.basic import FileSender
 
268
class FileSenderLimited(FileSender):
 
269
        def beginFileTransfer(self, file, consumer, limit, transform = None):
 
270
                self.file = file
 
271
                self.consumer = consumer
 
272
                self.CHUNK_SIZE = limit
 
273
                self.transform = transform
 
274
                
 
275
                self.consumer.registerProducer(self, False)
 
276
                self.deferred = defer.Deferred()
 
277
                return self.deferred
 
278
        
 
279
        def resumeProducing(self):
 
280
                chunk = ''
 
281
                chunk = self.file.read(self.CHUNK_SIZE)
 
282
                
 
283
                if self.transform:
 
284
                        chunk = self.transform(chunk)
 
285
 
 
286
                self.consumer.write(chunk)
 
287
                self.lastSent = chunk[-1]
 
288
                self.file = None
 
289
                self.consumer.unregisterProducer()
 
290
                self.deferred.callback(self.lastSent)
 
291
                self.deferred = None
 
292
 
 
293
from twisted.protocols.basic import LineReceiver
 
294
class ExchangeServer (LineReceiver):
 
295
        def __init__(self):
 
296
                self.state = "IDLE"
 
297
        
 
298
        def error(self, message):
 
299
                self.sendLine("ERROR")
 
300
                self.sendLine(message)
 
301
                self.transport.loseConnection()
 
302
        
 
303
        def connectionLost(self, reason):
 
304
                print "server: connection lost: ", reason
 
305
        
 
306
        def connectionMade(self):
 
307
                print "server: connection made"
 
308
        
 
309
        def lineReceived(self, data):
 
310
                print "server: ", data
 
311
                
 
312
                if self.state == "SESSION":
 
313
                        if g_data.get_sessions().count(data):
 
314
                                self.session_name = data
 
315
                                self.state = "IDLE"
 
316
                                self.sendLine("OK")
 
317
                        else:
 
318
                                self.error(data + " doesn't exist on server")
 
319
                elif self.state == "SNAPSHOT":
 
320
                        if g_data.get_snaps(self.session_name, g_data.get_user()).count(data):
 
321
                                filename = g_data.get_session_path(self.session_name)+data+'.ardour'
 
322
                                print filename
 
323
                                self.sendLine(str(os.stat(filename).st_size))
 
324
                                self.sendLine("OK")
 
325
                                self.file = open(filename, 'r')
 
326
                                file_sender = FileSender()
 
327
                                cb = file_sender.beginFileTransfer(self.file, self.transport)
 
328
                                cb.addCallback(self.file_done)
 
329
                        else:
 
330
                                self.error("snapshot: " + data + " doesn't exist on server")
 
331
                elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
 
332
                        if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
 
333
                                filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+data
 
334
                                print filename
 
335
                                if self.state == "SOUNDFILE":
 
336
                                        self.sendLine(str(os.stat(filename).st_size))
 
337
                                else:        #SOUNDFILE_HEADER
 
338
                                        header_size = get_header_size(filename)
 
339
                                        if header_size:
 
340
                                                self.sendLine(str(header_size))
 
341
                                        else:
 
342
                                                self.error('soundfile: ' + data + 'doesn\'t have "data" chunk')
 
343
                                self.sendLine("OK")
 
344
                                self.file = open(filename, 'r')
 
345
                                if self.state == "SOUNDFILE":
 
346
                                        file_sender = FileSender()
 
347
                                        cb = file_sender.beginFileTransfer(self.file, self.transport)
 
348
                                else:        # SOUNDFILE_HEADER
 
349
                                        file_sender = FileSenderLimited()
 
350
                                        cb = file_sender.beginFileTransfer(self.file, self.transport, header_size)
 
351
                                cb.addCallback(self.file_done)
 
352
                        else:
 
353
                                self.error("soundfile: " + data + "doesn't exist on server")
 
354
                elif self.state == "SOUNDFILE_SIZE":
 
355
                        if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
 
356
                                filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
 
357
                                print filename
 
358
                                self.sendLine(str(os.stat(filename).st_size))
 
359
                                self.state = "IDLE"
 
360
                elif data == "SESSION":
 
361
                        self.state = "SESSION"
 
362
                elif data == "SNAPS":
 
363
                        self.state = "SNAPS"
 
364
                        for snap in g_data.get_snaps(self.session_name, g_data.get_user()):
 
365
                                self.sendLine(snap)
 
366
                        self.sendLine("OK")
 
367
                        self.state = "IDLE"
 
368
                elif data == "SNAPSHOT":
 
369
                        self.state = "SNAPSHOT"
 
370
                elif data == "SOUNDFILE":
 
371
                        self.state = "SOUNDFILE"
 
372
                elif data == "SOUNDFILE_HEADER":
 
373
                        self.state = "SOUNDFILE_HEADER"
 
374
                elif data == "SOUNDFILE_SIZE":
 
375
                        self.state = "SOUNDFILE_SIZE"
 
376
        
 
377
        def file_done(self, data):
 
378
                print "server: file done"
 
379
                self.file.close()
 
380
                self.state = "IDLE"
 
381
        
 
382
class ExchangeServerFactory(protocol.ServerFactory):
 
383
        protocol = ExchangeServer
 
384
        
 
385
        def __init__(self):
 
386
                pass
 
387
 
 
388
class ExchangeClient (LineReceiver):
 
389
        def __init__(self, session_name, collab_name, snap_name, debug_mode):
 
390
                self.session_name = session_name
 
391
                self.collab_name = collab_name
 
392
                self.snap_name = snap_name
 
393
                self.debug_mode = debug_mode
 
394
                self.state = "IDLE"
 
395
        
 
396
        def connectionLost(self, reason):
 
397
                g_display.show_status("Connection lost")
 
398
        
 
399
        def connectionMade(self):
 
400
                g_display.show_status("Connection made")
 
401
                self.state = "SESSION"
 
402
                self.sendLine("SESSION")
 
403
                self.sendLine(self.session_name)
 
404
        
 
405
        def rawDataReceived(self, data):
 
406
                self.file.write(data)
 
407
                self.received += len(data)
 
408
                print self.received, self.filesize
 
409
                if self.received >= self.filesize:
 
410
                        self.setLineMode()
 
411
                        self.file.close()
 
412
                        g_data.rescan_session(self.session_name)
 
413
                        if self.state == "SNAPSHOT":
 
414
                                self.sounds = get_sound_list(self.filename)
 
415
                                if len(self.sounds):
 
416
                                        self.sound_index = 0
 
417
                                        if self.debug_mode:
 
418
                                                self.state = "SOUNDFILE_HEADER"
 
419
                                                self.sendLine("SOUNDFILE_HEADER")
 
420
                                        else:
 
421
                                                self.state = "SOUNDFILE"
 
422
                                                self.sendLine("SOUNDFILE")
 
423
                                        self.sendLine(self.sounds[self.sound_index])
 
424
                                else:
 
425
                                        self.transport.loseConnection()
 
426
                        elif self.state == "SOUNDFILE":
 
427
                                self.sound_index += 1
 
428
                                if self.sound_index > len(self.sounds)-1:
 
429
                                        self.transport.loseConnection()
 
430
                                else:
 
431
                                        self.sendLine("SOUNDFILE")
 
432
                                        self.sendLine(self.sounds[self.sound_index])
 
433
                        elif self.state == "SOUNDFILE_HEADER":
 
434
                                self.state = "SOUNDFILE_SIZE"
 
435
                                self.sendLine("SOUNDFILE_SIZE")
 
436
                                self.sendLine(self.sounds[self.sound_index])
 
437
        
 
438
        def lineReceived(self, data):
 
439
                print "client: ", data
 
440
                
 
441
                if data == "ERROR":
 
442
                        self.state = "ERROR"
 
443
                elif data == "OK":
 
444
                        if self.state == "SESSION":
 
445
                                if self.snap_name:
 
446
                                        self.state = "SNAPSHOT"
 
447
                                        self.sendLine("SNAPSHOT")
 
448
                                        self.sendLine(self.snap_name)
 
449
                                else:
 
450
                                        self.state = "SNAPS"
 
451
                                        self.sendLine("SNAPS")
 
452
                        elif self.state == "SNAPS":
 
453
                                self.transport.loseConnection()
 
454
                        elif self.state == "SNAPSHOT":
 
455
                                self.setRawMode()
 
456
                                self.filename = g_data.get_session_path(self.session_name)+'/'+self.snap_name+'.ardour'
 
457
                                self.file = open(self.filename, 'w')
 
458
                                self.received = 0
 
459
                        elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
 
460
                                self.setRawMode()
 
461
                                self.filename = g_data.get_session_path(self.session_name)+"/interchange/"+self.session_name+"/audiofiles/"+self.sounds[self.sound_index]
 
462
                                self.file = open(self.filename, 'w')
 
463
                                self.received = 0
 
464
                elif self.state == "ERROR":
 
465
                        raise_error(data, g_display.window)
 
466
                elif self.state == "SNAPS":
 
467
                        g_data.add_snap(self.session_name, self.collab_name, data)
 
468
                elif self.state == "SNAPSHOT":
 
469
                        self.filesize = int(data)
 
470
                elif self.state == "SOUNDFILE":
 
471
                        self.filesize = int(data)
 
472
                elif self.state == "SOUNDFILE_HEADER":
 
473
                        self.filesize = int(data)
 
474
                elif self.state == "SOUNDFILE_SIZE":
 
475
                        append_empty_data(self.filename, int(data))
 
476
                        self.sound_index += 1
 
477
                        if self.sound_index > len(self.sounds)-1:
 
478
                                self.transport.loseConnection()
 
479
                        else:
 
480
                                self.state = "SOUNDFILE_HEADER"
 
481
                                self.sendLine("SOUNDFILE_HEADER")
 
482
                                self.sendLine(self.sounds[self.sound_index])
 
483
 
 
484
class ExchangeClientFactory(protocol.ClientFactory):
 
485
        def buildProtocol(self, addr):
 
486
                return ExchangeClient(self.session_name, self.collab_name, self.snap_name, self.debug_mode)
 
487
        
 
488
        def clientConnectionFailed(self, connector, reason):
 
489
                raise_error('Connection failed: ' + reason.getErrorMessage(), g_display.window)
 
490
                g_display.show_status('Connection failed')
 
491
        
 
492
        def __init__(self, session_name, collab_name, snap_name, debug_mode):
 
493
                self.session_name = session_name
 
494
                self.collab_name = collab_name
 
495
                self.snap_name = snap_name
 
496
                self.debug_mode = debug_mode
 
497
 
 
498
class HelperWin(object):
 
499
        def delete_me(self, window):
 
500
                self = 0
 
501
 
 
502
class Preferences(HelperWin):
 
503
        def __init__(self):
 
504
                self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
505
                self.window.set_title('Preferences')
 
506
                self.window.connect('destroy', self.delete_me)
 
507
                self.window.set_position(gtk.WIN_POS_MOUSE)
 
508
                
 
509
                main_box = gtk.VBox()
 
510
                self.window.add(main_box)
 
511
                
 
512
                hbox1 = gtk.HBox()
 
513
                label1 = gtk.Label("User")
 
514
                self.user = gtk.Entry()
 
515
                self.user.set_text(g_data.get_user())
 
516
                hbox1.pack_start(label1)
 
517
                hbox1.pack_start(self.user)
 
518
                main_box.pack_start(hbox1)
 
519
                
 
520
                ok_btn = gtk.Button("Ok")
 
521
                ok_btn.connect('clicked', self.ok_clicked)
 
522
                main_box.pack_start(ok_btn)
 
523
                
 
524
                self.window.show_all()
 
525
                
 
526
        def ok_clicked(self, btn):
 
527
                g_data.set_user(self.user.get_text())
 
528
                self.window.hide_all()
 
529
                
 
530
        def show_all(self):
 
531
                self.window.show_all()
 
532
 
 
533
class AddCollaborator(HelperWin):
 
534
        def __init__(self, session):
 
535
                self.session_name = session
 
536
                
 
537
                self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
538
                self.window.set_title('Fetch Session')
 
539
                self.window.connect('destroy', self.delete_me)
 
540
                self.window.set_position(gtk.WIN_POS_MOUSE)
 
541
                
 
542
                main_box = gtk.VBox()
 
543
                self.window.add(main_box)
 
544
                
 
545
                hbox0 = gtk.HBox()
 
546
                label0 = gtk.Label("Collaborator")
 
547
                self.collab = gtk.Entry()
 
548
                self.collab.connect('key-release-event', self.key_press)
 
549
                hbox0.pack_start(label0)
 
550
                hbox0.pack_start(self.collab)
 
551
                main_box.pack_start(hbox0)
 
552
                
 
553
                hbox1 = gtk.HBox()
 
554
                label1 = gtk.Label("IP Address")
 
555
                self.address = gtk.Entry()
 
556
                self.address.connect('key-release-event', self.key_press)
 
557
                hbox1.pack_start(label1)
 
558
                hbox1.pack_start(self.address)
 
559
                main_box.pack_start(hbox1)
 
560
                
 
561
                hbox2 = gtk.HBox()
 
562
                label2 = gtk.Label("Port Number")
 
563
                self.port = gtk.Entry()
 
564
                self.port.connect('key-release-event', self.key_press)
 
565
                self.port.set_text(str(g_data.port))
 
566
                hbox2.pack_start(label2)
 
567
                hbox2.pack_start(self.port)
 
568
                main_box.pack_start(hbox2)
 
569
                
 
570
                hbox3 = gtk.HBox()
 
571
                label3 = gtk.Label("Username")
 
572
                label3.set_sensitive(False)
 
573
                self.username = gtk.Entry()
 
574
                self.username.set_sensitive(False)
 
575
                hbox3.pack_start(label3)
 
576
                hbox3.pack_start(self.username)
 
577
                main_box.pack_start(hbox3)
 
578
                
 
579
                hbox4 = gtk.HBox()
 
580
                label4 = gtk.Label("Password")
 
581
                label4.set_sensitive(False)
 
582
                self.password = gtk.Entry()
 
583
                self.password.set_sensitive(False)
 
584
                hbox4.pack_start(label4)
 
585
                hbox4.pack_start(self.password)
 
586
                main_box.pack_start(hbox4)
 
587
                
 
588
                self.ok_btn = gtk.Button(gtk.STOCK_OK)
 
589
                self.ok_btn.set_use_stock(True)
 
590
                self.ok_btn.connect('clicked', self.ok_clicked)
 
591
                self.ok_btn.set_sensitive(False)
 
592
                main_box.pack_start(self.ok_btn)
 
593
                
 
594
                self.window.show_all()
 
595
        
 
596
        def key_press(self, event, data):
 
597
                if self.collab.get_text() and self.address.get_text() and self.port.get_text():
 
598
                        self.ok_btn.set_sensitive(True)
 
599
                else:
 
600
                        self.ok_btn.set_sensitive(False)
 
601
                return True
 
602
        
 
603
        def ok_clicked(self, btn):
 
604
                self.window.hide_all()
 
605
                g_data.add_collab(self.session_name, self.collab.get_text(), self.address.get_text(), int(self.port.get_text()))
 
606
                self.collab.set_text('')
 
607
                self.address.set_text('')
 
608
                self.port.set_text('')
 
609
                self.username.set_text('')
 
610
                self.password.set_text('')
 
611
        
 
612
        def show_all(self):
 
613
                self.window.show_all()
 
614
 
 
615
class ArdourShareWindow(object):
 
616
        def menuitem_cb(self, window, action, widget):
 
617
                print self, window, action, widget
 
618
        
 
619
        def add_collaborator_cb(self, window, action, widget):
 
620
                if self.session:
 
621
                        self.add_session = AddCollaborator(self.session)
 
622
        
 
623
        def fetch_snapshot_cb(self, window, action, widget):
 
624
                if self.session and self.collab and self.collab != g_data.get_user():
 
625
                        client = ExchangeClientFactory(self.session, self.collab, self.snap, g_data.debug_mode)
 
626
                        reactor.connectTCP(g_data.get_collab_ip(self.session, self.collab), g_data.port, client)
 
627
        
 
628
        def preferences_cb(self, window, action, widget):
 
629
                self.preferences = Preferences()
 
630
        
 
631
        def add_session_ok_file_btn_clicked(self, w):
 
632
                filename = self.file_sel.get_filename()
 
633
                if filename.endswith(".ardour"):
 
634
                        g_data.add_session(filename[0:filename.rfind("/")+1])
 
635
                        self.update_session_view()
 
636
                else:
 
637
                        raise_error("Not an Ardour session", self.window)
 
638
                self.file_sel.destroy()
 
639
        
 
640
        def add_session_cb(self, window, action, widget):
 
641
                if g_data.get_user():
 
642
                        self.file_sel = gtk.FileSelection("Add Session...")
 
643
                        self.file_sel.ok_button.connect("clicked", self.add_session_ok_file_btn_clicked)
 
644
                        self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
 
645
                        self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
 
646
                        self.file_sel.show()
 
647
                else:
 
648
                        raise_error("Set the user name in the preferences first", self.window)
 
649
        
 
650
        def create_session_cb(self, window, action, widget):
 
651
                if g_data.get_user():
 
652
                        self.file_sel = gtk.FileSelection("Create Session...")
 
653
                        self.file_sel.ok_button.connect("clicked", self.create_file_ok_btn_clicked)
 
654
                        self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
 
655
                        self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
 
656
                        self.file_sel.show()
 
657
                else:
 
658
                        raise_error("Set the user name in the preferences first", self.window)
 
659
        
 
660
        def create_file_ok_btn_clicked(self, w):
 
661
                filename = self.file_sel.get_filename()
 
662
                if len(filename) > 0:
 
663
                        g_data.create_session(filename)
 
664
                        self.update_session_view()
 
665
                else:
 
666
                        raise_error("Not an Ardour session", self.window)
 
667
                self.file_sel.destroy()
 
668
        
 
669
        def update_session_view(self):
 
670
                self.session_model.clear()
 
671
                for session in g_data.get_sessions():
 
672
                        self.session_model.set(self.session_model.append(), 0, session)
 
673
        
 
674
        def update_collab_view(self):
 
675
                self.collab_model.clear()
 
676
                for collab in g_data.get_collabs(self.session):
 
677
                        self.collab_model.set(self.collab_model.append(), 0, collab)
 
678
        
 
679
        def update_snap_view(self):
 
680
                self.snap_model.clear()
 
681
                for snap in g_data.get_snaps(self.session, self.collab):
 
682
                        self.snap_model.set(self.snap_model.append(), 0, snap)
 
683
        
 
684
        def cb_session_selection_changed(self, selection_object):
 
685
                selected = []
 
686
                selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
 
687
                for x in selected:
 
688
                        self.session = self.session_model[x][0]
 
689
                self.selected_type = "session"
 
690
                self.update_collab_view()
 
691
        
 
692
        def cb_collab_selection_changed(self, selection_object):
 
693
                selected = []
 
694
                selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
 
695
                for x in selected:
 
696
                        self.collab = self.collab_model[x][0]
 
697
                self.selected_type = "collab"
 
698
                self.update_snap_view()
 
699
        
 
700
        def cb_snap_selection_changed(self, selection_object):
 
701
                selected = []
 
702
                selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
 
703
                for x in selected:
 
704
                        self.snap = self.snap_model[x][0]
 
705
                self.selected_type = "snap"
 
706
        
 
707
        def delete_cb(self, window, action, widget):
 
708
                if self.selected_type == "session":
 
709
                        g_data.delete_session(self.session)
 
710
                        self.session = ""
 
711
                        self.collab = ""
 
712
                        self.snap = ""
 
713
                elif self.selected_type == "collab":
 
714
                        g_data.delete_collab(self.session, self.collab)
 
715
                        self.collab = ""
 
716
                        self.snap = ""
 
717
                elif self.selected_type == "snap":
 
718
                        g_data.delete_snap(self.session, self.collab, self.snap)
 
719
                        self.snap = ""
 
720
                
 
721
                self.update_session_view()
 
722
                self.update_collab_view()
 
723
                self.update_snap_view()
 
724
                self.selected_type = ""
 
725
                
 
726
        def show_status(self, text):
 
727
                mid = self.status_bar.push(self._status_cid, text)
 
728
                if self._status_mid:
 
729
                        self.status_bar.remove(self._status_cid, self._status_mid)
 
730
                self._status_mid = mid
 
731
        
 
732
        def __init__(self):
 
733
                self.selected_type = ""
 
734
                self.session = ""
 
735
                self.collab = g_data.get_user()
 
736
                self.snap = ""
 
737
                
 
738
                self.preferences = 0
 
739
                self.add_collab = 0
 
740
                self.add_session = 0
 
741
                
 
742
                self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
743
                self.window.set_title('Session Exchange')
 
744
                self.window.set_size_request(400, 200)
 
745
                self.window.connect('destroy', lambda win: gtk.main_quit())
 
746
                self.window.set_position(gtk.WIN_POS_MOUSE)
 
747
                
 
748
                accel_group = gtk.AccelGroup()
 
749
                self.window.add_accel_group(accel_group)
 
750
                
 
751
                main_box = gtk.VBox()
 
752
                self.window.add(main_box)
 
753
                
 
754
                menu_items = (
 
755
                        ('/_File',            None,         None,             0, '<Branch>'),
 
756
                        ('/File/_Add Session...','<control>A', self.add_session_cb, 0, ''),
 
757
                        ('/File/Create _Session...', '<control>S', self.create_session_cb, 0, ''),
 
758
                        ('/File/sep1',        None,         None,             0, '<Separator>'),
 
759
                        ('/File/_Quit',       '<control>Q', gtk.main_quit,     0, '<StockItem>', gtk.STOCK_QUIT),
 
760
                        ('/_Edit',            None,         None,             0, '<Branch>' ),
 
761
                        ('/Edit/Cu_t',        '<control>X', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_CUT),
 
762
                        ('/Edit/_Copy',       '<control>C', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_COPY),
 
763
                        ('/Edit/_Paste',      '<control>V', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_PASTE),
 
764
                        ('/Edit/_Delete',     None,         self.delete_cb, 0, '<StockItem>', gtk.STOCK_DELETE),
 
765
                        ('/Edit/sep1',        None,         None,             0, '<Separator>'),
 
766
                        ('/Edit/Add Colla_borator...','<control>B', self.add_collaborator_cb,0,''),
 
767
                        ('/Edit/_Fetch Snapshot','<control>F', self.fetch_snapshot_cb,0,''),
 
768
                        ('/Edit/sep1',        None,         None,             0, '<Separator>'),
 
769
                        ('/Edit/_Preferences...','<control>P', self.preferences_cb, 0, '')
 
770
                )
 
771
                
 
772
                #need to hold a reference to the item_factory or the menubar will disappear.
 
773
                self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group)
 
774
                self.item_factory.create_items(menu_items, self.window)
 
775
                main_box.pack_start(self.item_factory.get_widget('<main>'), False)
 
776
                
 
777
                pane1 = gtk.HPaned()
 
778
                pane2 = gtk.HPaned()
 
779
                pane1.pack2(pane2, True, False)
 
780
                
 
781
                scroll1 = gtk.ScrolledWindow()
 
782
                scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
783
                pane1.pack1(scroll1, True, False)
 
784
                scroll2 = gtk.ScrolledWindow()
 
785
                scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
786
                pane2.pack1(scroll2, True, False)
 
787
                scroll3 = gtk.ScrolledWindow()
 
788
                scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
789
                pane2.pack2(scroll3, True, False)
 
790
                
 
791
                self.session_model = gtk.ListStore(gobject.TYPE_STRING)
 
792
                view1 = gtk.TreeView(self.session_model)
 
793
                column1 = gtk.TreeViewColumn('Sessions', gtk.CellRendererText(), text=0)
 
794
                view1.append_column(column1)
 
795
                self.session_selection = view1.get_selection()
 
796
                self.session_selection.connect("changed", self.cb_session_selection_changed)
 
797
                scroll1.add(view1)
 
798
                
 
799
                self.update_session_view()
 
800
                
 
801
                self.collab_model = gtk.ListStore(gobject.TYPE_STRING)
 
802
                view2 = gtk.TreeView(self.collab_model)
 
803
                column2 = gtk.TreeViewColumn('Collaborators', gtk.CellRendererText(), text=0)
 
804
                view2.append_column(column2)
 
805
                self.collab_selection = view2.get_selection()
 
806
                self.collab_selection.connect("changed", self.cb_collab_selection_changed)
 
807
                scroll2.add(view2)
 
808
                
 
809
                self.snap_model = gtk.ListStore(gobject.TYPE_STRING)
 
810
                view3 = gtk.TreeView(self.snap_model)
 
811
                column3 = gtk.TreeViewColumn('Snapshots', gtk.CellRendererText(), text=0)
 
812
                view3.append_column(column3)
 
813
                self.snap_selection = view3.get_selection()
 
814
                self.snap_selection.connect("changed", self.cb_snap_selection_changed)
 
815
                scroll3.add(view3)
 
816
                
 
817
                main_box.pack_start(pane1, True, True)
 
818
                
 
819
                self.status_bar = gtk.Statusbar()
 
820
                main_box.pack_start(self.status_bar, False)
 
821
                self._status_cid = self.status_bar.get_context_id('display')
 
822
                self._status_mid = ''
 
823
                
 
824
                self.window.show_all()
 
825
 
 
826
def print_help():
 
827
        print """
 
828
        -h, --help
 
829
        -n, --no-server          Only act as a client
 
830
        -p, --port <port number> Defaults to 8970
 
831
        -d, --debug              Infers audio files.  For debugging Ardour.
 
832
        -v, --version            Version
 
833
        """
 
834
        sys.exit(2)
 
835
 
 
836
def main():
 
837
        try:
 
838
                opts, args = getopt.getopt(sys.argv[1:], "hp:ndv", ["help", "port=", "no-server", "debug", "version"])
 
839
        except getopt.GetoptError:
 
840
                print_help()
 
841
        
 
842
        server = True
 
843
        for o, a in opts:
 
844
                if o in ("-h", "--help"):
 
845
                        print_help()
 
846
                if o in ("-d", "--debug"):
 
847
                        g_display.window.set_title('Session Exchange: Debug Mode')
 
848
                        g_data.debug_mode = True
 
849
                if o in ("-p", "--port"):
 
850
                        g_data.port = int(a)
 
851
                if o in ("-n", "--no-server"):
 
852
                        server = False
 
853
                if o in ("-v", "--version"):
 
854
                        print VERSION
 
855
                        sys.exit(2)
 
856
        
 
857
        if (server):
 
858
                try:
 
859
                        reactor.listenTCP(g_data.port, ExchangeServerFactory())
 
860
                except twisted.internet.error.CannotListenError:
 
861
                        print "Can not listen on a port number under 1024 unless run as root"
 
862
                        sys.exit(2)
 
863
 
 
864
        reactor.run()
 
865
 
 
866
        g_data.close()
 
867
 
 
868
# global objects
 
869
g_data = Data()
 
870
g_display = ArdourShareWindow()
 
871
 
 
872
if __name__ == '__main__':
 
873
        main()