3 # LADI Session Handler (ladish)
5 # Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 #*************************************************************************
8 # This file contains code of the commandline control app
9 #*************************************************************************
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.
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.
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.
26 service_name
= 'org.ladish'
28 control_object_path
= "/org/ladish/Control"
29 studio_object_path
= "/org/ladish/Studio"
31 control_interface_name
= 'org.ladish.Control'
32 studio_interface_name
= 'org.ladish.Studio'
33 app_supervisor_interface_name
= 'org.ladish.AppSupervisor'
34 room_interface_name
= 'org.ladish.Room'
35 patchbay_interface_name
= 'org.jackaudio.JackPatchbay'
40 from traceback
import print_exc
44 def bool_convert(str_value
):
45 if str_value
.lower() == "false":
48 if str_value
.lower() == "off":
51 if str_value
.lower() == "no":
57 if str_value
.lower() == "(null)":
60 return bool(str_value
)
62 def 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
)
69 def dbus_type_to_type_string(dbus_value
):
70 if type(dbus_value
) == dbus
.Boolean
:
72 if type(dbus_value
) == dbus
.Int32
:
74 if type(dbus_value
) == dbus
.UInt32
:
76 if type(dbus_value
) == dbus
.Byte
:
78 if type(dbus_value
) == dbus
.String
:
81 return None # throw exception here?
83 def dbus_typesig_to_type_string(type_char
):
84 type_char
= str(type_char
)
96 print('unknown dbus typesig')
97 return None # throw exception here?
99 def parse_new_app_args(params_array
):
101 cmdline
= params_array
[0]
108 if index
< len(params_array
):
109 if params_array
[index
] == '-':
110 return index
+ 1, cmdline
, name
, level
, term
111 name
= params_array
[index
]
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
])
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':
128 if index
< len(params_array
) and params_array
[index
] == '-':
131 return index
, cmdline
, name
, level
, term
133 def add_app(obj
, cmdline
, name
, level
, term
):
134 dbus
.Interface(obj
, app_supervisor_interface_name
).RunCustom(term
, cmdline
, name
, level
)
136 def get_room_obj_by_name(bus
, studio_iface
, room_name
):
137 for room
in studio_iface
.GetRoomList():
140 name
= room
[1]["name"]
141 if name
== room_name
:
142 return bus
.get_object(service_name
, opath
)
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]:
151 if (port_flags
& 1) != 0:
153 elif (port_flags
& 2) != 0:
154 port_flags
= "output"
156 port_flags
= "unknown"
164 port_type
= "unknown"
166 print ' "%s" [%s %s]' % (port
[1], port_flags
, port_type
)
169 if len(graph
[2]) == 1:
170 print "1 connection:"
172 print "%u connections:" % len(graph
[2])
173 for connection
in graph
[2]:
174 print '"%s":"%s" -> "%s":"%s"' % (connection
[1], connection
[3], connection
[5], connection
[7])
176 print "0 connections."
179 if len(sys
.argv
) == 1:
180 argv0
= os
.path
.basename(sys
.argv
[0])
181 print("Usage: %s [command] [command] ..." % argv0
)
183 print(" exit - exit ladish dbus service")
184 print(" slist - list studios")
185 print(" alist - list apps")
186 print(" sload <studioname> - load studio")
187 print(" sdel <studioname> - delete studio")
188 print(" snew [studioname] - new studio")
189 print(" sisloaded - is studio loaded?")
190 print(" sname - get studio name")
191 print(" ssave - save studio")
192 print(" sunload - unload studio")
193 print(" srename <studioname> - rename studio")
194 print(" sstart - start studio")
195 print(" sstop - stop studio")
196 print(" rtlist - list room templates")
197 print(" rtdel <roomtemplatename> - delete room template")
198 print(" rtnew <roomtemplatename> - create new room template")
199 print(" snewroom <rname> <rtname> - create new studio room")
200 print(" srlist - list studio rooms")
201 print(" sdelroom <rname> - delete studio room")
202 print(" pload <rname> <proj_dir> - load project into room")
203 print(" punload <rname> - unload project from room")
204 print(" psave <rname> - save project")
205 print(" psaveas <rname> <proj_dir> <proj_name> - save as project")
206 print(" snewapp <appargs> - add new app to studio (see below for more info)")
207 print(" rnewapp <rname> <appargs> - add new app to room (see below for more info)")
208 print(" sgdump - studio graph dump")
209 print(" rgdump <rname> - room graph dump")
210 print(" sconnect <client1> <port1> <client2> <port2> - connect ports in studio");
211 print(" sdisconnect <client1> <port1> <client2> <port2> - disconnect ports in studio");
212 print(" rconnect <rname> <client1> <port1> <client2> <port2> - connect ports in studio");
213 print(" rdisconnect <rname> <client1> <port1> <client2> <port2> - disconnect ports in room");
215 print("Add new app arguments:");
216 print(" <commandline> [<name> [<level>] [term]] [-]");
218 print(" <commandline> - the commandline to execut");
219 print(" <name> - app name");
220 print(" <level> - level, default is 0");
221 print(" term - if specified, app will be run in terminal");
222 print(" - - marks end of new app params, useful if there are other commands following");
226 print(" * Add to studio jack_mixer instance named \"mixer\", at level 1, without terminal");
228 print(" $ %s snewapp jack_mixer mixer 1" % argv0
);
230 print(" * Add to room \"main\" fluidjack instance named \"fluid\", at level 0, with terminal");
232 print(" $ %s rnewapp main \"fluidjack FluidR3.SF2\" fluid 0 term" % argv0
);
236 bus
= dbus
.SessionBus()
242 while index
< len(sys
.argv
):
243 arg
= sys
.argv
[index
]
247 control_obj
= bus
.get_object(service_name
, control_object_path
)
248 control_iface
= dbus
.Interface(control_obj
, control_interface_name
)
254 # we have deactivated the object and we need to get new connection if there are more commands
258 print("--- studio list")
259 for studio
in control_iface
.GetStudioList():
261 mtime
= studio
[1]['Modification Time']
262 print('"%s" last modified on %s' % (name
, time
.ctime(mtime
)))
264 print("--- app list")
265 for app
in control_iface
.GetApplicationList():
268 print("--- studio load")
269 if index
>= len(sys
.argv
):
270 print("load studio command requires studio name argument")
273 arg
= sys
.argv
[index
]
277 #open_options["option1"] = "asd"
278 #open_options["option2"] = True
280 control_iface
.LoadStudio(arg
, open_options
)
282 print("--- studio delete")
283 if index
>= len(sys
.argv
):
284 print("delete studio command requires studio name argument")
287 arg
= sys
.argv
[index
]
290 control_iface
.DeleteStudio(arg
)
292 print("--- studio new")
294 if index
< len(sys
.argv
):
295 name
= sys
.argv
[index
]
298 control_iface
.NewStudio(name
)
299 elif arg
== 'sisloaded':
300 print("--- studio is loaded")
301 if control_iface
.IsStudioLoaded():
305 elif arg
== 'rtlist':
306 print("--- list room templates")
307 for studio
in control_iface
.GetRoomTemplateList():
311 print("--- create new room template")
312 if index
>= len(sys
.argv
):
313 print("create new room template command requires room template name argument")
316 arg
= sys
.argv
[index
]
319 control_iface
.CreateRoomTemplate(arg
)
321 print("--- delete room template")
322 if index
>= len(sys
.argv
):
323 print("delete room template command requires room template name argument")
326 arg
= sys
.argv
[index
]
329 control_iface
.DeleteRoomTemplate(arg
)
332 studio_obj
= bus
.get_object(service_name
, studio_object_path
)
333 studio_iface
= dbus
.Interface(studio_obj
, studio_interface_name
)
336 print("--- studio get name")
337 print("\"%s\"" % studio_iface
.GetName())
339 print("--- studio save")
341 elif arg
== 'sunload':
342 print("--- studio unload")
343 studio_iface
.Unload()
346 elif arg
== 'srename':
347 print("--- studio rename")
348 if index
>= len(sys
.argv
):
349 print("rename studio command requires studio name argument")
352 arg
= sys
.argv
[index
]
355 studio_iface
.Rename(arg
)
356 elif arg
== 'sstart':
357 print("--- studio start")
360 print("--- studio stop")
362 elif arg
== 'snewroom':
363 print("--- create new studio room")
364 if index
+ 1 >= len(sys
.argv
):
365 print("creation of studio room requires room name and room template name arguments")
368 room_name
= sys
.argv
[index
]
370 room_template_name
= sys
.argv
[index
]
373 studio_iface
.CreateRoom(room_name
, room_template_name
)
374 elif arg
== 'srlist':
375 print("--- list studio rooms")
376 for room
in studio_iface
.GetRoomList():
379 name
= room
[1]["name"]
380 if room
[1].has_key("template"):
381 template
= str(room
[1]["template"])
386 print('"%s" from template "%s" (%s)' % (name
, template
, opath
))
388 print('"%s" (%s)' % (name
, opath
))
389 elif arg
== 'sdelroom':
390 print("--- delete studio room")
391 if index
>= len(sys
.argv
):
392 print("delete studio room command requires room name argument")
395 arg
= sys
.argv
[index
]
398 studio_iface
.DeleteRoom(arg
)
400 print("--- load project")
401 if index
+ 1 >= len(sys
.argv
):
402 print("load project command requires room name and project dir arguments")
405 room_name
= sys
.argv
[index
]
407 project_dir
= sys
.argv
[index
]
410 dbus
.Interface(get_room_obj_by_name(bus
, studio_iface
, room_name
), room_interface_name
).LoadProject(project_dir
)
411 elif arg
== 'punload':
412 print("--- unload project")
413 if index
>= len(sys
.argv
):
414 print("load project command requires room name argument")
417 room_name
= sys
.argv
[index
]
420 dbus
.Interface(get_room_obj_by_name(bus
, studio_iface
, room_name
), room_interface_name
).UnloadProject()
422 print("--- save project")
423 if index
>= len(sys
.argv
):
424 print("save project command requires room name argument")
427 room_name
= sys
.argv
[index
]
430 dbus
.Interface(get_room_obj_by_name(bus
, studio_iface
, room_name
), room_interface_name
).SaveProject("", "")
431 elif arg
== 'psaveas':
432 print("--- save project as")
433 if index
+ 2 >= len(sys
.argv
):
434 print("save project as command requires room name, project dir and project name arguments")
437 room_name
= sys
.argv
[index
]
439 project_dir
= sys
.argv
[index
]
441 project_name
= sys
.argv
[index
]
444 dbus
.Interface(get_room_obj_by_name(bus
, studio_iface
, room_name
), room_interface_name
).SaveProject(project_dir
, project_name
)
445 elif arg
== 'snewapp':
446 print("--- new studio app")
447 count
, cmdline
, name
, level
, term
= parse_new_app_args(sys
.argv
[index
:])
449 add_app(studio_obj
, cmdline
, name
, level
, term
)
450 elif arg
== 'rnewapp':
451 print("--- new room app")
452 arg
= sys
.argv
[index
]
455 count
, cmdline
, name
, level
, term
= parse_new_app_args(sys
.argv
[index
:])
458 add_app(get_room_obj_by_name(bus
, studio_iface
, arg
), cmdline
, name
, level
, term
)
459 elif arg
== "sgdump":
460 print('--- dump studio graph')
461 dump_graph(studio_obj
)
462 elif arg
== "rgdump":
463 if index
>= len(sys
.argv
):
464 print("rconnect command requires rname, client1, port1, client2 and port2 arguments")
466 rname
= sys
.argv
[index
]
468 print('--- dump room "' + rname
+ '" graph')
469 room_obj
= get_room_obj_by_name(bus
, studio_obj
, rname
)
471 elif arg
== "sconnect":
472 if index
+ 4 > len(sys
.argv
):
473 print("sconnect command requires client1, port1, client2 and port2 arguments")
476 p1
= sys
.argv
[index
+ 1]
477 c2
= sys
.argv
[index
+ 2]
478 p2
= sys
.argv
[index
+ 3]
480 print('--- connect studio port "' + c1
+ '":"' + p1
+ '" to "' + c2
+ '":"' + p2
+ '"')
481 patchbay_iface
= dbus
.Interface(studio_obj
, patchbay_interface_name
)
482 patchbay_iface
.ConnectPortsByName(c1
, p1
, c2
, p2
)
483 elif arg
== "sdisconnect":
484 if index
+ 4 > len(sys
.argv
):
485 print("sdisconnect command requires client1, port1, client2 and port2 arguments")
488 p1
= sys
.argv
[index
+ 1]
489 c2
= sys
.argv
[index
+ 2]
490 p2
= sys
.argv
[index
+ 3]
492 print('--- disconnect studio port "' + c2
+ '":"' + p2
+ '" from "' + c1
+ '":"' + p1
+ '"')
493 patchbay_iface
= dbus
.Interface(studio_obj
, patchbay_interface_name
)
494 patchbay_iface
.DisconnectPortsByName(c1
, p1
, c2
, p2
)
495 elif arg
== "rconnect":
496 if index
+ 5 > len(sys
.argv
):
497 print("rconnect command requires rname, client1, port1, client2 and port2 arguments")
499 rname
= sys
.argv
[index
]
500 c1
= sys
.argv
[index
+ 1]
501 p1
= sys
.argv
[index
+ 2]
502 c2
= sys
.argv
[index
+ 3]
503 p2
= sys
.argv
[index
+ 4]
505 print('--- connect room "' + rname
+ '" port "' + c1
+ '":"' + p1
+ '" to "' + c2
+ '":"' + p2
+ '"')
506 room_obj
= get_room_obj_by_name(bus
, studio_iface
, rname
)
507 patchbay_iface
= dbus
.Interface(room_obj
, patchbay_interface_name
)
508 patchbay_iface
.ConnectPortsByName(c1
, p1
, c2
, p2
)
509 elif arg
== "rdisconnect":
510 if index
+ 5 > len(sys
.argv
):
511 print("rdisconnect command requires rname, client1, port1, client2 and port2 arguments")
513 rname
= sys
.argv
[index
]
514 c1
= sys
.argv
[index
+ 1]
515 p1
= sys
.argv
[index
+ 2]
516 c2
= sys
.argv
[index
+ 3]
517 p2
= sys
.argv
[index
+ 4]
519 print('--- disconnect room "' + rname
+ '" port "' + c2
+ '":"' + p2
+ '" from "' + c1
+ '":"' + p1
+ '"')
520 room_obj
= get_room_obj_by_name(bus
, studio_iface
, rname
)
521 patchbay_iface
= dbus
.Interface(room_obj
, patchbay_interface_name
)
522 patchbay_iface
.DisconnectPortsByName(c1
, p1
, c2
, p2
)
524 print("Unknown command '%s'" % arg
)
525 except dbus
.DBusException
, e
:
526 print("DBus exception: %s" % str(e
))
528 if __name__
== '__main__':