root/ladish_control @ 4f7b78388fa1a85e4868c979c0b8bdbeac685417

Revision 4f7b78388fa1a85e4868c979c0b8bdbeac685417, 21.1 KB (checked in by Nedko Arnaudov <nedko@…>, 2 years ago)

ladish_control: vgraph connection management. #125

  • Property mode set to 100755
Line 
1#!/usr/bin/env python
2#
3# LADI Session Handler (ladish)
4#
5# Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6#
7#*************************************************************************
8# This file contains code of the commandline control app
9#*************************************************************************
10#
11# LADI Session Handler is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# LADI Session Handler is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23# or write to the Free Software Foundation, Inc.,
24# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25
26service_name = 'org.ladish'
27
28control_object_path = "/org/ladish/Control"
29studio_object_path = "/org/ladish/Studio"
30
31control_interface_name = 'org.ladish.Control'
32studio_interface_name = 'org.ladish.Studio'
33app_supervisor_interface_name = 'org.ladish.AppSupervisor'
34room_interface_name = 'org.ladish.Room'
35patchbay_interface_name = 'org.jackaudio.JackPatchbay'
36
37import sys
38import os
39import time
40from traceback import print_exc
41
42import dbus
43
44def bool_convert(str_value):
45    if str_value.lower() == "false":
46        return False
47
48    if str_value.lower() == "off":
49        return False
50
51    if str_value.lower() == "no":
52        return False
53
54    if str_value == "0":
55        return False
56
57    if str_value.lower() == "(null)":
58        return False
59
60    return bool(str_value)
61
62def dbus_type_to_python_type(dbus_value):
63    if type(dbus_value) == dbus.Boolean:
64        return bool(dbus_value)
65    if type(dbus_value) == dbus.Int32 or type(dbus_value) == dbus.UInt32:
66        return int(dbus_value)
67    return dbus_value
68
69def dbus_type_to_type_string(dbus_value):
70    if type(dbus_value) == dbus.Boolean:
71        return "bool"
72    if type(dbus_value) == dbus.Int32:
73        return "sint"
74    if type(dbus_value) == dbus.UInt32:
75        return "uint"
76    if type(dbus_value) == dbus.Byte:
77        return "char"
78    if type(dbus_value) == dbus.String:
79        return "str"
80
81    return None                         # throw exception here?
82
83def dbus_typesig_to_type_string(type_char):
84    type_char = str(type_char)
85    if type_char == 'i':
86        return "sint"
87    if type_char == 'u':
88        return "uint"
89    if type_char == 'y':
90        return "char"
91    if type_char == 's':
92        return "str"
93    if type_char == 'b':
94        return "bool"
95
96    print('unknown dbus typesig')
97    return None                         # throw exception here?
98
99def parse_new_app_args(params_array):
100    #print params_array
101    cmdline = params_array[0]
102    index = 1
103
104    name = ''
105    level = 0
106    term = False
107
108    if index < len(params_array):
109        if params_array[index] == '-':
110            return index + 1, cmdline, name, level, term
111        name = params_array[index]
112        index += 1
113
114    if index < len(params_array):
115        if params_array[index] == '-':
116            return index + 1, cmdline, name, level, term
117        # direct conversion to dbus.Byte is wrong because ord() is used ("1" -> 0x31 instead of "1" -> 0x01)
118        level = int(params_array[index])
119        index += 1
120
121    if index < len(params_array):
122        if params_array[index] == '-':
123            return index + 1, cmdline, name, level, term
124        if params_array[index] == 'term':
125            term = True
126            index += 1
127
128    if index < len(params_array) and  params_array[index] == '-':
129        index += 1
130
131    return index, cmdline, name, level, term
132
133def add_app(obj, cmdline, name, level, term):
134    dbus.Interface(obj, app_supervisor_interface_name).RunCustom(term, cmdline, name, level)
135
136def get_room_obj_by_name(bus, studio_iface, room_name):
137    for room in studio_iface.GetRoomList():
138        #print repr(room)
139        opath = room[0]
140        name = room[1]["name"]
141        if name == room_name:
142            return bus.get_object(service_name, opath)
143
144def dump_graph(obj):
145    patchbay_iface = dbus.Interface(obj, patchbay_interface_name)
146    graph = patchbay_iface.GetGraph(0)
147    for client in graph[1]:
148        print '"%s"' % client[1]
149        for port in client[2]:
150            print '  "%s"' % port[1]
151    print
152    if len(graph[2]):
153        if len(graph[2]) == 1:
154            print "1 connection:"
155        else:
156            print "%u connections:" % len(graph[2])
157        for connection in graph[2]:
158            print '"%s":"%s" -> "%s":"%s"' % (connection[1], connection[3], connection[5], connection[7])
159    else:
160        print "0 connections."
161
162def main():
163    if len(sys.argv) == 1:
164        argv0 = os.path.basename(sys.argv[0])
165        print("Usage: %s [command] [command] ..." % argv0)
166        print("Commands:")
167        print("    exit                      - exit ladish dbus service")
168        print("    slist                     - list studios")
169        print("    alist                     - list apps")
170        print("    sload <studioname>        - load studio")
171        print("    sdel <studioname>         - delete studio")
172        print("    snew [studioname]         - new studio")
173        print("    sisloaded                 - is studio loaded?")
174        print("    sname                     - get studio name")
175        print("    ssave                     - save studio")
176        print("    sunload                   - unload studio")
177        print("    srename <studioname>      - rename studio")
178        print("    sstart                    - start studio")
179        print("    sstop                     - stop studio")
180        print("    rtlist                    - list room templates")
181        print("    rtdel <roomtemplatename>  - delete room template")
182        print("    rtnew <roomtemplatename>  - create new room template")
183        print("    snewroom <rname> <rtname> - create new studio room")
184        print("    srlist                    - list studio rooms")
185        print("    sdelroom <rname>          - delete studio room")
186        print("    pload <rname> <proj_dir>  - load project into room")
187        print("    punload <rname>           - unload project from room")
188        print("    psave <rname>             - save project")
189        print("    psaveas <rname> <proj_dir> <proj_name>  - save as project")
190        print("    snewapp <appargs>         - add new app to studio (see below for more info)")
191        print("    rnewapp <rname> <appargs> - add new app to room (see below for more info)")
192        print("    sgdump                    - studio graph dump")
193        print("    rgdump <rname>            - room graph dump")
194        print("    sconnect <client1> <port1> <client2> <port2>            - connect ports in studio");
195        print("    sdisconnect <client1> <port1> <client2> <port2>         - disconnect ports in studio");
196        print("    rconnect <rname> <client1> <port1> <client2> <port2>    - connect ports in studio");
197        print("    rdisconnect <rname> <client1> <port1> <client2> <port2> - disconnect ports in room");
198        print("");
199        print("Add new app arguments:");
200        print("    <commandline> [<name> [<level>] [term]] [-]");
201        print("");
202        print("    <commandline> - the commandline to execut");
203        print("    <name>  - app name");
204        print("    <level> - level, default is 0");
205        print("    term    - if specified, app will be run in terminal");
206        print("    -       - marks end of new app params, useful if there are other commands following");
207        print("");
208        print("Examples:");
209        print("");
210        print(" * Add to studio jack_mixer instance named \"mixer\", at level 1, without terminal");
211        print("");
212        print("    $ %s snewapp jack_mixer mixer 1" % argv0);
213        print("");
214        print(" * Add to room \"main\" fluidjack instance named \"fluid\", at level 0, with terminal");
215        print("");
216        print("    $ %s rnewapp main \"fluidjack FluidR3.SF2\" fluid 0 term" % argv0);
217        print("");
218        sys.exit(0)
219   
220    bus = dbus.SessionBus()
221    control_obj = None
222    studio_obj = None
223
224    # check arguments
225    index = 1
226    while index < len(sys.argv):
227        arg = sys.argv[index]
228        index += 1
229        try:
230            if not control_obj:
231                control_obj = bus.get_object(service_name, control_object_path)
232                control_iface = dbus.Interface(control_obj, control_interface_name)
233           
234            if arg == "exit":
235                print("--- exit")
236                control_iface.Exit()
237                time.sleep(1)
238                # we have deactivated the object and we need to get new connection if there are more commands
239                control_obj = None
240                control_iface = None
241            elif arg == 'slist':
242                print("--- studio list")
243                for studio in control_iface.GetStudioList():
244                    name = studio[0]
245                    mtime = studio[1]['Modification Time']
246                    print('"%s" last modified on %s' % (name, time.ctime(mtime)))
247            elif arg == 'alist':
248                print("--- app list")
249                for app in control_iface.GetApplicationList():
250                    print(app)
251            elif arg == 'sload':
252                print("--- studio load")
253                if index >= len(sys.argv):
254                    print("load studio command requires studio name argument")
255                    sys.exit()
256
257                arg = sys.argv[index]
258                index += 1
259
260                open_options = {}
261                #open_options["option1"] = "asd"
262                #open_options["option2"] = True
263
264                control_iface.LoadStudio(arg, open_options)
265            elif arg == 'sdel':
266                print("--- studio delete")
267                if index >= len(sys.argv):
268                    print("delete studio command requires studio name argument")
269                    sys.exit()
270
271                arg = sys.argv[index]
272                index += 1
273
274                control_iface.DeleteStudio(arg)
275            elif arg == 'snew':
276                print("--- studio new")
277                name = ""
278                if index < len(sys.argv):
279                    name = sys.argv[index]
280                    index += 1
281
282                control_iface.NewStudio(name)
283            elif arg == 'sisloaded':
284                print("--- studio is loaded")
285                if control_iface.IsStudioLoaded():
286                    print("yes")
287                else:
288                    print("no")
289            elif arg == 'rtlist':
290                print("--- list room templates")
291                for studio in control_iface.GetRoomTemplateList():
292                    name = studio[0]
293                    print('"%s"' % name)
294            elif arg == 'rtnew':
295                print("--- create new room template")
296                if index >= len(sys.argv):
297                    print("create new room template command requires room template name argument")
298                    sys.exit()
299
300                arg = sys.argv[index]
301                index += 1
302
303                control_iface.CreateRoomTemplate(arg)
304            elif arg == 'rtdel':
305                print("--- delete room template")
306                if index >= len(sys.argv):
307                    print("delete room template command requires room template name argument")
308                    sys.exit()
309
310                arg = sys.argv[index]
311                index += 1
312
313                control_iface.DeleteRoomTemplate(arg)
314            else:
315                if not studio_obj:
316                    studio_obj = bus.get_object(service_name, studio_object_path)
317                    studio_iface = dbus.Interface(studio_obj, studio_interface_name)
318
319                if arg == 'sname':
320                    print("--- studio get name")
321                    print("\"%s\"" % studio_iface.GetName())
322                elif arg == 'ssave':
323                    print("--- studio save")
324                    studio_iface.Save()
325                elif arg == 'sunload':
326                    print("--- studio unload")
327                    studio_iface.Unload()
328                    studio_obj = None
329                    studio_iface = None
330                elif arg == 'srename':
331                    print("--- studio rename")
332                    if index >= len(sys.argv):
333                        print("rename studio command requires studio name argument")
334                        sys.exit()
335
336                    arg = sys.argv[index]
337                    index += 1
338
339                    studio_iface.Rename(arg)
340                elif arg == 'sstart':
341                    print("--- studio start")
342                    studio_iface.Start()
343                elif arg == 'sstop':
344                    print("--- studio stop")
345                    studio_iface.Stop()
346                elif arg == 'snewroom':
347                    print("--- create new studio room")
348                    if index + 1 >= len(sys.argv):
349                        print("creation of studio room requires room name and room template name arguments")
350                        sys.exit()
351
352                    room_name = sys.argv[index]
353                    index += 1
354                    room_template_name = sys.argv[index]
355                    index += 1
356
357                    studio_iface.CreateRoom(room_name, room_template_name)
358                elif arg == 'srlist':
359                    print("--- list studio rooms")
360                    for room in studio_iface.GetRoomList():
361                        #print repr(room)
362                        opath = room[0]
363                        name = room[1]["name"]
364                        if room[1].has_key("template"):
365                            template = str(room[1]["template"])
366                        else:
367                            template = None
368
369                        if template:
370                            print('"%s" from template "%s" (%s)' % (name, template, opath))
371                        else:
372                            print('"%s" (%s)' % (name, opath))
373                elif arg == 'sdelroom':
374                    print("--- delete studio room")
375                    if index >= len(sys.argv):
376                        print("delete studio room command requires room name argument")
377                        sys.exit()
378
379                    arg = sys.argv[index]
380                    index += 1
381
382                    studio_iface.DeleteRoom(arg)
383                elif arg == 'pload':
384                    print("--- load project")
385                    if index + 1 >= len(sys.argv):
386                        print("load project command requires room name and project dir arguments")
387                        sys.exit()
388
389                    room_name = sys.argv[index]
390                    index += 1
391                    project_dir = sys.argv[index]
392                    index += 1
393
394                    dbus.Interface(get_room_obj_by_name(bus, studio_iface, room_name), room_interface_name).LoadProject(project_dir)
395                elif arg == 'punload':
396                    print("--- unload project")
397                    if index >= len(sys.argv):
398                        print("load project command requires room name argument")
399                        sys.exit()
400
401                    room_name = sys.argv[index]
402                    index += 1
403
404                    dbus.Interface(get_room_obj_by_name(bus, studio_iface, room_name), room_interface_name).UnloadProject()
405                elif arg == 'psave':
406                    print("--- save project")
407                    if index >= len(sys.argv):
408                        print("save project command requires room name argument")
409                        sys.exit()
410
411                    room_name = sys.argv[index]
412                    index += 1
413
414                    dbus.Interface(get_room_obj_by_name(bus, studio_iface, room_name), room_interface_name).SaveProject("", "")
415                elif arg == 'psaveas':
416                    print("--- save project as")
417                    if index + 2 >= len(sys.argv):
418                        print("save project as command requires room name, project dir and project name arguments")
419                        sys.exit()
420
421                    room_name = sys.argv[index]
422                    index += 1
423                    project_dir = sys.argv[index]
424                    index += 1
425                    project_name = sys.argv[index]
426                    index += 1
427
428                    dbus.Interface(get_room_obj_by_name(bus, studio_iface, room_name), room_interface_name).SaveProject(project_dir, project_name)
429                elif arg == 'snewapp':
430                    print("--- new studio app")
431                    count, cmdline, name, level, term = parse_new_app_args(sys.argv[index:])
432                    index += count
433                    add_app(studio_obj, cmdline, name, level, term)
434                elif arg == 'rnewapp':
435                    print("--- new room app")
436                    arg = sys.argv[index]
437                    index += 1
438
439                    count, cmdline, name, level, term = parse_new_app_args(sys.argv[index:])
440                    index += count
441
442                    add_app(get_room_obj_by_name(bus, studio_iface, arg), cmdline, name, level, term)
443                elif arg == "sgdump":
444                    print('--- dump studio graph')
445                    dump_graph(studio_obj)
446                elif arg == "rgdump":
447                    if index >= len(sys.argv):
448                        print("rconnect command requires rname, client1, port1, client2 and port2 arguments")
449                        sys.exit()
450                    rname = sys.argv[index]
451                    index += 1
452                    print('--- dump room "' + rname + '" graph')
453                    room_obj = get_room_obj_by_name(bus, studio_obj, rname)
454                    dump_graph(room_obj)
455                elif arg == "sconnect":
456                    if index + 4 > len(sys.argv):
457                        print("sconnect command requires client1, port1, client2 and port2 arguments")
458                        sys.exit()
459                    c1 = sys.argv[index]
460                    p1 = sys.argv[index + 1]
461                    c2 = sys.argv[index + 2]
462                    p2 = sys.argv[index + 3]
463                    index += 4
464                    print('--- connect studio port "' + c1 + '":"' + p1 + '" to "' + c2 + '":"' + p2 + '"')
465                    patchbay_iface = dbus.Interface(studio_obj, patchbay_interface_name)
466                    patchbay_iface.ConnectPortsByName(c1, p1, c2, p2)
467                elif arg == "sdisconnect":
468                    if index + 4 > len(sys.argv):
469                        print("sdisconnect command requires client1, port1, client2 and port2 arguments")
470                        sys.exit()
471                    c1 = sys.argv[index]
472                    p1 = sys.argv[index + 1]
473                    c2 = sys.argv[index + 2]
474                    p2 = sys.argv[index + 3]
475                    index += 4
476                    print('--- disconnect studio port "' + c2 + '":"' + p2 + '" from "' + c1 + '":"' + p1 + '"')
477                    patchbay_iface = dbus.Interface(studio_obj, patchbay_interface_name)
478                    patchbay_iface.DisconnectPortsByName(c1, p1, c2, p2)
479                elif arg == "rconnect":
480                    if index + 5 > len(sys.argv):
481                        print("rconnect command requires rname, client1, port1, client2 and port2 arguments")
482                        sys.exit()
483                    rname = sys.argv[index]
484                    c1 = sys.argv[index + 1]
485                    p1 = sys.argv[index + 2]
486                    c2 = sys.argv[index + 3]
487                    p2 = sys.argv[index + 4]
488                    index += 5
489                    print('--- connect room "' + rname + '" port "' + c1 + '":"' + p1 + '" to "' + c2 + '":"' + p2 + '"')
490                    room_obj = get_room_obj_by_name(bus, studio_iface, rname)
491                    patchbay_iface = dbus.Interface(room_obj, patchbay_interface_name)
492                    patchbay_iface.ConnectPortsByName(c1, p1, c2, p2)
493                elif arg == "rdisconnect":
494                    if index + 5 > len(sys.argv):
495                        print("rdisconnect command requires rname, client1, port1, client2 and port2 arguments")
496                        sys.exit()
497                    rname = sys.argv[index]
498                    c1 = sys.argv[index + 1]
499                    p1 = sys.argv[index + 2]
500                    c2 = sys.argv[index + 3]
501                    p2 = sys.argv[index + 4]
502                    index += 5
503                    print('--- disconnect room "' + rname + '" port "' + c2 + '":"' + p2 + '" from "' + c1 + '":"' + p1 + '"')
504                    room_obj = get_room_obj_by_name(bus, studio_iface, rname)
505                    patchbay_iface = dbus.Interface(room_obj, patchbay_interface_name)
506                    patchbay_iface.DisconnectPortsByName(c1, p1, c2, p2)
507                else:
508                    print("Unknown command '%s'" % arg)
509        except dbus.DBusException, e:
510            print("DBus exception: %s" % str(e))
511
512if __name__ == '__main__':
513    main()
Note: See TracBrowser for help on using the browser.