2 Copyright 2004-2005 Chris Tallon, Andreas Vogel
4 This file is part of VOMP.
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #include "vmedialist.h"
30 #include "vaudioplayer.h"
42 class MediaDirectory {
51 void setDirname(const char * n) {
52 if (dirname) delete dirname;
55 dirname=new char[strlen(n)+1];
58 void setDisplayname(const char * n) {
59 if (displayname) delete displayname;
62 displayname=new char[strlen(n)+1];
63 strcpy(displayname,n);
65 void setFullpath(const char * n) {
66 if (fullpath) delete fullpath;
69 fullpath=new char[strlen(n)+1];
72 void setSelection(int s) {
75 void setMediaType(ULONG n) {mtype=n;}
76 void setSortorder(int s) {
79 const char * getDirname() {
82 const char * getDisplayname() {
83 if (displayname) return displayname;
84 if (fullpath) return fullpath;
85 if (dirname) return dirname;
88 const char * getFullPath() {
94 ULONG getMediaType(){return mtype;}
99 MediaDirectory(const char *d) : dirname(NULL),displayname(NULL),fullpath(NULL),selection(0),
100 sortorder(0),mtype(MEDIA_TYPE_ALL){
103 MediaDirectory(MediaDirectory &c) {
104 MediaDirectory(c.getDirname());
105 setDisplayname(c.getDisplayname());
106 setSelection(c.getSelection());
107 setMediaType(c.getMediaType());
108 setSortorder(c.getSortorder());
111 if (dirname) delete dirname;
112 if (displayname) delete displayname;
113 if (fullpath) delete fullpath;
117 typedef vector<MediaDirectory*> MDirList;
125 list.push_back(new MediaDirectory(NULL));
128 MDirList::iterator it;
129 for (it=list.begin();it<list.end();it++) {
133 MediaDirectory *getCurrent() {
134 return list[current];
136 const char * getPath() {
137 return getCurrent()->getFullPath();
147 int append(const char *dirname) {
148 if (! dirname) return current;
149 MediaDirectory* md=new MediaDirectory(dirname);
150 const char *cp=getCurrent()->getFullPath();
151 int len=strlen(dirname)+2;
152 if (cp) len+=strlen(cp);
153 char * fp=new char[len];
159 else if (*dirname != '/' ) strcpy(fp,"/");
175 class MediaSorterName
178 bool operator() (const Media* a, const Media* b)
180 if (b->getMediaType() == MEDIA_TYPE_DIR &&
181 a->getMediaType() != MEDIA_TYPE_DIR)
183 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
184 a->getMediaType() == MEDIA_TYPE_DIR)
186 int c = strcmp(b->getFileName(), a->getFileName());
187 if (c > 0) return true;
192 //a sorter with a randomly initialized order
193 class MediaSorterRandom
196 MediaSorterRandom(int start) {
199 bool operator() (const Media* a, const Media* b)
201 if (b->getMediaType() == MEDIA_TYPE_DIR &&
202 a->getMediaType() != MEDIA_TYPE_DIR)
204 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
205 a->getMediaType() == MEDIA_TYPE_DIR)
207 unsigned char suma=sum(a->getFileName(),(unsigned char)mystart);
208 unsigned char sumb=sum(b->getFileName(),(unsigned char)mystart);
209 if (sumb > suma) return true;
213 unsigned char sum(const char *name,unsigned char start) {
214 for (;*name!=0;name++) start=start ^ (unsigned char)*name;
221 struct MediaSorterTime
223 bool operator() (const Media* a, const Media* b)
225 if (b->getMediaType() == MEDIA_TYPE_DIR &&
226 a->getMediaType() != MEDIA_TYPE_DIR)
228 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
229 a->getMediaType() == MEDIA_TYPE_DIR)
231 if (b->getTime()>a->getTime()) return true;
237 VMediaList::VMediaList()
239 boxstack = BoxStack::getInstance();
241 dirlist=new DirList();
242 Log::getInstance()->log("VMediaList::VMediaList", Log::DEBUG, "dirlist=%p,curren=%p",dirlist,dirlist->getCurrent());
243 dirlist->getCurrent()->setSortorder(SORT_NAME);
246 if (Video::getInstance()->getFormat() == Video::PAL)
252 setTitleBarColour(Colour::TITLEBARBACKGROUND);
254 sl.setPosition(10, 30 + 5);
255 sl.setSize(area.w - 20, area.h - 30 - 15 - 30);
265 VMediaList::~VMediaList()
271 void VMediaList::clearMediaList() {
274 for (UINT i = 0; i < mediaList->size(); i++)
276 delete (*mediaList)[i];
286 int VMediaList::getNumEntries(int mediaType,int lowerThen) {
287 if (mediaType == MEDIA_TYPE_ALL && lowerThen < 0) return mediaList->size();
288 if (lowerThen < 0) lowerThen=mediaList->size();
290 for (int i=0;i<(int)(mediaList->size()) && i <= lowerThen;i++) {
291 if ((*mediaList)[i]->getMediaType() & mediaType) rt++;
296 void VMediaList::setList(MediaList* tlist)
298 if (mediaList != tlist) {
303 sortList(dirlist->getCurrent()->getSortorder());
304 updateSelectList(dirlist->getCurrent()->getSelection());
308 void VMediaList::updateSelectList(){
309 updateSelectList(-1);
311 void VMediaList::updateSelectList(int currentNumber){
313 char tempA[Media::TIMEBUFLEN];
314 Log::getInstance()->log("VMediaList::updateSelectList", Log::DEBUG, "media=%p",mediaList);
316 ULONG currentSelection=0;
317 if (sl.getNumOptions() >= 1 && currentNumber < 0) {
318 currentSelection=sl.getCurrentOptionData();
326 for (UINT i = 0; i < mediaList->size(); i++)
328 media = (*mediaList)[i];
329 if (media->getMediaType() == MEDIA_TYPE_DIR) {
330 sprintf(str, "%04u %s [%s]", i,media->getTimeString(tempA), media->getDisplayName());
331 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
332 media->index = sl.addOption(str, (ULONG)media, first);
335 sprintf(str, "%04u %s %s", i,media->getTimeString(tempA), media->getDisplayName());
336 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
337 media->index = sl.addOption(str, (ULONG)media, first);
342 if (currentNumber >= 0) sl.hintSetCurrent(currentNumber);
343 else sl.hintSetCurrent(0);
344 if (currentSelection != 0) {
346 //position to the previous selection
347 for (int i=0;i<sl.getNumOptions();i++) {
348 sl.hintSetCurrent(i);
349 if (sl.getCurrentOptionData() == currentSelection) {
354 if (! found) sl.hintSetCurrent(0);
357 if (sl.getNumOptions() > 0)
362 void VMediaList::highlightMedia(Media* media)
364 sl.hintSetCurrent(media->index);
367 boxstack->update(this);
370 void VMediaList::draw()
372 Log::getInstance()->log("VMediaList::draw", Log::DEBUG, "namestr=%s",dirlist->getCurrent()->getDisplayname());
374 SNPRINTF(title, 398, tr("Media - %s"), dirlist->getCurrent()->getDisplayname());
380 sl.setVisible(false);
382 drawText(tr("Loading..."), 240, 180, Colour::LIGHTTEXT);
386 //if (sl.getNumOptions() > 0) sl.draw();
390 // Put the status stuff at the bottom
395 w.nextSymbol = WSymbol::UP;
396 w.setPosition(20, 385);
399 w.nextSymbol = WSymbol::DOWN;
400 w.setPosition(50, 385);
403 w.nextSymbol = WSymbol::SKIPBACK;
404 w.setPosition(85, 385);
407 w.nextSymbol = WSymbol::SKIPFORWARD;
408 w.setPosition(115, 385);
411 w.nextSymbol = WSymbol::PLAY;
412 w.setPosition(150, 385);
419 void VMediaList::doShowingBar()
421 int topOption = sl.getTopOption() + 1;
422 if (sl.getNumOptions() == 0) topOption = 0;
425 const char* strmode=tr("Name");
436 SNPRINTF(showing, 250,tr("%i to %i of %i"),
437 topOption, sl.getBottomOption(), sl.getNumOptions());
440 // b.setSurfaceOffset(220, 385);
441 // b.setDimensions(160, 25);
442 // b.fillColour(Colour::VIEWBACKGROUND);
443 // b.drawText(showing, 0, 0, Colour::LIGHTTEXT);
445 rectangle(200, 384, 18, 16, Colour::VIDEOBLUE);
446 rectangle(220, 385, 220+160, 385+25, Colour::VIEWBACKGROUND);
447 drawText(strmode, 220, 385, Colour::LIGHTTEXT);
448 drawText(showing, 280, 385, Colour::LIGHTTEXT);
449 if (sl.getCurrentOptionData() != 0) Log::getInstance()->log("VMediaList",Log::DEBUG,"selected %s",((Media *)sl.getCurrentOptionData())->getDisplayName());
452 Media * VMediaList::getMedia(int ltype,ULONG move) {
453 int cur=sl.getCurrentOption();
457 int last=sl.getCurrentOption();
469 m=(Media*)sl.getCurrentOptionData();
470 if (m->getMediaType() & ltype) {
474 //stop if we are done
475 if (sl.getCurrentOption() == cur || sl.getCurrentOption() == last) break;
480 int VMediaList::handleCommand(int command)
486 sl.hintSetCurrent(0);
489 boxstack->update(this);
499 boxstack->update(this);
502 case Remote::DF_DOWN:
509 boxstack->update(this);
512 case Remote::SKIPBACK:
518 boxstack->update(this);
521 case Remote::SKIPFORWARD:
527 boxstack->update(this);
535 boxstack->update(this);
538 sortList(SORT_RANDOM);
539 boxstack->update(this);
543 boxstack->update(this);
551 if (mediaList) media = (Media*)sl.getCurrentOptionData();
552 if (media == NULL) return 2;
553 Log::getInstance()->log("VMediaList", Log::DEBUG, "activated %lu", media->index);
554 switch(media->getMediaType())
559 Log::getInstance()->log("VMediaList", Log::DEBUG, "create child for %s",media->getFileName());
560 if (media->getFileName() == NULL ) return 2;
561 if (sl.getNumOptions() >=1) {
562 dirlist->getCurrent()->setSelection(sl.getCurrentOption());
564 dirlist->getCurrent()->setSortorder(sortOrder);
565 dirlist->append(media->getFileName());
566 //same sort order for next level
567 dirlist->getCurrent()->setSortorder(sortOrder);
571 case MEDIA_TYPE_AUDIO:
572 Log::getInstance()->log("VMediaList", Log::DEBUG, "play audio file %s",
573 media->getFileName());
574 VAudioplayer::createPlayer(this,command==Remote::PLAY);
576 case MEDIA_TYPE_VIDEO:
577 Log::getInstance()->log("VMediaList", Log::DEBUG, "play video file %s",
578 media->getFileName());
581 case MEDIA_TYPE_PICTURE:
582 Log::getInstance()->log("VMediaList", Log::DEBUG, "show picture file %s",
583 media->getFileName());
584 VPicture::createViewer(this,command==Remote::PLAY);
588 Log::getInstance()->log("VMediaList", Log::DEBUG, "unknown media type %d file %s",
589 media->getMediaType(),media->getFileName());
593 VVideoLive* v = new VVideoLive(mediaList, media->type, this);
599 v->medianelChange(VVideoLive::NUMBER, media->number);
606 if (dirlist->getLevel() < 1) return 4;
611 // stop command getting to any more views
615 void VMediaList::processMessage(Message* m)
617 if (m->message == Message::MOUSE_MOVE)
619 if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
623 boxstack->update(this);
626 else if (m->message == Message::MOUSE_LBDOWN)
628 if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
630 boxstack->handleCommand(Remote::OK); //simulate OK press
633 { //check if press is outside this view! then simulate cancel
634 int x=(m->parameter>>16)-getScreenX();
635 int y=(m->parameter&0xFFFF)-getScreenY();
636 if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
638 boxstack->handleCommand(Remote::BACK); //simulate cancel press
644 int VMediaList::createList() {
645 Log::getInstance()->log("VMediaList::createList", Log::DEBUG, "");
646 VMediaList *vmn=new VMediaList();
647 //show the "loading" indicator
648 BoxStack::getInstance()->add(vmn);
651 BoxStack::getInstance()->remove(vmn);
656 void VMediaList::sortList(int newSort) {
657 if (sortOrder == newSort) return;
658 Log::getInstance()->log("VMediaList::sortList", Log::DEBUG, "p=%p,sort=%d, size=%d",this,newSort,mediaList->size());
659 if (mediaList->begin() != mediaList->end()) {
662 ::sort(mediaList->begin(),mediaList->end(),MediaSorterTime());
665 ::sort(mediaList->begin(),mediaList->end(),MediaSorterName());
668 ::sort(mediaList->begin(),mediaList->end(),MediaSorterRandom(time(NULL)));
677 int VMediaList::load() {
681 boxstack->update(this);
682 VDR* vdr=VDR::getInstance();
683 Log::getInstance()->log("VMediaList::load", Log::DEBUG, "load list for %s",dirlist->getPath());
684 if (vdr->isConnected()) {
685 MediaDirectory *md=dirlist->getCurrent();
686 MediaList *mn=vdr->getMediaList(md->getFullPath(),md->getMediaType());
690 boxstack->update(this);
694 if (! vdr->isConnected()) {
695 Command::getInstance()->connectionLost();
698 Log::getInstance()->log("VMediaList", Log::ERR, "unable to get MediaList for %s",dirlist->getPath());
700 VInfo* vi = new VInfo();
701 vi->setSize(400, 150);
705 vi->setTitleBarOn(0);
707 if (Video::getInstance()->getFormat() == Video::PAL)
708 vi->setPosition(170, 200);
710 vi->setPosition(160, 150);
711 vi->setOneLiner(tr("unable to get media list"));
714 Message* m = new Message();
715 m->message = Message::ADD_VIEW;
717 m->parameter = (ULONG)vi;
718 Command::getInstance()->postMessageNoLock(m);
723 const char * VMediaList::getDirname() const {
724 return dirlist->getCurrent()->getFullPath();