|
1 /* |
|
2 * MP3/MPlayer plugin to VDR (C++) |
|
3 * |
|
4 * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de> |
|
5 * |
|
6 * This code is free software; you can redistribute it and/or |
|
7 * modify it under the terms of the GNU General Public License |
|
8 * as published by the Free Software Foundation; either version 2 |
|
9 * of the License, or (at your option) any later version. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, |
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 * GNU General Public License for more details. |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License |
|
17 * along with this program; if not, write to the Free Software |
|
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
19 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html |
|
20 */ |
|
21 |
|
22 #include <ctype.h> |
|
23 #include <dirent.h> |
|
24 #include <stdlib.h> |
|
25 #include <stdio.h> |
|
26 #include <errno.h> |
|
27 #include <sys/stat.h> |
|
28 #include <sys/ioctl.h> |
|
29 #include <sys/types.h> |
|
30 #include <unistd.h> |
|
31 |
|
32 #include "common.h" |
|
33 #include "menu.h" |
|
34 #include "data.h" |
|
35 #include "data-src.h" |
|
36 #include "i18n.h" |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 |
|
40 void Status(const char *text) |
|
41 { |
|
42 #if APIVERSNUM >= 10307 |
|
43 Skins.Message(mtStatus,text); |
|
44 #else |
|
45 if(text) { |
|
46 Interface->Status(text); |
|
47 Interface->Flush(); |
|
48 } |
|
49 #endif |
|
50 } |
|
51 |
|
52 void Error(const char *text) |
|
53 { |
|
54 #if APIVERSNUM >= 10307 |
|
55 Skins.Message(mtError,text); |
|
56 #else |
|
57 Interface->Error(text); |
|
58 #endif |
|
59 } |
|
60 |
|
61 void Info(const char *text) |
|
62 { |
|
63 #if APIVERSNUM >= 10307 |
|
64 Skins.Message(mtInfo,text); |
|
65 #else |
|
66 Interface->Info(text); |
|
67 #endif |
|
68 } |
|
69 |
|
70 // --- cMenuBrowseItem --------------------------------------------------------- |
|
71 |
|
72 class cMenuBrowseItem : public cOsdItem { |
|
73 private: |
|
74 cFileObj *item; |
|
75 virtual void Set(void); |
|
76 public: |
|
77 cMenuBrowseItem(cFileObj *Item); |
|
78 cFileObj *Item(void) { return item; } |
|
79 }; |
|
80 |
|
81 cMenuBrowseItem::cMenuBrowseItem(cFileObj *Item) |
|
82 { |
|
83 item = Item; |
|
84 Set(); |
|
85 } |
|
86 |
|
87 void cMenuBrowseItem::Set(void) |
|
88 { |
|
89 char *buffer=0; |
|
90 asprintf(&buffer,item->Type()==otFile?"%s":"[%s]",item->Name()); |
|
91 SetText(buffer,false); |
|
92 } |
|
93 |
|
94 // --- cMenuBrowse ------------------------------------------------------ |
|
95 |
|
96 cFileObj *cMenuBrowse::lastselect=0; |
|
97 |
|
98 cMenuBrowse::cMenuBrowse(cFileSource *Source, bool Dirselect, bool WithID3, const char *title, const char * const *Excl) |
|
99 :cOsdMenu(title) |
|
100 { |
|
101 currentdir=parent=0; |
|
102 delete lastselect; lastselect=0; |
|
103 list=new cDirList; |
|
104 |
|
105 dirselectable=Dirselect; |
|
106 withID3=WithID3; |
|
107 excl=Excl; |
|
108 |
|
109 SetSource(Source); |
|
110 NewDir(currentdir); |
|
111 } |
|
112 |
|
113 cMenuBrowse::~cMenuBrowse() |
|
114 { |
|
115 free(parent); |
|
116 free(currentdir); |
|
117 delete list; |
|
118 } |
|
119 |
|
120 cFileObj *cMenuBrowse::CurrentItem(void) |
|
121 { |
|
122 cMenuBrowseItem *item = (cMenuBrowseItem *)Get(Current()); |
|
123 return item ? item->Item():0; |
|
124 } |
|
125 |
|
126 void cMenuBrowse::SetButtons(void) |
|
127 { |
|
128 SetHelp(tr("Select"), currentdir?tr("Parent"):0, 0, withID3?tr("ID3 info"):0); |
|
129 Display(); |
|
130 } |
|
131 |
|
132 void cMenuBrowse::SetSource(cFileSource *Source) |
|
133 { |
|
134 source=Source; |
|
135 free(currentdir); currentdir=0; |
|
136 free(parent); parent=0; |
|
137 source->GetRemember(currentdir,parent); |
|
138 } |
|
139 |
|
140 bool cMenuBrowse::LoadDir(const char *dir) |
|
141 { |
|
142 Clear(); |
|
143 Status(tr("Scanning directory...")); |
|
144 bool res=list->Load(source,dir,excl); |
|
145 if(res) { |
|
146 cFileObj *item=list->First(); |
|
147 while(item) { |
|
148 Add(new cMenuBrowseItem(item),(parent && !strcmp(item->Name(),parent))); |
|
149 item=list->Next(item); |
|
150 } |
|
151 } |
|
152 Status(0); |
|
153 return res; |
|
154 } |
|
155 |
|
156 bool cMenuBrowse::NewDir(const char *dir) |
|
157 { |
|
158 char *ncur=dir ? strdup(dir):0; |
|
159 bool r=LoadDir(ncur); |
|
160 if(!r && ncur) { |
|
161 free(ncur); ncur=0; |
|
162 r=LoadDir(ncur); |
|
163 } |
|
164 if(r) { |
|
165 free(currentdir); currentdir=ncur; |
|
166 |
|
167 cFileObj *item=CurrentItem(); |
|
168 source->SetRemember(currentdir,item?item->Name():0); |
|
169 |
|
170 SetButtons(); |
|
171 return true; |
|
172 } |
|
173 free(ncur); |
|
174 Error(tr("Error scanning directory!")); |
|
175 return false; |
|
176 } |
|
177 |
|
178 eOSState cMenuBrowse::Parent(void) |
|
179 { |
|
180 eOSState res=osContinue; |
|
181 |
|
182 if(currentdir) { |
|
183 free(parent); |
|
184 char *ss=strrchr(currentdir,'/'); |
|
185 if(ss) { |
|
186 *ss++=0; |
|
187 parent=strdup(ss); |
|
188 ss=currentdir; |
|
189 } |
|
190 else parent=strdup(currentdir); |
|
191 |
|
192 if(!NewDir(ss)) res=osEnd; |
|
193 } |
|
194 return res; |
|
195 } |
|
196 |
|
197 eOSState cMenuBrowse::Select(bool isred) |
|
198 { |
|
199 eOSState res=osContinue; |
|
200 cFileObj *item; |
|
201 |
|
202 if((item=CurrentItem())) { |
|
203 switch(item->Type()) { |
|
204 case otParent: |
|
205 if(!isred || !dirselectable) |
|
206 res=Parent(); |
|
207 break; |
|
208 case otDir: |
|
209 if(!isred || !dirselectable) { |
|
210 if(!NewDir(item->Path())) res=osEnd; |
|
211 break; |
|
212 } |
|
213 // fall through to otFile |
|
214 case otFile: |
|
215 lastselect=new cFileObj(item); |
|
216 res=osBack; |
|
217 break; |
|
218 default: |
|
219 break; |
|
220 } |
|
221 } |
|
222 return res; |
|
223 } |
|
224 |
|
225 eOSState cMenuBrowse::ID3Info(void) |
|
226 { |
|
227 return osContinue; |
|
228 } |
|
229 |
|
230 eOSState cMenuBrowse::ProcessStdKey(eKeys Key, eOSState state) |
|
231 { |
|
232 if(state==osUnknown) { |
|
233 switch (Key) { |
|
234 case kOk: state=Select(false); break; |
|
235 case kRed: state=Select(true); break; |
|
236 case kGreen: state=Parent(); break; |
|
237 case kBlue: if(withID3) state=ID3Info(); |
|
238 break; |
|
239 //case kMenu: state=osEnd; break; |
|
240 default: break; |
|
241 } |
|
242 } |
|
243 if(state==osEnd || state==osBack) { |
|
244 cFileObj *item=CurrentItem(); |
|
245 if(item) source->SetRemember(currentdir,item->Name()); |
|
246 } |
|
247 return state; |
|
248 } |
|
249 |
|
250 // --- cMenuSourceItem ---------------------------------------------------------- |
|
251 |
|
252 class cMenuSourceItem : public cOsdItem { |
|
253 private: |
|
254 cFileSource *source; |
|
255 virtual void Set(void); |
|
256 public: |
|
257 cMenuSourceItem(cFileSource *Source); |
|
258 cFileSource *Source(void) { return source; } |
|
259 }; |
|
260 |
|
261 cMenuSourceItem::cMenuSourceItem(cFileSource *Source) |
|
262 { |
|
263 source=Source; |
|
264 Set(); |
|
265 } |
|
266 |
|
267 void cMenuSourceItem::Set(void) |
|
268 { |
|
269 char *buffer=0; |
|
270 asprintf(&buffer, "%s\t%s\t%s", source->NeedsMount()?(source->Status()?"*":">"):"", source->Description(), source->BaseDir()); |
|
271 SetText(buffer,false); |
|
272 } |
|
273 |
|
274 // --- cMenuSource -------------------------------------------------- |
|
275 |
|
276 cFileSource *cMenuSource::selected=0; |
|
277 |
|
278 cMenuSource::cMenuSource(cFileSources *Sources, const char *title) |
|
279 :cOsdMenu(title,2,20) |
|
280 { |
|
281 selected=0; |
|
282 current=Sources->GetSource(); |
|
283 cFileSource *source=Sources->First(); |
|
284 while(source) { |
|
285 cOsdMenu::Add(new cMenuSourceItem(source),source==current); |
|
286 source=Sources->Next(source); |
|
287 } |
|
288 |
|
289 SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject")); |
|
290 Display(); |
|
291 } |
|
292 |
|
293 bool cMenuSource::DoMount(cFileSource *src) |
|
294 { |
|
295 bool res=src->Mount(); |
|
296 RefreshCurrent(); |
|
297 DisplayCurrent(true); |
|
298 return res; |
|
299 } |
|
300 |
|
301 bool cMenuSource::CheckMount(void) |
|
302 { |
|
303 cFileSource *src=selected ? selected:current; |
|
304 if(src->NeedsMount() && !src->Status()) { |
|
305 Error(tr("Selected source is not mounted!")); |
|
306 return false; |
|
307 } |
|
308 return true; |
|
309 } |
|
310 |
|
311 eOSState cMenuSource::Select(void) |
|
312 { |
|
313 if(HasSubMenu() || Count() == 0) return osContinue; |
|
314 |
|
315 cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); |
|
316 if(src->NeedsMount() && !src->Status()) { |
|
317 if(!DoMount(src)) Error(tr("Mount failed!")); |
|
318 } |
|
319 if(!src->NeedsMount() || src->Status()) { |
|
320 selected=src; |
|
321 return osBack; |
|
322 } |
|
323 return osContinue; |
|
324 } |
|
325 |
|
326 eOSState cMenuSource::Mount(void) |
|
327 { |
|
328 if(HasSubMenu() || Count() == 0) return osContinue; |
|
329 |
|
330 cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); |
|
331 if(src->NeedsMount() && !src->Status()) { |
|
332 if(DoMount(src)) Info(tr("Mount succeeded")); |
|
333 else Error(tr("Mount failed!")); |
|
334 } |
|
335 return osContinue; |
|
336 } |
|
337 |
|
338 eOSState cMenuSource::Unmount(void) |
|
339 { |
|
340 if(HasSubMenu() || Count() == 0) return osContinue; |
|
341 |
|
342 cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); |
|
343 if(src->NeedsMount() && src->Status()) { |
|
344 bool res=src->Unmount(); |
|
345 RefreshCurrent(); |
|
346 DisplayCurrent(true); |
|
347 if(res) Info(tr("Unmount succeeded")); |
|
348 else Error(tr("Unmount failed!")); |
|
349 } |
|
350 return osContinue; |
|
351 } |
|
352 |
|
353 eOSState cMenuSource::Eject(void) |
|
354 { |
|
355 if(HasSubMenu() || Count() == 0) return osContinue; |
|
356 |
|
357 cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source(); |
|
358 if(src->NeedsMount()) { |
|
359 bool res=src->Eject(); |
|
360 RefreshCurrent(); |
|
361 DisplayCurrent(true); |
|
362 if(!res) Error(tr("Eject failed!")); |
|
363 } |
|
364 return osContinue; |
|
365 } |
|
366 |
|
367 eOSState cMenuSource::ProcessKey(eKeys Key) |
|
368 { |
|
369 eOSState state = cOsdMenu::ProcessKey(Key); |
|
370 |
|
371 if(state==osBack && !CheckMount()) state=osContinue; |
|
372 if(state==osUnknown) { |
|
373 switch(Key) { |
|
374 case kOk: |
|
375 case kRed: return Select(); |
|
376 case kGreen: return Mount(); |
|
377 case kYellow: return Unmount(); |
|
378 case kBlue: return Eject(); |
|
379 case kMenu: CheckMount(); return osEnd; |
|
380 default: break; |
|
381 } |
|
382 } |
|
383 return state; |
|
384 } |
|
385 |
|
386 // --- cProgressBar ------------------------------------------------------------ |
|
387 |
|
388 cProgressBar::cProgressBar(int Width, int Height, int Current, int Total) |
|
389 :cBitmap(Width, Height, 2) |
|
390 { |
|
391 if(Total > 0) { |
|
392 int p = Current * Width / Total;; |
|
393 #if APIVERSNUM >= 10307 |
|
394 DrawRectangle(0, 0, p, Height - 1, clrGreen); |
|
395 DrawRectangle(p + 1, 0, Width - 1, Height - 1, clrWhite); |
|
396 #else |
|
397 Fill(0, 0, p, Height - 1, clrGreen); |
|
398 Fill(p + 1, 0, Width - 1, Height - 1, clrWhite); |
|
399 #endif |
|
400 } |
|
401 } |
|
402 |