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))
37 self.short_history = deque(maxlen=60)
39 def __get_player(self):
40 """Instanciate the player"""
41 host = self.config.get('MPD', 'host')
42 port = self.config.get('MPD', 'port')
43 pswd = self.config.get('MPD', 'password', fallback=None)
44 return PlayerClient(host, port, pswd)
46 def add_history(self):
47 self.short_history.appendleft(self.player.current)
49 def register_plugin(self, plugin_class):
50 """Registers plubin in Sima instance..."""
51 self.plugins.append(plugin_class(self))
53 def foreach_plugin(self, method, *args, **kwds):
54 """Plugin's callbacks dispatcher"""
55 for plugin in self.plugins:
56 #self.log.debug('dispatching {0} to {1}'.format(method, plugin))
57 getattr(plugin, method)(*args, **kwds)
59 def need_tracks(self):
61 self.log.debug('Queueing disabled!')
63 queue = self.player.queue
64 queue_trigger = self.config.getint('sima', 'queue_length')
65 self.log.debug('Currently {0} track(s) ahead. (target {1})'.format(
66 len(queue), queue_trigger))
67 if len(queue) < queue_trigger:
73 for plugin in self.plugins:
74 pl_callback = getattr(plugin, 'callback_need_track')()
76 to_add.extend(pl_callback)
78 self.log.warning('Queue plugins returned nothing!')
79 for plugin in self.plugins:
80 pl_callback = getattr(plugin, 'callback_need_track_fb')()
82 to_add.extend(pl_callback)
84 self.player.add(track)
86 def reconnect_player(self):
87 """Trying to reconnect cycling through longer timeout
88 cycle : 5s 10s 1m 5m 20m 1h
90 sleepfor = [5, 10, 60, 300, 1200, 3600]
94 self.log.info('Trying to reconnect in {:>4d} seconds'.format(tmp))
100 except PlayerUnHandledError as err:
101 #TODO: unhandled Player exceptions
102 self.log.warning('Unhandled player exception: %s' % err)
103 self.log.info('Got reconnected')
106 def hup_handler(self, signum, frame):
107 self.log.warning('Caught a sighup!')
108 self.player.disconnect()
109 self.foreach_plugin('shutdown')
110 raise SigHup('SIGHUP caught!')
113 """General shutdown method
115 self.log.warning('Starting shutdown.')
116 self.player.disconnect()
117 self.foreach_plugin('shutdown')
119 self.log.info('The way is shut, it was made by those who are dead. '
120 'And the dead keep it…')
121 self.log.info('bye...')
129 except PlayerUnHandledError as err:
130 #TODO: unhandled Player exceptions
131 self.log.warning('Unhandled player exception: {}'.format(err))
133 self.player = PlayerClient()
135 except PlayerError as err:
136 self.log.warning('Player error: %s' % err)
137 self.reconnect_player()
141 """Dispatching callbacks to plugins
143 # hanging here untill a monitored event is raised in the player
144 if getattr(self, 'changed', False): # first iteration exception
145 self.changed = self.player.monitor()
146 else: # first iteration goes through else
147 self.changed = ['playlist', 'player', 'skipped']
148 self.log.debug('changed: {}'.format(', '.join(self.changed)))
149 if 'playlist' in self.changed:
150 self.foreach_plugin('callback_playlist')
151 if ('player' in self.changed
152 or 'options' in self.changed):
153 self.foreach_plugin('callback_player')
154 if 'database' in self.changed:
155 self.foreach_plugin('callback_player_database')
156 if 'skipped' in self.changed:
157 if self.player.state == 'play':
158 self.log.info('Playing: {}'.format(self.player.current))
160 self.foreach_plugin('callback_next_song')
161 if self.need_tracks():
165 # vim: ai ts=4 sw=4 sts=4 expandtab