pyTivo
[pyTivo/krkeegan.git] / plugins / music / music.py
blob2b99752f7370945069178f85ff7855abace8f551
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 t.files, t.total, t.start = self.get_files(handler, query)
72 t.files = map(media_data, t.files)
73 t.isdir = isdir
74 t.quote = quote
75 t.escape = escape
76 handler.wfile.write(t)
78 def get_local_path(self, handler, query):
80 subcname = query['Container'][0]
81 container = handler.server.containers[subcname.split('/')[0]]
83 path = container['path']
84 for folder in subcname.split('/')[1:]:
85 if folder == '..':
86 return False
87 path = os.path.join(path, folder)
88 return path
90 def get_files(self, handler, query):
91 subcname = query['Container'][0]
92 path = self.get_local_path(handler, query)
94 files = os.listdir(path)
95 totalFiles = len(files)
97 def dir_sort(x, y):
98 xdir = os.path.isdir(os.path.join(path, x))
99 ydir = os.path.isdir(os.path.join(path, y))
101 if xdir and ydir:
102 return name_sort(x, y)
103 elif xdir:
104 return -1
105 elif ydir:
106 return 1
107 else:
108 return name_sort(x, y)
110 def name_sort(x, y):
111 numbername = re.compile(r'(\d*)(.*)')
112 m = numbername.match(x)
113 xNumber = m.group(1)
114 xStr = m.group(2)
115 m = numbername.match(y)
116 yNumber = m.group(1)
117 yStr = m.group(2)
119 if xNumber and yNumber:
120 xNumber, yNumber = int(xNumber), int(yNumber)
121 if xNumber == yNumber:
122 return cmp(xStr, yStr)
123 else:
124 return cmp(xNumber, yNumber)
125 elif xNumber:
126 return -1
127 elif yNumber:
128 return 1
129 else:
130 return cmp(xStr, yStr)
132 files.sort(dir_sort)
134 index = 0
135 if query.has_key('ItemCount'):
136 count = int(query['ItemCount'] [0])
138 if query.has_key('AnchorItem'):
139 anchor = unquote(query['AnchorItem'][0])
140 for i in range(len(files)):
142 if os.path.isdir(os.path.join(path,files[i])):
143 file_url = '/TiVoConnect?Command=QueryContainer&Container=' + subcname + '/' + files[i]
144 else:
145 file_url = '/' + subcname + '/' + files[i]
146 if file_url == anchor:
147 index = i + 1
148 break
149 if query.has_key('AnchorOffset'):
150 index = index + int(query['AnchorOffset'][0])
151 files = files[index:index + count]
153 return files, totalFiles, index