]> git.vomp.tv Git - vompclient.git/blob - vmedialist.cc
20 warnings. Ish. Change Message::ADD_VIEW to use void* data for view pointer
[vompclient.git] / vmedialist.cc
1 /*
2     Copyright 2004-2005 Chris Tallon, Andreas Vogel
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP 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 VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 /*
21    Hints for the directory playing:
22    depending on the configValue directoryMode: none|audio|picture|count
23    it will be decided what to do if a directory is selected with [PLAY]:
24     none:    as currently - simply go into
25     audio:   start picture viewer and audio, audio on top
26     picture: start picture viewer and audio, picture on top
27     count:   count occurence of both types, decide for audio/picture
28    Synchronization is done via the "directoryDone" call,
29    this is issued if the Viewer top engine has finished it's list
30    (getMedia returned 0)
31    We will the go back one level and continue
32    Currently we will traverse to new directories only at the beginning 
33    or the real end of each dir.
34    This is handled only by playAll (never by getMedia).
35    As we sort always in a way that all directories come first this should be OK.
36    there are 2 situations where we give the user a chance to interrupt (this is handled
37    by starting a 10ms timer and afterwrads sending a PLAYER_EVENT with the timer ref as
38    parameter):
39    empty directory found - timer 1 - call directoryDone
40    after changing to a new directory the first entry is again a directory - timer 2 - playAll
41    controlling flags:
42      directoryPlaying: globally set as long as we play a dir, reset on any key press here
43      startLevel:       in DirList - set to the level where we started playing, if we are
44                        back to this playing is finished
45      configuredDirmode: configured mode
46      
47 */
48
49
50
51 #include <vector>
52 #include <time.h>
53 #include <string.h>
54 #ifndef WIN32
55 #include "unistd.h"
56 #endif
57 #include "vmedialist.h"
58
59 #include "vmediaview.h"
60 #include "vvideomedia.h"
61 #include "input.h"
62 #include "wsymbol.h"
63 #include "boxstack.h"
64 #include "colour.h"
65 #include "video.h"
66 #include "i18n.h"
67 #include "vdr.h"
68 #include "messagequeue.h"
69 #include "vinfo.h"
70 #include "media.h"
71 #include "mediaplayer.h"
72 #include "log.h"
73 #include "localmediafile.h"
74 #include "mediaoptions.h"
75
76 //a ref count holder
77 class MediaListHolder {
78   public:
79     MediaListHolder(MediaList *l) {
80       _list=l;
81       _ref=1;
82     }
83     MediaList * list() {
84       return _list;
85     }
86     void ref() {
87       _ref++;
88       Log::getInstance()->log("##MLH",Log::DEBUG,"ref %p now %d",_list,_ref);
89     }
90     void unref() {
91       if (_ref >0 ) _ref--;
92       Log::getInstance()->log("##MLH",Log::DEBUG,"unref %p now %d",_list,_ref);
93       if (_ref == 0) delete this;
94     }
95     ~MediaListHolder() {
96       if (_list) delete _list;
97     }
98   private:
99     UINT _ref;
100     MediaList *_list;
101 };
102
103 class MediaDirectory {
104         private:
105     MediaURI *uri;
106                 int selection;
107                 int sortorder;
108                 ULONG mtype;
109     MediaListHolder *holder;
110         public:
111                 void setMediaType(ULONG n) {mtype=n;}
112                 void setSortorder(int s) {
113                         sortorder=s;
114                 }
115                 void setSelection(int s) {
116                         selection=s;
117                 }
118                 int getSelection() {
119                         return selection;
120                 }
121     bool move(ULONG mv) {
122       if (! holder) return false;
123       switch(mv) {
124         case VMediaList::MV_NEXT:
125           if (selection < ((int)holder->list()->size() -1)) {
126             selection++;
127             return true;
128           }
129           break;
130         case VMediaList::MV_PREV:
131           if (selection > 0) {
132             selection--;
133             return true;
134           }
135           break;
136       }
137       return false;
138     }
139
140                 ULONG getMediaType(){return mtype;}
141                 int getSortorder() {
142                         return sortorder;
143                 }
144     const MediaURI * getURI() {
145       return uri;
146     }
147     const char * getDisplayName() {
148       if (! uri || ! uri->getDisplayName()) return "/";
149       return uri->getDisplayName();
150     }
151     //get the holder (increment refcount)
152     MediaListHolder *getHolder() {
153       if ( !holder) return NULL;
154       holder->ref();
155       return holder;
156     }
157     //assign a holder to the directory (auto ref)
158     void assignHolder(MediaListHolder *h) {
159       if (holder) holder->unref();
160       holder=NULL;
161       if (! h) return;
162       h->ref();
163       holder=h;
164     }
165     //constructor with copy!
166                 MediaDirectory(const MediaURI *u) : selection(0),
167             sortorder(0),mtype(MEDIA_TYPE_ALL),holder(NULL){
168         if (u) 
169           uri=new MediaURI(u);
170         else
171           uri=NULL;
172                   }
173                 MediaDirectory(MediaDirectory &c) {
174                         setSelection(c.getSelection());
175                         setMediaType(c.getMediaType());
176                         setSortorder(c.getSortorder());
177       uri=new MediaURI(c.getURI());
178       holder=c.getHolder();
179                 }
180                 ~MediaDirectory() {
181       if (uri) delete uri;
182       if (holder) holder->unref();
183                 }
184 };
185
186 typedef std::vector<MediaDirectory*> MDirList;
187 class DirList {
188         private:
189                 int current;
190     int startlevel;
191     MDirList list;
192         public:
193                 DirList() {
194                         current=0;
195       startlevel=0;
196                         list.push_back(new MediaDirectory(NULL));
197                 }
198     DirList(DirList *cp) {
199       current=-1;
200       for (MDirList::iterator it=cp->list.begin();it<cp->list.end();it++) {
201         list.push_back(new MediaDirectory(*(*it)));
202         current++;
203       }
204       if (current < 0) {
205         list.push_back(new MediaDirectory(NULL));
206         current=0;
207       }
208       startlevel=cp->startlevel;
209       if (startlevel > current) startlevel=current;
210     }
211                 ~DirList() {
212                         MDirList::iterator it;
213                         for (it=list.begin();it<list.end();it++) {
214                                 delete *it;
215                         }
216                 }
217                 MediaDirectory *getCurrent() {
218                         return list[current];
219                 }
220                 const MediaURI * getURI() {
221                         return getCurrent()->getURI();
222                 }
223                 int dropTop() {
224                         if (current > 0) {
225                                 current--;
226                                 delete list.back();
227                                 list.pop_back();
228                         }
229                         return current;
230                 }
231                 int append(const MediaURI *uri) {
232                         if (! uri) return current;
233                         MediaDirectory* md=new MediaDirectory(uri);
234                         list.push_back(md);
235                         current++;
236                         return current;
237                 }
238
239                 int getLevel() {
240                         return current;
241                 }
242     void setStartLevel() {
243       startlevel=current;
244     }
245     bool isOnStartLevel() {
246       return (startlevel == current);
247     }
248
249 };
250
251
252 class MediaSorterName
253 {
254   public:
255   bool operator() (const Media* a, const Media* b)
256   {
257     if (b->getMediaType() == MEDIA_TYPE_DIR &&
258          a->getMediaType() != MEDIA_TYPE_DIR)
259       return false;
260     if ( b->getMediaType() != MEDIA_TYPE_DIR &&
261         a->getMediaType() == MEDIA_TYPE_DIR)
262       return true;
263     int c = strcmp(b->getFileName(), a->getFileName());
264     if (c > 0) return true;
265     return false;
266   }
267 };
268
269 //a sorter with a randomly initialized order
270 class MediaSorterRandom
271 {
272   public:
273   MediaSorterRandom(int start) {
274     mystart=start;
275   }
276   bool operator() (const Media* a, const Media* b)
277   {
278     if (b->getMediaType() == MEDIA_TYPE_DIR &&
279          a->getMediaType() != MEDIA_TYPE_DIR)
280       return false;
281     if ( b->getMediaType() != MEDIA_TYPE_DIR &&
282         a->getMediaType() == MEDIA_TYPE_DIR)
283       return true;
284     unsigned char suma=sum(a->getFileName(),(unsigned char)mystart);
285     unsigned char sumb=sum(b->getFileName(),(unsigned char)mystart);
286     if (sumb > suma) return true;
287     return false;
288   }
289   private:
290   unsigned char sum(const char *name,unsigned char start) {
291     for (;*name!=0;name++) start=start ^ (unsigned char)*name;
292     return start;
293   }
294   int mystart;
295 };
296
297
298 struct MediaSorterTime
299 {
300   bool operator() (const Media* a, const Media* b)
301   {
302     if (b->getMediaType() == MEDIA_TYPE_DIR &&
303          a->getMediaType() != MEDIA_TYPE_DIR)
304       return false;
305     if ( b->getMediaType() != MEDIA_TYPE_DIR &&
306         a->getMediaType() == MEDIA_TYPE_DIR)
307       return true;
308     if (b->getTime()>a->getTime()) return true;
309     return false;
310   }
311 };
312
313
314 VMediaList::VMediaList()
315 {
316   boxstack = BoxStack::getInstance();
317
318   Log::getInstance()->log("VMediaList::VMediaList", Log::DEBUG, "start");
319         dirlist=new DirList();
320   audiodirlist=NULL;
321   Log::getInstance()->log("VMediaList::VMediaList", Log::DEBUG, "dirlist=%p,curren=%p",dirlist,dirlist->getCurrent());
322         dirlist->getCurrent()->setSortorder(SORT_NAME);
323   setSize(570, 420);
324   createBuffer();
325   if (Video::getInstance()->getFormat() == Video::PAL)
326     setPosition(80, 70);
327   else
328     setPosition(70, 35);
329
330   setTitleBarOn(1);
331   setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
332
333   sl.setPosition(10, 30 + 5);
334   sl.setSize(area.w - 20, area.h - 30 - 15 - 30);
335   sl.addColumn(0);
336   sl.addColumn(60);
337   add(&sl);
338   
339   loading=true;
340   sortOrder=SORT_NONE;
341   viewer=NULL;
342   dirmode=M_NONE;
343   const char *dmstring=MediaOptions::getInstance()->getStringOption("DirectoryPlayMode");
344   if (dmstring) {
345     if (strcmp(dmstring,"count") == 0) dirmode=M_COUNT;
346     else if (strcmp(dmstring,"audio") == 0) dirmode=M_AUDIO;
347     else if (strcmp(dmstring,"picture") == 0) dirmode=M_PICTURE;
348   }
349   playingAll=false;
350   //init additional providers
351 #ifndef WIN32
352   LocalMediaFile::init();
353 #endif
354 }
355
356
357 VMediaList::~VMediaList()
358 {
359   Log::getInstance()->log("VMediaList::~VMediaList", Log::DEBUG, "start");
360   Timers::getInstance()->cancelTimer(this,1);
361   Timers::getInstance()->cancelTimer(this,2);
362   removeViewer();
363   delete dirlist;
364   if (audiodirlist) delete audiodirlist;
365   Log::getInstance()->log("VMediaList::~VMediaList", Log::DEBUG, "finished");
366 }
367
368 void VMediaList::removeViewer() {
369   if (viewer) {
370       BoxStack::getInstance()->remove(viewer);
371   }
372   viewer=NULL;
373 }
374
375 VMediaView * VMediaList::getViewer() {
376   if (! viewer) {
377     viewer=VMediaView::createViewer(this);
378   }
379   return viewer;
380 }
381
382
383 void VMediaList::playAudio(bool all,bool activate, bool showInfo) {
384   MediaListHolder *h=dirlist->getCurrent()->getHolder();
385   if (! h) return;
386   VMediaView *player=getViewer();
387   //OK make a copy of the current active list for audio playing
388   if (audiodirlist) delete audiodirlist;
389   audiodirlist=new DirList(dirlist);
390   player->play(all,activate,MV_NONE,showInfo);
391   h->unref();
392 }
393
394 void VMediaList::updateAll() {
395   BoxStack::getInstance()->update(this);
396   if (viewer) BoxStack::getInstance()->update(viewer);
397   BoxStack::getInstance()->update(NULL);
398 }
399
400
401
402
403 int VMediaList::getNumEntries(ULONG mediaType,int lowerThen,bool noAudioList) {
404   MediaListHolder *h=dirlist->getCurrent()->getHolder();
405   Log::getInstance()->log("VMediaList",Log::DEBUG,"getNumEntries type=%lu,lt=%d,na=%d,h=%p,l=%p",
406       mediaType,lowerThen,(int)noAudioList,h,(h?h->list():0));
407   if (! h) return 0;
408   if (mediaType == MEDIA_TYPE_ALL && lowerThen < 0) {
409     h->unref();
410     return h->list()->size();
411   }
412   if (lowerThen < 0) lowerThen=h->list()->size();
413   int rt=0;
414   MediaList *ml=h->list();
415   h->unref();
416   if (mediaType == MEDIA_TYPE_AUDIO) {
417     //OK we look into the separate audiolist (if we have it...)
418     if (audiodirlist && ! noAudioList) {
419       MediaListHolder *ah=audiodirlist->getCurrent()->getHolder();
420       if (ah) {
421         ml=ah->list();
422         ah->unref();
423       }
424     }
425   }
426   for (int i=0;i<(int)(ml->size()) && i <= lowerThen;i++) {
427     if ((*ml)[i]->getMediaType() & mediaType) rt++;
428   }
429   return rt;
430 }
431
432 void VMediaList::setList(MediaListHolder* tlist)
433 {
434   dirlist->getCurrent()->assignHolder(tlist);
435   sortOrder=SORT_NONE;
436   sortList(dirlist->getCurrent()->getSortorder());
437   updateSelectList(dirlist->getCurrent()->getSelection());
438 }
439
440
441 void VMediaList::updateSelectList(){
442         updateSelectList(-1);
443 }
444 void VMediaList::updateSelectList(int currentNumber){
445   MediaListHolder *h=dirlist->getCurrent()->getHolder();
446   char str[5000];
447   char tempA[Media::TIMEBUFLEN];
448   Log::getInstance()->log("VMediaList::updateSelectList", Log::DEBUG, "media=%p",h);
449   if (! h) return;
450
451   ULONG currentSelection=0;
452   if (sl.getNumOptions() >= 1 && currentNumber < 0) {
453     currentSelection=sl.getCurrentOptionData();
454         }
455   sl.clear();
456
457   Media* media;
458   int first = 1;
459   if (h && h->list())
460   {
461     for (UINT i = 0; i < h->list()->size(); i++)
462     {
463       media = (*h->list())[i];
464       if (media->getMediaType() == MEDIA_TYPE_DIR) {
465         sprintf(str, "%04u  %s  [%s]", i,media->getTimeString(tempA), media->getDisplayName());
466         //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
467         media->index = sl.addOption(str, (ULONG)media, first);
468       }
469       else {
470         sprintf(str, "%04u  %s  %s", i,media->getTimeString(tempA), media->getDisplayName());
471         //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
472         media->index = sl.addOption(str, (ULONG)media, first);
473       }
474       first = 0;
475     }
476   }
477         if (currentNumber >= 0) sl.hintSetCurrent(currentNumber);
478         else sl.hintSetCurrent(0);
479   if (currentSelection != 0) {
480     bool found=false;
481     //position to the previous selection
482     for (int i=0;i<sl.getNumOptions();i++) {
483       sl.hintSetCurrent(i);
484       if (sl.getCurrentOptionData() == currentSelection) {
485         found=true;
486         break;
487       }
488     }
489     if (! found) sl.hintSetCurrent(0);
490   }
491   loading=false;
492   if (sl.getNumOptions() > 0)
493     sl.draw();
494   doShowingBar();
495   if (h) h->unref();
496 }
497
498
499 void VMediaList::draw()
500 {
501   Log::getInstance()->log("VMediaList::draw", Log::DEBUG, "namestr=%s",dirlist->getCurrent()->getDisplayName());
502   char title[400];
503   SNPRINTF(title, 398, tr("Media - %s"), dirlist->getCurrent()->getDisplayName());
504   title[399]=0;
505   setTitleText(title);
506   
507   if (loading)
508   {
509     sl.setVisible(false);
510     TBBoxx::draw();
511     drawText(tr("Loading..."), 240, 180, DrawStyle::LIGHTTEXT);
512   }
513   else 
514   {
515     //if (sl.getNumOptions() > 0) sl.draw();
516     sl.setVisible(true);
517     TBBoxx::draw();
518
519     // Put the status stuff at the bottom
520
521     WSymbol w;
522     TEMPADD(&w);
523
524     w.nextSymbol = WSymbol::UP;
525     w.setPosition(20, 385);
526     w.draw();
527
528     w.nextSymbol = WSymbol::DOWN;
529     w.setPosition(50, 385);
530     w.draw();
531
532     w.nextSymbol = WSymbol::SKIPBACK;
533     w.setPosition(85, 385);
534     w.draw();
535
536     w.nextSymbol = WSymbol::SKIPFORWARD;
537     w.setPosition(115, 385);
538     w.draw();
539
540     w.nextSymbol = WSymbol::PLAY;
541     w.setPosition(150, 385);
542     w.draw();
543
544     doShowingBar();
545   }
546 }
547
548 void VMediaList::doShowingBar()
549 {
550   int topOption = sl.getTopOption() + 1;
551   if (sl.getNumOptions() == 0) topOption = 0;
552
553   char showing[250];
554   const char* strmode=NULL;
555   switch (sortOrder) {
556     case SORT_TIME:
557       strmode=tr("Time");
558       break;
559     case SORT_NAME:
560       strmode=tr("Name");
561       break;
562     default:
563       strmode=tr("Rand");
564       break;
565   }
566   SNPRINTF(showing, 250,tr("%i to %i of %i"), 
567       topOption, sl.getBottomOption(), sl.getNumOptions());
568
569 //  Box b;
570 //  b.setSurfaceOffset(220, 385);
571 //  b.setDimensions(160, 25);
572 //  b.fillColour(DrawStyle::VIEWBACKGROUND);
573 //  b.drawText(showing, 0, 0, DrawStyle::LIGHTTEXT);
574
575   rectangle(200, 384, 18, 16, DrawStyle::VIDEOBLUE);
576   rectangle(220, 385, 220+160, 385+25, DrawStyle::VIEWBACKGROUND);
577   drawText(strmode, 220, 385, DrawStyle::LIGHTTEXT);
578   drawText(showing, 280, 385, DrawStyle::LIGHTTEXT);
579   if (sl.getCurrentOptionData() != 0) Log::getInstance()->log("VMediaList",Log::DEBUG,"selected %s",((Media *)sl.getCurrentOptionData())->getDisplayName());
580 }
581
582 //find the next entry in the media list
583 //return the index in the list (starting with 0)
584 //return -1 if none found
585 int VMediaList::findNextEntry(int current, MediaList *list,ULONG ltype, ULONG move,bool wrap) {
586   if (! list) return -1;
587   if (current < 0) current=0;
588   if (current >= (int)list->size()) current=list->size()-1;
589   int next=current;
590   int rt=-1;
591   bool again=true;
592   while (again) {
593     switch (move) {
594       case MV_PREV:
595         next--;
596         break;
597       case MV_NEXT:
598         next++;
599         break;
600       default:
601         again=false;
602         break;
603     }
604     if (next < 0) {
605       if (! wrap) {
606         break;
607       }
608       else {
609         next=list->size()-1;
610       }
611     }
612     if (next >= (int)list->size()) {
613       if (! wrap) {
614         break;
615       }
616       else {
617         next=0;
618       }
619     }
620     if (next == current && move != MV_NONE) {
621       break;
622     }
623     if (((*list)[next])->getMediaType() != ltype) {
624       ;
625     } 
626     else {
627       rt=next;
628       break;
629     }
630   }
631   return rt;
632 }
633
634
635
636
637 Media * VMediaList::getMedia(ULONG ltype,ULONG move) {
638   Media *rt=NULL;
639   MediaList *list=NULL;
640   MediaListHolder *h=NULL;
641   Log::getInstance()->log("VMediaList",Log::DEBUG,"getMedia, t=%lu, mv=%lu",ltype,move);
642   //we have 2 lists:
643   //the currently active one (dirlist->getCurrent()->getHolder())
644   //and potentially a second one for audio (audiolist)
645   //currently (no recursive playing) we should always have an attached medialist in the audiolist
646   if (ltype == MEDIA_TYPE_AUDIO && audiodirlist != NULL ) {
647     h=audiodirlist->getCurrent()->getHolder();
648     if (! h) {
649       Log::getInstance()->log("VMediaList",Log::ERR,"getMedia AUDIO empty medialist");
650       return NULL;
651     }
652     int nentry=findNextEntry(audiodirlist->getCurrent()->getSelection(),h->list(),ltype,move,false);
653     if (nentry < 0) {
654       Log::getInstance()->log("VMediaList",Log::DEBUG,"getMedia AUDIO no next entry");
655       h->unref();
656       return NULL;
657     }
658     audiodirlist->getCurrent()->setSelection(nentry);
659     list=h->list();
660     rt=new Media((*list)[nentry]);
661     h->unref();
662     Log::getInstance()->log("VMediaList",Log::DEBUG,"getMedia AUDIO next entry %d",nentry);
663   }
664   else {
665     h=dirlist->getCurrent()->getHolder();
666     if (! h) {
667       Log::getInstance()->log("VMediaList",Log::ERR,"getMedia PICTURE empty medialist");
668       return NULL;
669     }
670     int nentry=findNextEntry(dirlist->getCurrent()->getSelection(),h->list(),ltype,move,false);
671     if (nentry < 0) {
672       Log::getInstance()->log("VMediaList",Log::DEBUG,"getMedia type=%lu no next entry",ltype);
673       h->unref();
674       return NULL;
675     }
676     Log::getInstance()->log("VMediaList",Log::DEBUG,"getMedia type=%lu next entry %d",ltype,nentry);
677     dirlist->getCurrent()->setSelection(nentry);
678     updateSelection(true);
679     list=h->list();
680     h->unref();
681     rt=new Media((*list)[nentry]);
682   }
683   if (! rt->getURI()) {
684     MediaURI *uri=list->getURI(rt);
685     rt->setURI(uri);
686     delete uri;
687   }
688   return rt;
689 }
690
691 void VMediaList::updateSelection(bool toSelectList) {
692   if (! toSelectList) 
693     dirlist->getCurrent()->setSelection(sl.getCurrentOption());
694   else {
695     sl.hintSetCurrent(dirlist->getCurrent()->getSelection());
696     sl.draw();
697   }
698 }
699
700 Media * VMediaList::getCurrentMedia(DirList *dl) {
701   if (! dl) return NULL;
702   MediaDirectory *d=dirlist->getCurrent();
703   if (! d) return NULL;
704   MediaListHolder *h=d->getHolder();
705   if (! h) return NULL;
706   if (d->getSelection() < 0 || d->getSelection() >= (int)h->list()->size()) return NULL;
707   Media *rt= (*h->list())[d->getSelection()];
708   h->unref();
709   return rt;
710 }
711
712
713 int VMediaList::handleCommand(int command)
714 {
715   playingAll=false;
716   switch(command)
717   {
718     case Input::ONE:
719     {
720       sl.hintSetCurrent(0);
721       sl.draw();
722       updateSelection();
723       doShowingBar();
724       boxstack->update(this);
725       return 2;
726     }
727     case Input::DF_UP:
728     case Input::UP:
729     {
730       sl.up();
731       sl.draw();
732       updateSelection();
733
734       doShowingBar();
735       boxstack->update(this);
736       return 2;
737     }
738     case Input::DF_DOWN:
739     case Input::DOWN:
740     {
741       sl.down();
742       sl.draw();
743       updateSelection();
744
745       doShowingBar();
746       boxstack->update(this);
747       return 2;
748     }
749     case Input::SKIPBACK:
750     {
751       sl.pageUp();
752       sl.draw();
753       updateSelection();
754
755       doShowingBar();
756       boxstack->update(this);
757       return 2;
758     }
759     case Input::SKIPFORWARD:
760     {
761       sl.pageDown();
762       sl.draw();
763       updateSelection();
764
765       doShowingBar();
766       boxstack->update(this);
767       return 2;
768     }
769     case Input::BLUE:
770     {
771       switch(sortOrder) {
772         case SORT_NAME:
773           sortList(SORT_TIME);
774           boxstack->update(this);
775           return 2;
776         case SORT_TIME:
777           sortList(SORT_RANDOM);
778           boxstack->update(this);
779           return 2;
780         default:
781           sortList(SORT_NAME);
782           boxstack->update(this);
783           return 2;
784       }
785     }
786     case Input::OK:
787     case Input::PLAY:
788     {
789       Media* media = NULL;
790       if (dirlist) media = getCurrentMedia(dirlist);
791       if (media == NULL) return 2;
792       Log::getInstance()->log("VMediaList", Log::DEBUG, "activated %lu", media->index);
793       switch(media->getMediaType())
794       {
795         case MEDIA_TYPE_DIR:
796         { 
797         //create child
798         Log::getInstance()->log("VMediaList", Log::DEBUG, "create child for %s",media->getFileName());
799         if (media->getFileName() == NULL ) return 2;
800         if (command == Input::PLAY) {
801           dirlist->setStartLevel();
802           playingAll=true;
803         }
804         bool rt=changeDirectory(media);
805         if (command == Input::PLAY && rt) {
806           playAll();
807         }
808         else {
809           playingAll=false;
810         }
811         break;
812         }
813         case MEDIA_TYPE_AUDIO:
814         Log::getInstance()->log("VMediaList", Log::DEBUG, "play audio file %s",
815           media->getFileName());
816         if (dirmode != M_NONE && command == Input::PLAY)
817           playAll();
818         else
819           playAudio(command==Input::PLAY,true,true);
820         break;
821         case MEDIA_TYPE_VIDEO: {
822 #ifndef WIN32 //Only DVB style MPEG is supported by the Windows Part!
823         Log::getInstance()->log("VMediaList", Log::DEBUG, "play video file %s",
824           media->getFileName());
825         //OK - simply today
826         if (! media->getURI()) {
827           //addURI
828           MediaListHolder *h=dirlist->getCurrent()->getHolder();
829           if (!h) {
830             Log::getInstance()->log("VMediaList", Log::ERR, "no media List");
831             break;
832           }
833           MediaURI *u=h->list()->getURI(media);
834           media->setURI(u);
835           delete u;
836           h->unref();
837         }
838         removeViewer();
839         VVideoMedia *v=new VVideoMedia(media,this);
840         BoxStack::getInstance()->add(v);
841         BoxStack::getInstance()->update(v);
842         v->go(false);
843         //play video
844 #endif
845       }break;
846         case MEDIA_TYPE_PICTURE:
847         Log::getInstance()->log("VMediaList", Log::DEBUG, "show picture file %s",
848          media->getFileName());
849         if (dirmode != M_NONE && command == Input::PLAY)
850           playAll();
851         else
852           getViewer()->showPicture(MV_NONE,command==Input::PLAY,true);
853         break;
854         default:
855         Log::getInstance()->log("VMediaList", Log::DEBUG, "unknown media type %d file %s",
856           media->getMediaType(),media->getFileName());
857
858         }
859       /*
860       VVideoLive* v = new VVideoLive(dirlist->getCurrent()->getHolder(), media->type, this);
861
862       v->draw();
863       boxstack->add(v);
864       boxstack->updatev);
865
866       v->medianelChange(VVideoLive::NUMBER, media->number);
867       */
868
869       return 2;
870     }
871     case Input::BACK:
872     {
873                         if (dirlist->getLevel() < 1) return 4;
874                         dirlist->dropTop();
875                         load();
876     }
877   }
878   // stop command getting to any more views
879   return 1;
880 }
881
882 //go to the next level dir
883 //if OK - delete current medialist
884 bool VMediaList::changeDirectory(Media *media) {
885   Log::getInstance()->log("VMediaList",Log::DEBUG,"cd to %s",media->getFileName());
886   updateSelection();
887   dirlist->getCurrent()->setSortorder(sortOrder);
888   if (dirlist->getLevel() > 200) {
889     Log::getInstance()->log("VMediaList",Log::ERR,"above 300 levels, stop here...");
890     return false;
891   }
892   MediaListHolder *h=dirlist->getCurrent()->getHolder();
893   dirlist->getCurrent()->assignHolder(NULL); //prepare old holder for deletion
894   if (! h) {
895     return false;
896   }
897   MediaURI *uri=h->list()->getURI(media);
898   dirlist->append(uri);
899   delete uri;
900   //same sort order for next level
901   dirlist->getCurrent()->setSortorder(sortOrder);
902   int rt=load();
903   if (rt == 0) {
904     h->unref(); //this deletes now the old list
905     Log::getInstance()->log("VMediaList",Log::DEBUG,"cd OK");
906     return true;
907   }
908   //we were no able to load the new list - so go back to our current list
909   dirlist->dropTop();
910   dirlist->getCurrent()->assignHolder(h); //OK so we saved our list...
911   h->unref();
912   Log::getInstance()->log("VMediaList",Log::DEBUG,"cd  failed");
913   return false;
914 }
915
916 void VMediaList::directoryDone() {
917   if (! playingAll) return;
918   //go up until we are on the startlevel
919   Log::getInstance()->log("VMediaList", Log::DEBUG, "DirectoryDone ");
920   while ( ! dirlist->isOnStartLevel()) {
921     dirlist->dropTop();
922     load();
923     if (dirlist->isOnStartLevel()) break;
924     if (dirlist->getCurrent()->move(MV_NEXT))
925       break;
926   }
927   if ( dirlist->isOnStartLevel()) {
928     //OK we are done
929     playingAll=false;
930     Log::getInstance()->log("VMediaList", Log::DEBUG, "finished playing all l=%lu",dirlist->getLevel());
931     return;
932   }
933   updateSelection(true);
934   playAll();
935 }
936
937 bool VMediaList::playAll() {
938   if (dirmode == M_NONE) return false;
939   bool started=false;
940   if (! playingAll) {
941     //starting now
942     dirlist->setStartLevel();
943     playingAll=true;
944     started=true;
945   }
946   Media *media=getCurrentMedia(dirlist);
947   if (! media) {
948     //empty directory
949     Log::getInstance()->log("VMediaList", Log::DEBUG, "empty dir when calling playall");
950     //directoryDone
951     Timers::getInstance()->setTimerD(this,1,0,10000000l); //10ms
952     return true;
953   }
954   Media *mcopy=new Media(media);
955   Log::getInstance()->log("VMediaList", Log::DEBUG, "playing all name=%s,t=%lu, started=%d",
956       mcopy->getDisplayName(),mcopy->getMediaType(),(int)started);
957   while (mcopy->getMediaType()==MEDIA_TYPE_DIR) {
958     //recurse to the next directory
959     bool rt=changeDirectory(mcopy);
960     if (rt ) {
961       //OK succesfully changed dir
962       int entries=getNumEntries(MEDIA_TYPE_AUDIO|MEDIA_TYPE_DIR|MEDIA_TYPE_PICTURE);
963       Log::getInstance()->log("VMediaList", Log::DEBUG, "cd OK, entries=%d",entries);
964       media=getCurrentMedia(dirlist);
965       if (entries==0 || media == NULL) {
966         Log::getInstance()->log("VMediaList", Log::DEBUG, "playing all name=%s empty",mcopy->getDisplayName());
967         delete mcopy;
968         //trigger directory end with the ability of user intervention
969         Timers::getInstance()->setTimerD(this,1,0,10000000l); //10ms
970         return true;
971       }
972       delete mcopy;
973       mcopy=NULL;
974       if (media->getMediaType()==MEDIA_TYPE_DIR) {
975         //send a defered event to give the user a chance to interrupt
976         //will again call playAll (but this does not chage the start level)
977         Timers::getInstance()->setTimerD(this,2,0,10000000l); //10ms
978         return true;
979       }
980       break;
981     }
982     else 
983     {
984       //unable to change to the directory
985       if (dirlist->getCurrent()->move(MV_NEXT)) {
986         //OK there is still a next medium here
987         updateSelection(true);
988         media=getCurrentMedia(dirlist);
989         if (!media) {
990           Timers::getInstance()->setTimerD(this,1,0,10000000l); //10ms
991           return true;
992         }
993         delete mcopy;
994         mcopy=new Media(media);
995         continue;
996       }
997       //hmm - no entries here any more
998       //so we have to stop
999       delete mcopy;
1000       playingAll=false;
1001       return false;
1002     }
1003   }
1004   Log::getInstance()->log("VMediaList", Log::DEBUG, "playing all on level %d, sele=%d",
1005       dirlist->getLevel(),dirlist->getCurrent()->getSelection());
1006   delete mcopy;
1007   enum Dirmode currentMode=dirmode;
1008   //OK now we handled all directories - now deal with the current one
1009   //1st determine the number of entries
1010   int aentries=getNumEntries(MEDIA_TYPE_AUDIO,-1,true);
1011   int pentries=getNumEntries(MEDIA_TYPE_PICTURE,-1,true);
1012   if (aentries == 0 && pentries == 0) {
1013     directoryDone();
1014     return false;
1015   }
1016   if (currentMode == M_COUNT) {
1017     if (aentries > pentries) currentMode=M_AUDIO;
1018     else currentMode=M_PICTURE;
1019   }
1020   Log::getInstance()->log("VMediaList", Log::DEBUG, "mode=%d,ae=%d,pe=%d",currentMode,aentries,pentries);
1021   //now find the matching entries and start playing
1022   MediaListHolder *h=dirlist->getCurrent()->getHolder();
1023   if (! h) {
1024     Log::getInstance()->log("VMediaList", Log::ERR, "playing all empty medialist");
1025     playingAll=false;
1026     return false;
1027   }
1028   Media *maudio=NULL;
1029   Media *mpicture=NULL;
1030   int audioselection=-1;
1031   int pictureselection=-1;
1032   for (int i=dirlist->getCurrent()->getSelection();i<(int)h->list()->size();i++) {
1033     Media *m=(*h->list())[i];
1034     if (m->getMediaType() == MEDIA_TYPE_AUDIO && maudio == NULL) {
1035       maudio=m;
1036       audioselection=i;
1037     }
1038     if (m->getMediaType() == MEDIA_TYPE_PICTURE && mpicture == NULL) {
1039       mpicture=m;
1040       pictureselection=i;
1041     }
1042     if (maudio != NULL && mpicture != NULL) break;
1043   }
1044   //OK now we found the first media for both - start players
1045   if (maudio != NULL) {
1046     dirlist->getCurrent()->setSelection(audioselection);
1047     playAudio(true,currentMode==M_AUDIO,mpicture==NULL); //this makes now a copy of dirlist...
1048   }
1049   if (mpicture != NULL) {
1050     dirlist->getCurrent()->setSelection(pictureselection);
1051     getViewer()->showPicture(MV_NONE,true,currentMode==M_PICTURE);
1052   }
1053   h->unref();
1054   updateSelection(true);
1055   return true;
1056 }
1057
1058
1059     
1060
1061   
1062
1063
1064  
1065 void VMediaList::processMessage(Message* m)
1066 {
1067   if (m->message == Message::MOUSE_MOVE)
1068   {
1069     if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
1070     {
1071       sl.draw();
1072       doShowingBar();
1073       boxstack->update(this);
1074       updateSelection();
1075     }
1076   }
1077   else if (m->message == Message::MOUSE_LBDOWN)
1078   {
1079     if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
1080     {
1081       updateSelection();
1082       boxstack->handleCommand(Input::OK); //simulate OK press
1083     }
1084     else
1085     { //check if press is outside this view! then simulate cancel
1086       int x=(m->parameter>>16)-getScreenX();
1087       int y=(m->parameter&0xFFFF)-getScreenY();
1088       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
1089       {
1090         boxstack->handleCommand(Input::BACK); //simulate cancel press
1091       }
1092     }
1093   }
1094   else if (m->message == Message::PLAYER_EVENT) {
1095     switch (m->parameter) {
1096       case 1:
1097         directoryDone();
1098         break;
1099       case 2:
1100         playAll();
1101         break;
1102     }
1103   }
1104 }
1105
1106 int VMediaList::createList() {
1107    Log::getInstance()->log("VMediaList::createList", Log::DEBUG, "");
1108    VMediaList *vmn=new VMediaList();
1109    //show the "loading" indicator
1110    BoxStack::getInstance()->add(vmn);
1111    int rt=vmn->load();
1112    if ( rt != 0) {
1113      BoxStack::getInstance()->remove(vmn);
1114      }
1115    return rt;
1116 }
1117
1118 void VMediaList::sortList(int newSort) {
1119   MediaListHolder *h=dirlist->getCurrent()->getHolder();
1120   if (! h) return;
1121   Log::getInstance()->log("VMediaList::sortList", Log::DEBUG, "p=%p,sort=%d,osort=%d, size=%d",this,newSort,sortOrder,h->list()->size());
1122   if (sortOrder == newSort) return;
1123    if (h->list()->begin() != h->list()->end()) {
1124    switch (newSort) {
1125      case SORT_TIME:
1126        ::sort(h->list()->begin(),h->list()->end(),MediaSorterTime());
1127        break;
1128      case SORT_NAME:
1129        ::sort(h->list()->begin(),h->list()->end(),MediaSorterName());
1130        break;
1131      case SORT_RANDOM:
1132        ::sort(h->list()->begin(),h->list()->end(),MediaSorterRandom(time(NULL)));
1133        break;
1134      }
1135    }
1136    sortOrder=newSort;
1137    updateSelectList();
1138    h->unref();
1139    Log::getInstance()->log("VMediaList::sortList", Log::DEBUG, "done ");
1140 }
1141
1142
1143 int VMediaList::load() {
1144         
1145         loading=true;
1146         draw();
1147   boxstack->update(this);
1148   MediaPlayer * mp=MediaPlayer::getInstance();
1149   Log::getInstance()->log("VMediaList::load", Log::DEBUG, "load list for %p",dirlist->getURI());
1150         MediaDirectory *md=dirlist->getCurrent();
1151   MediaList *mn=NULL;
1152   if (md->getURI()) {
1153     mn=mp->getMediaList(md->getURI());
1154   }
1155   else {
1156     mn=mp->getRootList();
1157   }
1158   if (mn != NULL) {
1159     MediaListHolder *h=new MediaListHolder(mn);
1160     setList(h);
1161     h->unref();
1162     h=NULL;
1163     draw();
1164     boxstack->update(this);
1165     return 0;
1166     }
1167   else {
1168     Log::getInstance()->log("VMediaList", Log::ERR, "unable to get MediaList for %p",dirlist->getURI());
1169
1170     VInfo* vi = new VInfo();
1171     vi->setSize(400, 150);
1172     vi->createBuffer();
1173     vi->setExitable();
1174     vi->setBorderOn(1);
1175     vi->setTitleBarOn(0);
1176
1177     if (Video::getInstance()->getFormat() == Video::PAL)
1178       vi->setPosition(170, 200);
1179     else
1180       vi->setPosition(160, 150);
1181     vi->setOneLiner(tr("unable to get media list"));
1182     vi->draw();
1183
1184     Message* m = new Message();
1185     m->message = Message::ADD_VIEW;
1186     m->to = boxstack;
1187     m->data = reinterpret_cast<void*>(vi);
1188     MessageQueue::getInstance()->postMessage(m);
1189   }
1190   return 1;
1191 }
1192
1193 const char * VMediaList::getDirname(ULONG mtype) const {
1194   if (mtype == MEDIA_TYPE_AUDIO && audiodirlist) {
1195     return audiodirlist->getCurrent()->getDisplayName();
1196   }
1197   return dirlist->getCurrent()->getDisplayName();
1198 }
1199
1200 void VMediaList::timercall(int ref) {
1201   if (ref == 1 || ref == 2 ) {
1202     //send a directory done event 
1203     Message* m = new Message();
1204     m->message = Message::PLAYER_EVENT;
1205     m->to = this;
1206     m->parameter = ref;
1207     MessageQueue::getInstance()->postMessage(m);
1208   }
1209 }
1210  
1211