1 # -*- coding: utf-8 -*-
2 """Core Object dealing with plugins and player client
8 from collections import deque
9 from logging import getLogger
11 from .client import PlayerClient
12 from .client import PlayerError, PlayerUnHandledError
13 from .lib.simadb import SimaDB
14 from .lib.daemon import Daemon
15 from .utils.utils import SigHup
18 """Main class, plugin and player management
21 def __init__(self, conf):
23 Daemon.__init__(self, conf.get('daemon', 'pidfile'))
26 self.sdb = SimaDB(db_path=conf.get('sima', 'db_file'))
27 PlayerClient.database = self.sdb
28 self.log = getLogger('sima')
30 self.player = self.__get_player() # Player client
33 except (PlayerError, PlayerUnHandledError) as err:
34 self.log.error('Fails to connect player: {}'.format(err))
36 self.short_history = deque(maxlen=60)
38 def __get_player(self):
39 """Instanciate the player"""
40 host = self.config.get('MPD', 'host')
41 port = self.config.get('MPD', 'port')
42 pswd = self.config.get('MPD', 'password', fallback=None)
43 return PlayerClient(host, port, pswd)
45 def add_history(self):
46 self.short_history.appendleft(self.player.current)
48 def register_plugin(self, plugin_class):
49 """Registers plubin in Sima instance..."""
50 self.plugins.append(plugin_class(self))
52 def foreach_plugin(self, method, *args, **kwds):
53 """Plugin's callbacks dispatcher"""
54 for plugin in self.plugins:
55 #self.log.debug('dispatching {0} to {1}'.format(method, plugin))
56 getattr(plugin, method)(*args, **kwds)
58 def need_tracks(self):
60 self.log.debug('Queueing disabled!')
62 queue = self.player.queue
63 queue_trigger = self.config.getint('sima', 'queue_length')
64 self.log.debug('Currently {0} track(s) ahead. (target {1})'.format(
65 len(queue), queue_trigger))
66 if len(queue) < queue_trigger:
72 for plugin in self.plugins:
73 pl_callback = getattr(plugin, 'callback_need_track')()
75 to_add.extend(pl_callback)
77 self.log.warning('Queue plugins returned nothing!')
78 for plugin in self.plugins:
79 pl_callback = getattr(plugin, 'callback_need_track_fb')()
81 to_add.extend(pl_callback)
83 self.player.add(track)
85 def reconnect_player(self):
86 """Trying to reconnect cycling through longer timeout
87 cycle : 5s 10s 1m 5m 20m 1h
89 sleepfor = [5, 10, 60, 300, 1200, 3600]
93 self.log.info('Trying to reconnect in {:>4d} seconds'.format(tmp))
99 except PlayerUnHandledError as err:
100 #TODO: unhandled Player exceptions
101 self.log.warning('Unhandled player exception: %s' % err)
102 self.log.info('Got reconnected')
105 def hup_handler(self, signum, frame):
106 self.log.warning('Caught a sighup!')
107 self.player.disconnect()
108 self.foreach_plugin('shutdown')
109 raise SigHup('SIGHUP caught!')
112 """General shutdown method
114 self.log.warning('Starting shutdown.')
115 self.player.disconnect()
116 self.foreach_plugin('shutdown')
118 self.log.info('The way is shut, it was made by those who are dead. '
119 'And the dead keep it…')
120 self.log.info('bye...')
128 except PlayerUnHandledError as err:
129 #TODO: unhandled Player exceptions
130 self.log.warning('Unhandled player exception: {}'.format(err))
132 self.player = PlayerClient()
134 except PlayerError as err:
135 self.log.warning('Player error: %s' % err)
136 self.reconnect_player()
140 """Dispatching callbacks to plugins
142 # hanging here untill a monitored event is raised in the player
143 if getattr(self, 'changed', False): # first iteration exception
144 self.changed = self.player.monitor()
145 else: # first iteration goes through else
146 self.changed = ['playlist', 'player', 'skipped']
147 self.log.debug('changed: {}'.format(', '.join(self.changed)))
148 if 'playlist' in self.changed:
149 self.foreach_plugin('callback_playlist')
150 if ('player' in self.changed
151 or 'options' in self.changed):
152 self.foreach_plugin('callback_player')
153 if 'database' in self.changed:
154 self.foreach_plugin('callback_player_database')
155 if 'skipped' in self.changed:
156 if self.player.state == 'play':
157 self.log.info('Playing: {}'.format(self.player.current))
159 self.foreach_plugin('callback_next_song')
160 if self.need_tracks():
164 # vim: ai ts=4 sw=4 sts=4 expandtab