Merge branch 'master' into subfolders-8.3
[pyTivo.git] / plugin.py
blobd6390f9f7c3e87941edf36417d571666c7af1625
1 import os, shutil, re, random, threading
2 from urllib import unquote, unquote_plus
3 from urlparse import urlparse
5 def GetPlugin(name):
6 module_name = '.'.join(['plugins', name, name])
7 module = __import__(module_name, globals(), locals(), name)
8 plugin = getattr(module, module.CLASS_NAME)()
9 return plugin
11 class Plugin(object):
13 random_lock = threading.Lock()
15 CONTENT_TYPE = ''
17 def __new__(cls, *args, **kwds):
18 it = cls.__dict__.get('__it__')
19 if it is not None:
20 return it
21 cls.__it__ = it = object.__new__(cls)
22 it.init(*args, **kwds)
23 return it
25 def init(self):
26 pass
28 def send_file(self, handler, container, name):
29 o = urlparse("http://fake.host" + handler.path)
30 path = unquote_plus(o[2])
31 handler.send_response(200)
32 handler.end_headers()
33 f = file(container['path'] + path[len(name)+1:], 'rb')
34 shutil.copyfileobj(f, handler.wfile)
36 def get_local_base_path(self, handler, query):
38 subcname = query['Container'][0]
39 container = handler.server.containers[subcname.split('/')[0]]
41 return container['path']
43 def get_local_path(self, handler, query):
45 subcname = query['Container'][0]
46 container = handler.server.containers[subcname.split('/')[0]]
48 path = container['path']
49 for folder in subcname.split('/')[1:]:
50 if folder == '..':
51 return False
52 path = os.path.join(path, folder)
53 return path
55 def get_files(self, handler, query, filterFunction=None):
56 subcname = query['Container'][0]
57 cname = subcname.split('/')[0]
58 path = self.get_local_path(handler, query)
60 files = [ os.path.join(path, file) for file in os.listdir(path)]
61 if query.get('Recurse',['No'])[0] == 'Yes':
62 for file in files:
63 if os.path.isdir(file):
64 for new_file in os.listdir(file):
65 files.append( os.path.join(file, new_file) )
67 file_type = query.get('Filter', [''])[0]
68 if filterFunction:
69 files = [file for file in files if filterFunction(file, file_type)]
71 totalFiles = len(files)
73 def dir_sort(x, y):
74 xdir = os.path.isdir(os.path.join(path, x))
75 ydir = os.path.isdir(os.path.join(path, y))
77 if xdir and ydir:
78 return name_sort(x, y)
79 elif xdir:
80 return -1
81 elif ydir:
82 return 1
83 else:
84 return name_sort(x, y)
86 def name_sort(x, y):
87 numbername = re.compile(r'(\d*)(.*)')
88 m = numbername.match(x)
89 xNumber = m.group(1)
90 xStr = m.group(2)
91 m = numbername.match(y)
92 yNumber = m.group(1)
93 yStr = m.group(2)
95 if xNumber and yNumber:
96 xNumber, yNumber = int(xNumber), int(yNumber)
97 if xNumber == yNumber:
98 return cmp(xStr, yStr)
99 else:
100 return cmp(xNumber, yNumber)
101 elif xNumber:
102 return -1
103 elif yNumber:
104 return 1
105 else:
106 return cmp(xStr, yStr)
108 if query.get('SortOrder',['Normal'])[0] == 'Random':
109 seed = query.get('RandomSeed', ['1'])[0]
110 self.random_lock.acquire()
111 random.seed(seed)
112 random.shuffle(files)
113 self.random_lock.release()
114 else:
115 files.sort(dir_sort)
117 local_base_path = self.get_local_base_path(handler, query)
119 index = 0
120 count = 10
121 if query.has_key('ItemCount'):
122 count = int(query['ItemCount'] [0])
124 if query.has_key('AnchorItem'):
125 anchor = unquote(query['AnchorItem'][0])
126 for file, i in zip(files, range(len(files))):
127 file_name = file.replace(local_base_path, '')
129 if os.path.isdir(os.path.join(file)):
130 file_url = '/TiVoConnect?Command=QueryContainer&Container=' + cname + file_name
131 else:
132 file_url = '/' + cname + file_name
134 if file_url == anchor:
135 if count > 0:
136 index = i + 1
137 elif count < 0:
138 index = i - 1
139 else:
140 index = i
141 break
143 if query.has_key('AnchorOffset'):
144 index = index + int(query['AnchorOffset'][0])
146 #foward count
147 if index < index + count:
148 files = files[index:index + count ]
149 return files, totalFiles, index
150 #backwards count
151 else:
152 #off the start of the list
153 if index + count < 0:
154 index += 0 - (index + count)
155 files = files[index + count:index]
156 return files, totalFiles, index + count