]> kaliko git repositories - mpd-sima.git/blob - sima/core.py
Add SimaDB and deal with history
[mpd-sima.git] / sima / core.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 """Core Object dealing with plugins and player client
4 """
5
6 __version__ = '0.12.0.b'
7 __author__ = 'kaliko jack'
8 __url__ = 'git://git.kaliko.me/sima.git'
9
10 import sys
11 import time
12
13 from logging import getLogger
14
15 from .client import PlayerClient, Track
16 from .client import PlayerError, PlayerUnHandledError
17 from .lib.simadb import SimaDB
18
19 class Sima(object):
20     """Main class, plugin and player management
21     """
22
23     def __init__(self, conf, dbfile):
24         self.config = conf
25         self.sdb = SimaDB(db_path=dbfile)
26         self.log = getLogger('sima')
27         self.plugins = list()
28         self.player = PlayerClient()  # Player client
29         try:
30             self.player.connect()
31         except (PlayerError, PlayerUnHandledError) as err:
32             self.log.error('Fails to connect player: {}'.format(err))
33             self.shutdown()
34         self.current_track = None
35
36     def register_plugin(self, plugin_class):
37         """Registers plubin in Sima instance..."""
38         self.plugins.append(plugin_class(self))
39
40     def foreach_plugin(self, method, *args, **kwds):
41         """Plugin's callbacks dispatcher"""
42         for plugin in self.plugins:
43             getattr(plugin, method)(*args, **kwds)
44
45     def reconnect_player(self):
46         """Trying to reconnect cycling through longer timeout
47         cycle : 5s 10s 1m 5m 20m 1h
48         """
49         sleepfor = [5, 10, 60, 300, 1200, 3600]
50         while True:
51             tmp = sleepfor.pop(0)
52             sleepfor.append(tmp)
53             self.log.info('Trying to reconnect in {:>4d} seconds'.format(tmp))
54             time.sleep(tmp)
55             try:
56                 self.player.connect()
57             except PlayerError:
58                 continue
59             except PlayerUnHandledError as err:
60                 #TODO: unhandled Player exceptions
61                 self.log.warning('Unhandled player exception: %s' % err)
62             self.log.info('Got reconnected')
63             break
64
65     def shutdown(self):
66         """General shutdown method
67         """
68         self.log.warning('Starting shutdown.')
69         self.player.disconnect()
70         self.foreach_plugin('shutdown')
71
72         self.log.info('The way is shut, it was made by those who are dead. '
73                       'And the dead keep it…')
74         self.log.info('bye...')
75         sys.exit(0)
76
77     def run(self):
78         """
79         """
80         self.current_track = Track()
81         while 42:
82             try:
83                 self.loop()
84             except PlayerUnHandledError as err:
85                 #TODO: unhandled Player exceptions
86                 self.log.warning('Unhandled player exception: {}'.format(err))
87                 del(self.player)
88                 self.player = PlayerClient()
89                 time.sleep(10)
90             except PlayerError as err:
91                 self.log.warning('Player error: %s' % err)
92                 self.reconnect_player()
93
94     def loop(self):
95         """Dispatching callbacks to plugins
96         """
97         # hanging here untill a monitored event is raised in the player
98         if getattr(self, 'changed', False): # first loop detection
99             self.changed = self.player.monitor()
100         else:
101             self.changed = ['playlist', 'player', 'skipped']
102         self.log.debug('changed: {}'.format(', '.join(self.changed)))
103         if 'playlist' in self.changed:
104             self.foreach_plugin('callback_playlist')
105         if 'player' in self.changed:
106             self.foreach_plugin('callback_player')
107         if 'skipped' in self.changed:
108             if self.player.state == 'play':
109                 self.log.info('Playing: {}'.format(self.player.current))
110                 self.foreach_plugin('callback_next_song')
111                 self.current_track = self.player.current
112
113
114 # VIM MODLINE
115 # vim: ai ts=4 sw=4 sts=4 expandtab