Add example code for scrolling widget
[panucci.git] / src / panucci / services.py
blob0899f483a03a83adc28ceddd74d609eddc50fe18
1 #!/usr/bin/env python
3 # This file is part of Panucci.
4 # Copyright (c) 2008-2009 The Panucci Audiobook and Podcast Player Project
6 # Panucci is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # Panucci is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Panucci. If not, see <http://www.gnu.org/licenses/>.
19 # from services.py -- Core Services for gPodder
20 # Thomas Perl <thp@perli.net> 2007-08-24
22 # 2009-02-13 - nikosapi: made ObservableService more Panucci-esque
25 from logging import getLogger
27 # the following are only needed for __headphone_watcher
28 import util
29 import gobject
31 class ObservableService(object):
32 def __init__(self, signal_names=[], log=None):
33 self.__log = getLogger('ObservableService') if log is None else log
35 self.observers = {}
36 for signal in signal_names:
37 self.observers[signal] = []
39 if not signal_names:
40 self.__log.warning('No signal names defined...')
42 def register(self, signal_name, observer):
43 if signal_name in self.observers:
44 if not observer in self.observers[signal_name]:
45 self.observers[signal_name].append(observer)
46 self.__log.debug( 'Registered "%s" as an observer for "%s"',
47 observer.__name__, signal_name )
48 else:
49 self.__log.warning(
50 'Observer "%s" is already added to signal "%s"',
51 observer.__name__, signal_name )
52 else:
53 self.__log.warning(
54 'Signal "%s" is not available for registration', signal_name )
56 def unregister(self, signal_name, observer):
57 if signal_name in self.observers:
58 if observer in self.observers[signal_name]:
59 self.observers[signal_name].remove(observer)
60 self.__log.debug( 'Unregistered "%s" as an observer for "%s"',
61 observer.__name__, signal_name )
62 else:
63 self.__log.warning(
64 'Observer "%s" could not be removed from signal "%s"',
65 observer.__name__, signal_name )
66 else:
67 self.__log.warning(
68 'Signal "%s" is not available for un-registration.',
69 signal_name )
71 def notify(self, signal_name, *args, **kwargs):
72 caller = kwargs.get('caller')
73 caller = 'UnknownCaller' if caller is None else caller.__name__
74 rtn_value = False
76 if signal_name in self.observers:
77 self.__log.debug(
78 'Sending signal "%s" for caller "%s"', signal_name, caller )
80 rtn_value = True
81 for observer in self.observers[signal_name]:
82 rtn_value &= bool(observer( *args ))
83 else:
84 self.__log.warning(
85 'Signal "%s" (from caller "%s") is not available '
86 'for notification', signal_name, caller )
88 return rtn_value
91 HEADPHONE_SYS = "/sys/devices/platform/gpio-switch/headphone/state"
93 class __headphone_watcher(ObservableService):
94 """ A small service with one singnal that reports whether or not the
95 headphones are connected. Returns True if the headphones are connected,
96 False if they're not and None if it's not possible to determine the
97 headphone status. """
99 signals = [ 'headphone-status-changed', ]
101 def __init__(self, sys_file):
102 self.__log = getLogger('panucci.serivces.__headphone_watcher')
103 ObservableService.__init__(self, self.signals, self.__log)
105 self.__is_connected = None
107 if util.platform == util.MAEMO:
108 try:
109 self.__sys_file = open( sys_file, 'r' )
110 self.__is_connected = self.__get_state_from_fd(self.__sys_file)
111 gobject.io_add_watch( self.__sys_file, gobject.IO_PRI,
112 self.__on_status_changed )
113 except IOError:
114 self.__log.exception("Can't open headphone status file.")
116 @property
117 def is_connected(self):
118 return self.__is_connected
120 def __get_state_from_fd(self, fd):
121 fd.seek(0)
122 state = fd.read().strip()
123 return state == 'connected'
125 def __on_status_changed(self, src, cond):
126 self.__is_connected = self.__get_state_from_fd( src )
127 self.__log.debug(
128 'Headphone state changed (is_connected=%s).', self.__is_connected )
129 self.notify( 'headphone-status-changed', self.__is_connected,
130 caller=self.__on_status_changed )
131 return True
133 headphone_service = __headphone_watcher(HEADPHONE_SYS)