Welcome, guest | Sign In | My Account | Store | Cart

After writing a few alarms using winsound.Beep, desire to expand into other sound possibilities led to the writing of this program using winsound.PlaySound. The sounds are stored in a custom format (some experimentation in archiving files). This is committed for archival to be run under Python 2.5 or later versions.

Python, 304 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# ==============================================================================
# alarm.py
# ==============================================================================

try:
    import os, sys, time, msvcrt, winsound
    import random, StringIO, dfs
except Exception, error:
    sys.stderr.write('%s: %s' % (error.__class__.__name__, error))
    sys.exit(1)

def main():
    try:
        load_sounds()
        try:
            arg = time.strptime(sys.argv[1], '%H:%M')
            arg_sec = (arg.tm_hour * 60 + arg.tm_min) * 60
            now = time.localtime()
            now_sec = (now.tm_hour * 60 + now.tm_min) * 60 + now.tm_sec
            alarm(arg_sec - now_sec + (86400 if arg_sec <= now_sec else 0))
        except:
            sys.stdout.write('Usage: %s HH:MM' % os.path.basename(sys.argv[0]))
    except Exception, error:
        sys.stderr.write('%s: %s' % (error.__class__.__name__, error))

def load_sounds():
    global sounds
    sounds = []
    hack_dfs()
    dfs.Release(file('sounds.bin', 'rb')).release('')

def hack_dfs():
    os.path.exists = lambda path: 1
    os.path.isfile = lambda path: 0
    class File(StringIO.StringIO):
        def __init__(self, *args):
            StringIO.StringIO.__init__(self)
        def close(self):
            sounds.append(self.getvalue())
            StringIO.StringIO.close(self)
    __builtins__.open = File

def alarm(seconds):
    time.sleep(seconds)
    while msvcrt.kbhit():
        msvcrt.getch()
    while not msvcrt.kbhit():
        winsound.PlaySound(random.choice(sounds), winsound.SND_MEMORY)

if __name__ == '__main__':
    main()

# ==============================================================================
# dfs.py
# ==============================================================================

'''Module for Directory and File Serialization.

This module provides two classes that implement the
DFS (Directory and File Serialization) file format.'''

################################################################################

__version__ = '$Revision: 0 $'
__date__ = 'September 18, 2007'
__author__ = 'Stephen "Zero" Chappell <my.bios@gmail.com>'
__credits__ = '''\
S. Schaub, for introducing me to programming.
G. Niemeyer, for authoring with the bz2 module.
R. Townsend, for helping with the tarfile module.'''

################################################################################

import os as _os
import sys as _sys

################################################################################

FORMAT_DOCUMENTATION = '''\
Directory
    Header
        0,aaa,b,c,dd
            0 = Directory
            a = Pointer Size (bytes)
            b = Name Size (bytes)
            c = Content Flag
            d = Type Code
                00 = End
                01 = Error
                10 = Error
                11 = Real
    Pointer
    Name Size
    Name

File
    Header
        1,aaa,b,ccc
            1 = File
            a = Pointer Size (bytes)
            b = Name Size (bytes)
            c = Data Size (bytes)
    Pointer
    Name Size
    Name
    Data Size
    Data'''

################################################################################

class Acquire:

    'Acquire(destination) -> Acquire'

    BUFF_SIZE = 2 ** 20

    def __init__(self, destination):
        'Initialize the Acquire object.'
        self.__destination = destination
        self.__destination_path = _os.path.abspath(destination.name) \
            if hasattr(destination, 'name') else None
        self.__archive = False

    def acquire(self, source):
        'Save source to destination.'
        source = _os.path.abspath(source)
        self.__pointer = 0
        if self.__archive:
            self.__destination.write('\0')
        else:
            self.__archive = True
        if _os.path.isdir(source):
            self.__dir(source, '\0')
        elif _os.path.isfile(source):
            if source == self.__destination_path:
                raise ValueError, 'Source cannot be destination.'
            self.__file(source, '\0')
        else:
            raise ValueError, 'Source must be directory or file.'

    def __dir(self, source, pointer):
        'Private class method.'
        name = _os.path.basename(source)
        name_size = _str(len(name))
        try:
            dir_list = _os.listdir(source)
        except:
            dir_list = ()
        if dir_list:
            self.__pointer += 1
            self.__destination.write(chr((len(pointer) - 1 << 4) + \
                (len(name_size) - 1 << 3) + 7) + pointer + name_size + name)
        else:
            self.__destination.write(chr((len(pointer) - 1 << 4) + \
                (len(name_size) - 1 << 3) + 3) + pointer + name_size + name)
        pointer = _str(self.__pointer)
        for name in dir_list:
            source_name = _os.path.join(source, name)
            if source_name == self.__destination_path:
                continue
            elif _os.path.isdir(source_name):
                self.__dir(source_name, pointer)
            elif _os.path.isfile(source_name):
                self.__file(source_name, pointer)

    def __file(self, source, pointer):
        'Private class method.'
        name = _os.path.basename(source)
        name_size = _str(len(name))
        try:
            source = open(source, 'rb')
            source.seek(0, 2)
            data_size = _str(source.tell())
            source.seek(0, 0)
        except:
            source = None
            data_size = '\0'
        self.__destination.write(chr(127 + (len(pointer) - 1 << 4) + \
            (len(name_size) - 1 << 3) + len(data_size)) + pointer + \
            name_size + name + data_size)
        if source:
            data_size = _int(data_size)
            try:
                while data_size:
                    buff = source.read(min(self.BUFF_SIZE, data_size))
                    if buff:
                        self.__destination.write(buff)
                        data_size -= len(buff)
                    else:
                        raise IOError, 'File changed size while open.'
                position = source.tell()
                source.seek(0, 2)
                if position != source.tell():
                    raise IOError, 'File changed size while open.'
            finally:
                source.close()

################################################################################

class Release:

    'Release(source) -> Release'

    BUFF_SIZE = 2 ** 20

    def __init__(self, source):
        'Initialize the Release object.'
        self.__source = source
        self.__EOF = False

    def release(self, destination):
        'Save source to destination.'
        if self.__EOF:
            raise EOFError, 'End Of File Found'
        self.__parents = [_os.path.abspath(destination)]
        header = self.__source.read(1)
        header = ord(header) if header else -1
        if header == -1:
            self.__EOF = True
            raise Warning, 'Irregular File Termination Detected'
        while header != -1 and (header > 127 or header & 3):
            if header < 128:
                if header & 3 != 3:
                    raise IOError, 'Corrupt Directory Header Found'
                self.__dir(header)
            else:
                self.__file(header)
            header = self.__source.read(1)
            header = ord(header) if header else -1
        if header == -1:
            self.__EOF = True

    def EOF(self):
        'Return the End Of File status.'
        return self.__EOF

    def __dir(self, header):
        'Private class method.'
        path = _os.path.join(self.__parents[_int(self.__read((header >> 4 & 7) \
            + 1))], self.__read(_int(self.__read((header >> 3 & 1) + 1))))
        if _os.path.exists(path):
            if _os.path.isfile(path):
                raise IOError, 'Path Already Exists'
        else:
            _os.mkdir(path)
        if header >> 2 & 1:
            self.__parents.append(path)

    def __file(self, header):
        'Private class method.'
        destination = open(_os.path.join(self.__parents[_int(self.__read((
            header >> 4 & 7) + 1))], self.__read(_int(self.__read(
            (header >> 3 & 1) + 1)))), 'wb')
        data_size = _int(self.__read((header & 7) + 1))
        try:
            while data_size:
                buff = self.__source.read(min(self.BUFF_SIZE, data_size))
                if buff:
                    destination.write(buff)
                    data_size -= len(buff)
                else:
                    raise IOError, 'End Of File Found'
        finally:
            destination.close()

    def __read(self, size):
        'Private class method.'
        if size:
            buff = ''
            while size:
                temp = self.__source.read(size)
                if temp:
                    buff += temp
                    size -= len(temp)
                else:
                    raise IOError, 'End Of File Found'
            return buff
        raise IOError, 'Zero Length String Found'

################################################################################

def _str(integer):
    'Private module function.'
    if integer:
        string = ''
        while integer:
            string = chr(integer & 0xFF) + string
            integer >>= 8
        return string
    return '\0'

def _int(string):
    'Private module function.'
    integer = 0
    for c in string:
        integer <<= 8
        integer += ord(c)
    return integer

################################################################################

if __name__ == '__main__':
    _sys.stdout.write('Content-Type: text/plain\n\n')
    _sys.stdout.write(file(_sys.argv[0]).read())

If you want ready-made sounds, you can download and use the sounds.bin file.

2 comments

O. Chema 9 years, 4 months ago  # | flag

Where can I find the msvcrt module? I am getting the following error message: ImportError: No module named msvcrt

Stephen Chappell (author) 9 years, 4 months ago  # | flag

You have to be on Windows to use the msvcrt module. If you know a module for Linux that can play WAV files, you might be able to use it as a replacement in the alarm function.

Created by Stephen Chappell on Tue, 10 Jul 2012 (MIT)
Python recipes (4591)
Stephen Chappell's recipes (233)

Required Modules

  • (none specified)

Other Information and Tasks