1 """
2
3 This module is responsible for managing audio files:
4
5 * managing the main (content) audio files, located in
6 <audioroot>/main/path/to/audiofile
7 * managing extra audio files, located in
8 <audioroot/extra, in two subdirectories,
9 <audioroot/extra/masters and <audioroot/extra/transcoded.
10 * resolving audiofile symbolic names to files within
11 the managed hierarchy.
12 * creating combined (spliced) files according to rules passed
13 in.
14
15 """
16 import os
17 import thread
18
19 from ewa.mp3 import get_vbr_bitrate_samplerate_mode, splice
20 from ewa.transcode import transcode
21 from ewa.logutil import warn
22
23 path_join=os.path.join
24 path_exists=os.path.exists
25 getmtime=os.path.getmtime
26
28 return getattr(s, 'is_original', False)
29
32
35
39
40 - def get_main_path(self, audioname):
41 return path_join(self.basedir,
42 'main',
43 audioname)
44
47 p=path_join(self.basedir,
48 'extra',
49 'master',
50 audioname)
51 if path_exists(p):
52 return p
53 raise FileNotFound(p)
54
55
62 path= path_join(self.basedir,
63 'extra',
64 'transcoded',
65 str(bitrate),
66 str(samplerate),
67 mode,
68 audioname)
69 if not path.endswith('.mp3') or path.endswith('.MP3'):
70 path+='.mp3'
71 if create:
72 orig_path=self.get_extra_master_path(audioname)
73 if path_exists(path):
74 trans_mtime=getmtime(path)
75 orig_mtime=getmtime(orig_path)
76 if orig_mtime <= trans_mtime:
77
78 return path
79
80
81 transcode(orig_path, path, bitrate, samplerate, mode)
82 return path
83
85 symbols=list(rule(audioname))
86 if not symbols:
87 return symbols
88 audiopath=self.get_main_path(audioname)
89 isvbr, bitrate, samplerate, mode=get_vbr_bitrate_samplerate_mode(audiopath)
90 if isvbr:
91 warn("file is vbr: %s", audiopath)
92 raise AudioProviderException, "vbr not supported: %s" % audiopath
93
94 def resolve(x):
95 if is_original(x):
96 path=self.get_main_path(x)
97 if create and not path_exists(path):
98 raise FileNotFound(path)
99 return path
100 else:
101 try:
102 return self.get_extra_transcoded_path(x, mode, bitrate, samplerate, create)
103 except FileNotFound:
104 warn("extra audio not found: %s", x)
105 return None
106
107 return [y for y in (resolve(x) for x in symbols) if y]
108
109
111
112 - def __init__(self, basedir, targetdir=None):
117
119 return path_join(self.targetdir, audioname)
120
122 if audioname.startswith('/'):
123 audioname=audioname[1:]
124 mainpath=self.get_main_path(audioname)
125 playlist=self.get_playlist(audioname, rule)
126 target=self.get_combined_path(audioname)
127 parent=os.path.dirname(target)
128 if not path_exists(parent):
129 os.makedirs(parent)
130 renamed='%s%d~%d~' % (target,
131 os.getpid(),
132 thread.get_ident())
133 fp=open(renamed, 'wb')
134 for chunk in splice(playlist, mainpath, **spliceKwargs):
135 fp.write(chunk)
136 fp.close()
137 os.rename(renamed, target)
138 return target
139
141
143 if audioname.startswith('/'):
144 audioname=audioname[1:]
145 mainpath=self.get_main_path(audioname)
146 playlist=self.get_playlist(audioname, rule)
147 return splice(playlist, mainpath, **spliceKwargs)
148
149
150
151 __all__=['AudioProviderException',
152 'FileNotFound',
153 'FSAudioProvider',
154 'StreamAudioProvider']
155