pyTivo
[pyTivo/krkeegan.git] / plugins / music / music.py
blob33bca7fada3e8db5c562d40313c3c1f4ee05dd5b
1 import transcode, os, socket, re, shutil
2 from Cheetah.Template import Template
3 from plugin import Plugin
4 from urllib import unquote_plus, quote, unquote
5 from urlparse import urlparse
6 from xml.sax.saxutils import escape
7 import eyeD3
9 SCRIPTDIR = os.path.dirname(__file__)
11 class music(Plugin):
13 def __init__(self):
15 self.content_type = 'x-container/tivo-music'
17 def SendFile(self, handler, container, name):
19 o = urlparse("http://fake.host" + handler.path)
20 path = unquote_plus(o.path)
21 handler.send_response(200)
22 handler.end_headers()
23 f = file(container['path'] + path[len(name)+1:], 'rb')
24 shutil.copyfileobj(f, handler.wfile)
26 def QueryContainer(self, handler, query):
28 subcname = query['Container'][0]
29 cname = subcname.split('/')[0]
31 if not handler.server.containers.has_key(cname) or not self.get_local_path(handler, query):
32 handler.send_response(404)
33 handler.end_headers()
34 return
36 path = self.get_local_path(handler, query)
37 def isdir(file):
38 return os.path.isdir(os.path.join(path, file))
40 def media_data(file):
41 dict = {}
42 dict['path'] = file
44 file = os.path.join(path, file)
46 if isdir(file) or not eyeD3.isMp3File(file):
47 return dict
49 audioFile = eyeD3.Mp3AudioFile(file)
50 dict['Duration'] = audioFile.getPlayTime() * 1000
51 dict['SourceBitRate'] = audioFile.getBitRate()[1]
52 dict['SourceSampleRate'] = audioFile.getSampleFreq()
54 tag = audioFile.getTag()
55 dict['ArtistName'] = str(tag.getArtist())
56 dict['AlbumTitle'] = str(tag.getAlbum())
57 dict['SongTitle'] = str(tag.getTitle())
58 dict['AlbumYear'] = tag.getYear()
60 try:
61 dict['MusicGenre'] = tag.getGenre().getName()
62 except:
63 pass
65 return dict
67 handler.send_response(200)
68 handler.end_headers()
69 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'container.tmpl'))
70 t.name = subcname
71 print '----'
72 print len(self.get_files(handler, query)[0])
73 print len(map(media_data, self.get_files(handler, query)[0]))
74 t.files, t.total, t.start = self.get_files(handler, query)
75 t.files = map(media_data, t.files)
76 t.isdir = isdir
77 t.quote = quote
78 t.escape = escape
79 handler.wfile.write(t)
81 def get_local_path(self, handler, query):
83 subcname = query['Container'][0]
84 container = handler.server.containers[subcname.split('/')[0]]
86 path = container['path']
87 for folder in subcname.split('/')[1:]:
88 if folder == '..':
89 return False
90 path = os.path.join(path, folder)
91 return path
93 def get_files(self, handler, query):
94 subcname = query['Container'][0]
95 path = self.get_local_path(handler, query)
97 files = os.listdir(path)
98 totalFiles = len(files)
100 def dir_sort(x, y):
101 xdir = os.path.isdir(os.path.join(path, x))
102 ydir = os.path.isdir(os.path.join(path, y))
104 if xdir and ydir:
105 return name_sort(x, y)
106 elif xdir:
107 return -1
108 elif ydir:
109 return 1
110 else:
111 return name_sort(x, y)
113 def name_sort(x, y):
114 numbername = re.compile(r'(\d*)(.*)')
115 m = numbername.match(x)
116 xNumber = m.group(1)
117 xStr = m.group(2)
118 m = numbername.match(y)
119 yNumber = m.group(1)
120 yStr = m.group(2)
122 if xNumber and yNumber:
123 xNumber, yNumber = int(xNumber), int(yNumber)
124 if xNumber == yNumber:
125 return cmp(xStr, yStr)
126 else:
127 return cmp(xNumber, yNumber)
128 elif xNumber:
129 return -1
130 elif yNumber:
131 return 1
132 else:
133 return cmp(xStr, yStr)
135 files.sort(dir_sort)
137 index = 0
138 count = 10
139 if query.has_key('ItemCount'):
140 count = int(query['ItemCount'] [0])
142 if query.has_key('AnchorItem'):
143 anchor = unquote(query['AnchorItem'][0])
144 for i in range(len(files)):
145 if os.path.isdir(os.path.join(path,files[i])):
146 file_url = '/TiVoConnect?Command=QueryContainer&Container=' + subcname + '/' + files[i]
147 else:
148 file_url = '/' + subcname + '/' + files[i]
149 if file_url == anchor:
150 if count > 0:
151 index = i + 1
152 elif count < 0:
153 index = i - 1
154 else:
155 index = i
156 break
157 if query.has_key('AnchorOffset'):
158 index = index + int(query['AnchorOffset'][0])
160 if index < index + count:
161 files = files[max(index, 0):index + count ]
162 return files, totalFiles, index
163 else:
164 files = files[max(index + count, 0):index]
165 return files, totalFiles, index + count