1 # -*- coding: utf-8 -*-
2 """Core Object dealing with plugins and player client
5 __version__ = '0.12.0.b'
6 __author__ = 'kaliko jack'
7 __url__ = 'git://git.kaliko.me/sima.git'
12 from collections import deque
13 from logging import getLogger
15 from .client import PlayerClient
16 from .client import PlayerError, PlayerUnHandledError
17 from .lib.simadb import SimaDB
20 """Main class, plugin and player management
23 def __init__(self, conf, dbfile):
26 self.sdb = SimaDB(db_path=dbfile)
27 self.log = getLogger('sima')
29 self.player = PlayerClient() # Player client
32 except (PlayerError, PlayerUnHandledError) as err:
33 self.log.error('Fails to connect player: {}'.format(err))
35 self.short_history = deque(maxlen=40)
37 def add_history(self):
38 self.short_history.appendleft(self.player.current)
40 def register_plugin(self, plugin_class):
41 """Registers plubin in Sima instance..."""
42 self.plugins.append(plugin_class(self))
44 def foreach_plugin(self, method, *args, **kwds):
45 """Plugin's callbacks dispatcher"""
46 for plugin in self.plugins:
47 #self.log.debug('dispatching {0} to {1}'.format(method, plugin))
48 getattr(plugin, method)(*args, **kwds)
50 def need_tracks(self):
52 self.log.debug('Queueing disabled!')
54 queue = self.player.queue
55 queue_trigger = self.config.getint('sima', 'queue_length')
56 self.log.debug('Currently {0} track(s) ahead. (target {1})'.format(
57 len(queue), queue_trigger))
58 if len(queue) < queue_trigger:
64 for plugin in self.plugins:
65 pl_callback = getattr(plugin, 'callback_need_track')()
67 to_add.extend(pl_callback)
69 self.player.add(track)
71 def reconnect_player(self):
72 """Trying to reconnect cycling through longer timeout
73 cycle : 5s 10s 1m 5m 20m 1h
75 sleepfor = [5, 10, 60, 300, 1200, 3600]
79 self.log.info('Trying to reconnect in {:>4d} seconds'.format(tmp))
85 except PlayerUnHandledError as err:
86 #TODO: unhandled Player exceptions
87 self.log.warning('Unhandled player exception: %s' % err)
88 self.log.info('Got reconnected')
92 """General shutdown method
94 self.log.warning('Starting shutdown.')
95 self.player.disconnect()
96 self.foreach_plugin('shutdown')
98 self.log.info('The way is shut, it was made by those who are dead. '
99 'And the dead keep it…')
100 self.log.info('bye...')
109 except PlayerUnHandledError as err:
110 #TODO: unhandled Player exceptions
111 self.log.warning('Unhandled player exception: {}'.format(err))
113 self.player = PlayerClient()
115 except PlayerError as err:
116 self.log.warning('Player error: %s' % err)
117 self.reconnect_player()
120 """Dispatching callbacks to plugins
122 # hanging here untill a monitored event is raised in the player
123 if getattr(self, 'changed', False): # first iteration exception
124 self.changed = self.player.monitor()
125 else: # first iteration goes through else
126 self.changed = ['playlist', 'player', 'skipped']
127 self.log.debug('changed: {}'.format(', '.join(self.changed)))
128 if 'playlist' in self.changed:
129 self.foreach_plugin('callback_playlist')
130 if ('player' in self.changed
131 or 'options' in self.changed):
132 self.foreach_plugin('callback_player')
133 if 'database' in self.changed:
134 self.foreach_plugin('callback_player_database')
135 if 'skipped' in self.changed:
136 if self.player.state == 'play':
137 self.log.info('Playing: {}'.format(self.player.current))
139 self.foreach_plugin('callback_next_song')
140 if self.need_tracks():
144 # vim: ai ts=4 sw=4 sts=4 expandtab