1"""Translate text strings to Morse code"""
2
3FRAMERATE = 22050
4SAMPWIDTH = 2
5
6BASEFREQ = 441
7OCTAVE = 2
8
9DOT = 30
10DAH = 80
11
12morsetab = {
13        'a': '.-',
14        'b': '-...',
15        'c': '-.-.',
16        'd': '-..',
17        'e': '.',
18        'f': '..-.',
19        'g': '--.',
20        'h': '....',
21        'i': '..',
22        'j': '.---',
23        'k': '-.-',
24        'l': '.-..',
25        'm': '--',
26        'n': '-.',
27        'o': '---',
28        'p': '.--.',
29        'q': '--.-',
30        'r': '.-.',
31        's': '...',
32        't': '-',
33        'u': '..-',
34        'v': '...-',
35        'w': '.--',
36        'x': '-..-',
37        'y': '-.--',
38        'z': '--..',
39        '0': '-----',
40        '1': '.----',
41        '2': '..---',
42        '3': '...--',
43        '4': '....-',
44        '5': '.....',
45        '6': '-....',
46        '7': '--...',
47        '8': '---..',
48        '9': '----.',
49        ',': '--..--',
50        '.': '.-.-.-',
51        '?': '..--..',
52        ';': '-.-.-.',
53        ':': '---...',
54        "'": '.----.',
55        '-': '-....-',
56        '/': '-..-.',
57        '(': '-.--.-',
58        ')': '-.--.-', # XXX same as code for '(' ???
59        '_': '..--.-',
60        ' ': ' '
61}
62
63def morsecode(s):
64    from string import lower
65    m = ''
66    for c in s:
67        c = lower(c)
68        if morsetab.has_key(c):
69            c = morsetab[c] + ' '
70        else:
71            c = '? '
72        m = m + c
73    return m
74
75
76class BaseMorse:
77    "base class for morse transmissions"
78
79    def __init__(self):
80        "constructor"
81        self.dots = DOT
82        self.dahs = DAH
83
84    def noise(self, duration):
85        "beep for given duration"
86        pass
87
88    def pause(self, duration):
89        "pause for given duration"
90        pass
91
92    def dot(self):
93        "short beep"
94        self.noise(self.dots)
95
96    def dah(self):
97        "long beep"
98        self.noise(self.dahs)
99
100    def pdot(self):
101        "pause as long as a dot"
102        self.pause(self.dots)
103
104    def pdah(self):
105        "pause as long as a dah"
106        self.pause(self.dahs)
107
108    def sendmorse(self, s):
109        for c in s:
110            if c == '.': self.dot()
111            elif c == '-': self.dah()
112            else: self.pdah()
113            self.pdot()
114
115    def sendascii(self, s):
116        self.sendmorse(morsecode(s))
117
118    def send(self, s):
119        self.sendascii(s)
120
121
122import Audio_mac
123class MyAudio(Audio_mac.Play_Audio_mac):
124    def _callback(self, *args):
125        if hasattr(self, 'usercallback'): self.usercallback()
126        apply(Audio_mac.Play_Audio_mac._callback, (self,) + args)
127
128
129class MacMorse(BaseMorse):
130    "Mac specific class to play Morse code"
131
132    def __init__(self):
133        BaseMorse.__init__(self)
134        self.dev = MyAudio()
135        self.dev.setoutrate(FRAMERATE)
136        self.dev.setsampwidth(SAMPWIDTH)
137        self.dev.setnchannels(1)
138        self.dev.usercallback = self.usercallback
139        sinewave = ''
140        n = int(FRAMERATE / BASEFREQ)
141        octave = OCTAVE
142        from math import sin, pi
143        for i in range(n):
144            val = int(sin(2 * pi * i * octave / n) * 0x7fff)
145            sample = chr((val >> 8) & 255) + chr(val & 255)
146            sinewave = sinewave + sample[:SAMPWIDTH]
147        self.sinewave = sinewave
148        self.silence = '\0' * (n*SAMPWIDTH)
149        self.morsequeue = ''
150
151    def __del__(self):
152        self.close()
153
154    def close(self):
155        self.dev = None
156
157    def pause(self, duration):
158        self.dev.writeframes(self.silence * duration)
159
160    def noise(self, duration):
161        self.dev.writeframes(self.sinewave * duration)
162
163    def sendmorse(self, s):
164        self.morsequeue = self.morsequeue + s
165        self.dev.usercallback()
166        self.dev.usercallback()
167        self.dev.usercallback()
168
169    def usercallback(self):
170        if self.morsequeue:
171            c, self.morsequeue = self.morsequeue[0], self.morsequeue[1:]
172            if c == '.': self.dot()
173            elif c == '-': self.dah()
174            else: self.pdah()
175            self.pdot()
176
177
178def test():
179    m = MacMorse()
180    while 1:
181        try:
182            line = raw_input('Morse line: ')
183        except (EOFError, KeyboardInterrupt):
184            break
185        m.send(line)
186        while m.morsequeue: pass
187
188test()
189