--- /dev/null
+
+from ziface import ZIface
+import dbus.service
+import dbus.mainloop.glib
+import os
+
+from brisa.core.reactors import GLib2Reactor
+reactor = GLib2Reactor()
+
+from brisa.core import log
+from brisa.core import config
+from brisa.upnp.device import Device
+from brisa.upnp.services.cds import ContentDirectory
+from brisa.upnp.services.connmgr import ConnectionManagerServer
+
+from zukebox_server.services.playlist.zb_playlist import PlayList
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+class ZukeBoxServer(ZIface, dbus.service.Object):
+ """
+ Introduction
+ ============
+ ZukeBox is an abstraction for a JukeBox.
+ How works?
+ In a JukeBox somebody pay and choose a song for play, this way the
+ JukeBox should have default set of songs. ZukeBox has the same idea,
+ except for payment ;) , you can choose a song availble in the server
+ called ZukeBox Server or send a request for server to play your music,
+
+ Thus the clientes should be scan the network and get services availble
+ in ZukeBox Server.
+ Services availble are:
+ 1. Show the songs availble in the ZukeBox Server.
+ 2. Play a song availble.
+ 3. Play a song sent by a control point.
+ Some services will be availble too throught dbus.service a method for
+ rescan the default paths and save in the database.
+ """
+
+ DBUS_SERVICE_NAME = "br.org.zagaia"
+ DBUS_OBJ_PATH = "/br/org/zagaia/ZukeBox"
+ DBUS_IFACE = "br.org.zagaia.ZukeBox"
+
+ plugins_folder = config.get_parameter("zukebox_server", "plugins")
+ plugins_module_path = "zukebox_server.plugins"
+
+ def __init__(self, _server_name, _listen_url):
+ """ ZukeBox Server Construct
+ @param _server_name: Name of the ZukeBox Server
+ @param _listen_url: url to listen for requests
+
+ @type _server_name: string
+ @type _listen_url: string
+ """
+ ZIface.__init__(self)
+ bus = dbus.SessionBus()
+ busname = dbus.service.BusName(self.DBUS_SERVICE_NAME, bus=bus)
+
+ dbus.service.Object.__init__(self, busname, self.DBUS_OBJ_PATH)
+ self.server_name = _server_name
+ self.listen_url = _listen_url
+ self.device = None
+ self.cds = None
+
+ def _create_device(self):
+ model_name = "ZukeBox Server version 0.1"
+ project_page = "http://portal.fucapi.edu.br/nepcomp/zagaia"
+ serial_no = '0000010'
+ model_description = 'A UPnP Audio Server for ZukeBox'
+
+ self.device = Device('urn:schemas-upnp-org:device:ZukeBoxServer:1',
+ self.server_name, force_listen_url=self.listen_url,
+ manufacturer="Zagaia Laboratory and INdT Brazil",
+ manufacturer_url=project_page,
+ model_description=model_description,
+ model_name=model_name, model_number=serial_no,
+ model_url=project_page, serial_number=serial_no)
+
+ def _create_services(self):
+ self.cds = ContentDirectory(self.plugins_folder,
+ self.plugins_module_path)
+ cm = ConnectionManagerServer()
+ mod_path = config.get_parameter("zukebox_server", "home")
+ x_path = os.path.join(mod_path, "xml_descriptions")
+ print x_path
+ playlist = PlayList(positions=10, xml_path=x_path)
+
+ self.device.add_service(self.cds)
+ self.device.add_service(cm)
+ self.device.add_service(playlist)
+
+ def start(self):
+ """Start the ZukeBox Server"""
+ self._create_device()
+ self._create_services()
+ self.device.start()
+ reactor.add_after_stop_func(self.device.stop)
+ reactor.main()
+
+ # DBUS
+ @dbus.service.method(DBUS_IFACE)
+ def halt(self):
+ reactor.main_quit()
+
+ @dbus.service.method(DBUS_IFACE)
+ def rescan_audio_folder(self):
+ if not self.cds:
+ return
+ pm = self.cds.control_controller.plugin_manager
+ if not "audio_library" in pm.plugins_instances:
+ return
+ pm.plugins_instances["audio_library"].process_audio_folder()
+
+ @dbus.service.method(DBUS_IFACE)
+ def reload_config(self):
+ config.manager.update()
+
+
+
--- /dev/null
+
+import os
+#from brisa.core.reactors import install_default_reactor
+#reactor = install_default_reactor()
+
+from brisa.core import log
+from brisa.upnp.device import Service, ServiceController
+
+pjoin = os.path.join
+
+class PlayListOutBoundExcept(Exception):
+ def __rep__(self):
+ return "Play List Out of Bounds!"
+
+
+
+class PlayList(Service):
+ """Class PlayList
+ Introduction
+ ============
+ Implements a playlist for ZukeBox server.
+ """
+
+ service_type = "urn:schemas-upnp-org:service:PlayList:1"
+ service_name = "PlayList"
+
+ def __init__(self, positions=10, xml_path=''):
+ scpd_path = pjoin(xml_path, "zukebox-playlist-scpd.xml")
+ Service.__init__(self, self.service_name, self.service_type, '', scpd_path,
+ PlayListControl(positions, self.service_type))
+
+ def get_playlist(self):
+ return self.control_controller.get_playlist()
+
+class PlayListControl(ServiceController):
+
+ def __init__(self, positions, serv_type):
+ ServiceController.__init__(self, serv_type)
+ self.positions = positions
+ self.list = []
+ self.current = 0
+ self.prev = self.current
+ self.next = None
+ self.from_name = None
+ self.to_name = None
+ self.current_uri = None
+ self.current_uri_metadata = None
+
+ def soap_IsLocked(self, *args, **kwargs):
+ locked = True
+ if not len(self.list) == self.positions:
+ locked = False
+ rt = {"Locked": locked}
+ return {"IsLockedResponse": rt}
+
+ def soap_IsAvailble(self, *args, **kwargs):
+ availble = False
+ if not len(self.list) == 0:
+ availble = True
+ rt = {"Availble": availble}
+ return {"IsAvailbleResponse": rt}
+
+ def soap_IsAvailble(self, *args, **kwargs):
+ availble = False
+ if not len(self.list) == 0:
+ availble = True
+ rt = {"Availble": availble}
+ return {"IsAvailbleResponse": rt}
+
+ def soap_Append(self, *args, **kwargs):
+ """Put a object in the playlist
+ """
+ if not self.is_locked():
+ self.current_uri = kwargs["CurrentURI"]
+ self.current_uri_metadata = kwargs["CurrentURIMetaData"]
+ self.from_name = kwargs["FromName"]
+ self.to_name = kwargs["ToName"]
+ self.list.append(self.current_uri)
+
+ return {"Append": {}}
+ else:
+ raise PlayListOutBoundExcept()
+
+ def soap_Drop(self, *args, **kwargs):
+ """Pop the object at position passed by index
+ """
+ if self.is_availble():
+ index = kwargs["Index"]
+ self.list.pop(index)
+ return {"Drop": {}}
+ else:
+ raise PlayListOutBoundExcept()
+
+ def soap_GetSizeOfPlayList(self, *args, **kwargs):
+ """Return the size of playlist"""
+ lenght = len(self.list)
+ rt = {"PlayListSize": lenght}
+ return {"GetSizeOfPlayListResponse": rt}
+
+ def soap_GetCurrent(self, *args, **kwargs):
+ if self.is_availble():
+ rt = {"CurrentPosition": self.list[self.current]}
+ return {"GetCurrentResponse": rt}
+
+ def clean_playlist(self):
+ if self.is_availble():
+ self.list = []
+
+ def get_playlist(self):
+ return self.list