~ubuntu-branches/debian/wheezy/agtl/wheezy

« back to all changes in this revision

Viewing changes to files/advancedcaching/actors/tts.py

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-01-22 13:55:12 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110122135512-1mik0vssgpnx2fgu
Tags: 0.8.0.3-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import subprocess
 
2
import logging
 
3
import gobject
 
4
logger = logging.getLogger('tts')
 
5
 
 
6
class TTS(gobject.GObject):
 
7
 
 
8
    MIN_DISTANCE = 20
 
9
    MAX_INTERVAL_DISTANCE = 1000
 
10
    MIN_INTERVAL = 5
 
11
    MAX_INTERVAL = 50
 
12
    DEFAULT_INTERVAL = 10
 
13
 
 
14
    __gsignals__ = {
 
15
                    'error' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)),
 
16
                    }
 
17
 
 
18
    def __init__(self, core):
 
19
        gobject.GObject.__init__(self)
 
20
 
 
21
        self.gps_target_bearing_abs = None
 
22
        self.gps_target_distance = None
 
23
        self.gps_data = None
 
24
        self.proc = None
 
25
 
 
26
        self.timeout_event_id = None
 
27
        self.automatic_interval = False
 
28
        core.connect('good-fix', self.__on_good_fix)
 
29
        core.connect('no-fix', self.__on_no_fix)
 
30
        core.connect('settings-changed', self.__on_settings_changed)
 
31
 
 
32
    def __on_settings_changed(self, caller, settings, source):
 
33
        if 'tts_interval' in settings:
 
34
            self.__set_enabled(settings['tts_interval'])
 
35
 
 
36
    def __set_enabled(self, interval):
 
37
        if interval == -1:
 
38
            interval = self.__calculate_automatic_interval(self.gps_target_distance)
 
39
            self.automatic_interval = True
 
40
            logger.info("Setting interval to %d" % interval)
 
41
        else:
 
42
            self.automatic_interval = False
 
43
            
 
44
        if self.timeout_event_id != None:
 
45
            gobject.source_remove(self.timeout_event_id)
 
46
            self.timeout_event_id = None
 
47
 
 
48
        if interval > 0:
 
49
            self.timeout_event_id = gobject.timeout_add_seconds(interval, self.__tell)
 
50
            self.__connect()
 
51
        else:
 
52
            self.__disconnect()
 
53
 
 
54
    @staticmethod
 
55
    def __calculate_automatic_interval(d):
 
56
        if d == None:
 
57
            return TTS.DEFAULT_INTERVAL
 
58
        if d > TTS.MAX_INTERVAL_DISTANCE:
 
59
            return TTS.MAX_INTERVAL
 
60
        if d <= TTS.MIN_DISTANCE:
 
61
            return TTS.MIN_INTERVAL
 
62
        else:
 
63
            return int(round(TTS.MAX_INTERVAL + (TTS.MAX_INTERVAL_DISTANCE - d) * (float(TTS.MIN_INTERVAL - TTS.MAX_INTERVAL) / float(TTS.MAX_INTERVAL_DISTANCE - TTS.MIN_DISTANCE))))
 
64
 
 
65
    def __connect(self):
 
66
        if self.proc != None:
 
67
            return
 
68
        logger.info("Starting espeak...")
 
69
        try:
 
70
            self.proc = subprocess.Popen("espeak", stdin=subprocess.PIPE)
 
71
            self.proc.stdin.write("Espeak ready.\n")
 
72
        except:
 
73
            self.proc = None
 
74
            self.emit('error', Exception("Please install the 'espeak' package from the package manager to get text-to-speech functionality."))
 
75
 
 
76
    def __disconnect(self):
 
77
        logger.info("Stopping espeak...")
 
78
        if self.proc != None:
 
79
            self.proc.stdin.write("Stopping espeak.\n")
 
80
            #self.proc.terminate()
 
81
            self.proc = None
 
82
 
 
83
    def __on_good_fix(self, caller, gps_data, distance, bearing):
 
84
        self.gps_target_distance = distance
 
85
        self.gps_target_bearing_abs = bearing - gps_data.bearing
 
86
        self.gps_data = gps_data
 
87
 
 
88
    def __tell(self):
 
89
        output = "%s\n%s\n" % (self.__format_distance(), self.__format_bearing())
 
90
        logger.info("Espeak: %s" % repr(output.strip()))
 
91
        self.proc.stdin.write(output)
 
92
        if self.automatic_interval:
 
93
            self.__set_enabled(-1)
 
94
            return False
 
95
        return True
 
96
 
 
97
    def __format_distance(self):
 
98
        distance = self.gps_target_distance
 
99
        if distance == None:
 
100
            return 'No Fix. '
 
101
        if distance >= 1000:
 
102
            return '%d kilometers. ' % round(distance / 1000.0)
 
103
        elif distance >= 10:
 
104
            return '%d meters. ' % round(distance)
 
105
        else:
 
106
            return '%.1f meters. ' % round(distance, 1)
 
107
 
 
108
    def __format_bearing(self):
 
109
        if self.gps_target_bearing_abs == None:
 
110
            return ''
 
111
        if self.gps_data == None or self.gps_data.error_bearing > 179:
 
112
            return ''
 
113
        return "%d o'clock." % self.__degree_to_hour(self.gps_target_bearing_abs)
 
114
 
 
115
 
 
116
    def __on_no_fix(self, caller, fix, msg):
 
117
        self.gps_target_distance = None
 
118
        self.gps_target_bearing_abs = None
 
119
        self.gps_data = None
 
120
 
 
121
    @staticmethod
 
122
    def __degree_to_hour(degree):
 
123
        ret = round((degree % 360) / 30.0)
 
124
        return ret if ret != 0 else 12
 
125
 
 
126
    @staticmethod
 
127
    def test():
 
128
        print "Testing of coordinate-to-hour conversion:"
 
129
        for i in xrange(360):
 
130
            print "%3d -> %d" % (i, TTS.__degree_to_hour(i))
 
131
        print
 
132
        print "Testing of interval calculation:"
 
133
        for z in xrange(1050, 0, -3):
 
134
            print "%4d m -> %d seconds" % (z, TTS.__calculate_automatic_interval(z))
 
135
 
 
136
 
 
137
if __name__ == '__main__':
 
138
    TTS.test()
 
139