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"
34 #include "vvideolive.h"
43 class MediaDirectory {
52 void setDirname(const char * n) {
53 if (dirname) delete dirname;
56 dirname=new char[strlen(n)+1];
59 void setDisplayname(const char * n) {
60 if (displayname) delete displayname;
63 displayname=new char[strlen(n)+1];
64 strcpy(displayname,n);
66 void setFullpath(const char * n) {
67 if (fullpath) delete fullpath;
70 fullpath=new char[strlen(n)+1];
73 void setSelection(int s) {
76 void setMediaType(ULONG n) {mtype=n;}
77 void setSortorder(int s) {
80 const char * getDirname() {
83 const char * getDisplayname() {
84 if (displayname) return displayname;
85 if (fullpath) return fullpath;
86 if (dirname) return dirname;
89 const char * getFullPath() {
95 ULONG getMediaType(){return mtype;}
100 MediaDirectory(const char *d) : dirname(NULL),displayname(NULL),fullpath(NULL),selection(0),
101 sortorder(0),mtype(MEDIA_TYPE_ALL){
104 MediaDirectory(MediaDirectory &c) {
105 MediaDirectory(c.getDirname());
106 setDisplayname(c.getDisplayname());
107 setSelection(c.getSelection());
108 setMediaType(c.getMediaType());
109 setSortorder(c.getSortorder());
112 if (dirname) delete dirname;
113 if (displayname) delete displayname;
114 if (fullpath) delete fullpath;
118 typedef vector<MediaDirectory*> MDirList;
126 list.push_back(new MediaDirectory(NULL));
129 MDirList::iterator it;
130 for (it=list.begin();it<list.end();it++) {
134 MediaDirectory *getCurrent() {
135 return list[current];
137 const char * getPath() {
138 return getCurrent()->getFullPath();
148 int append(const char *dirname) {
149 if (! dirname) return current;
150 MediaDirectory* md=new MediaDirectory(dirname);
151 const char *cp=getCurrent()->getFullPath();
152 int len=strlen(dirname)+2;
153 if (cp) len+=strlen(cp);
154 char * fp=new char[len];
160 else if (*dirname != '/' ) strcpy(fp,"/");
176 class MediaSorterName
179 bool operator() (const Media* a, const Media* b)
181 if (b->getMediaType() == MEDIA_TYPE_DIR &&
182 a->getMediaType() != MEDIA_TYPE_DIR)
184 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
185 a->getMediaType() == MEDIA_TYPE_DIR)
187 int c = strcmp(b->getFileName(), a->getFileName());
188 if (c > 0) return true;
193 //a sorter with a randomly initialized order
194 class MediaSorterRandom
197 MediaSorterRandom(int start) {
200 bool operator() (const Media* a, const Media* b)
202 if (b->getMediaType() == MEDIA_TYPE_DIR &&
203 a->getMediaType() != MEDIA_TYPE_DIR)
205 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
206 a->getMediaType() == MEDIA_TYPE_DIR)
208 unsigned char suma=sum(a->getFileName(),(unsigned char)mystart);
209 unsigned char sumb=sum(b->getFileName(),(unsigned char)mystart);
210 if (sumb > suma) return true;
214 unsigned char sum(const char *name,unsigned char start) {
215 for (;*name!=0;name++) start=start ^ (unsigned char)*name;
222 struct MediaSorterTime
224 bool operator() (const Media* a, const Media* b)
226 if (b->getMediaType() == MEDIA_TYPE_DIR &&
227 a->getMediaType() != MEDIA_TYPE_DIR)
229 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
230 a->getMediaType() == MEDIA_TYPE_DIR)
232 if (b->getTime()>a->getTime()) return true;
238 VMediaList::VMediaList()
240 boxstack = BoxStack::getInstance();
242 dirlist=new DirList();
243 Log::getInstance()->log("VMediaList::VMediaList", Log::DEBUG, "dirlist=%p,curren=%p",dirlist,dirlist->getCurrent());
244 dirlist->getCurrent()->setSortorder(SORT_NAME);
247 if (Video::getInstance()->getFormat() == Video::PAL)
253 setTitleBarColour(Colour::TITLEBARBACKGROUND);
255 sl.setPosition(10, 30 + 5);
256 sl.setSize(area.w - 20, area.h - 30 - 15 - 30);
266 VMediaList::~VMediaList()
272 void VMediaList::clearMediaList() {
275 for (UINT i = 0; i < mediaList->size(); i++)
277 delete (*mediaList)[i];
287 int VMediaList::getNumEntries(int mediaType,int lowerThen) {
288 if (mediaType == MEDIA_TYPE_ALL && lowerThen < 0) return mediaList->size();
289 if (lowerThen < 0) lowerThen=mediaList->size();
291 for (int i=0;i<(int)(mediaList->size()) && i <= lowerThen;i++) {
292 if ((*mediaList)[i]->getMediaType() & mediaType) rt++;
297 void VMediaList::setList(MediaList* tlist)
299 if (mediaList != tlist) {
304 sortList(dirlist->getCurrent()->getSortorder());
305 updateSelectList(dirlist->getCurrent()->getSelection());
309 void VMediaList::updateSelectList(){
310 updateSelectList(-1);
312 void VMediaList::updateSelectList(int currentNumber){
314 char tempA[Media::TIMEBUFLEN];
315 Log::getInstance()->log("VMediaList::updateSelectList", Log::DEBUG, "media=%p",mediaList);
317 ULONG currentSelection=0;
318 if (sl.getNumOptions() >= 1 && currentNumber < 0) {
319 currentSelection=sl.getCurrentOptionData();
327 for (UINT i = 0; i < mediaList->size(); i++)
329 media = (*mediaList)[i];
330 if (media->getMediaType() == MEDIA_TYPE_DIR) {
331 sprintf(str, "%04u %s [%s]", i,media->getTimeString(tempA), media->getDisplayName());
332 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
333 media->index = sl.addOption(str, (ULONG)media, first);
336 sprintf(str, "%04u %s %s", i,media->getTimeString(tempA), media->getDisplayName());
337 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
338 media->index = sl.addOption(str, (ULONG)media, first);
343 if (currentNumber >= 0) sl.hintSetCurrent(currentNumber);
344 else sl.hintSetCurrent(0);
345 if (currentSelection != 0) {
347 //position to the previous selection
348 for (int i=0;i<sl.getNumOptions();i++) {
349 sl.hintSetCurrent(i);
350 if (sl.getCurrentOptionData() == currentSelection) {
355 if (! found) sl.hintSetCurrent(0);
358 if (sl.getNumOptions() > 0)
363 void VMediaList::highlightMedia(Media* media)
365 sl.hintSetCurrent(media->index);
368 boxstack->update(this);
371 void VMediaList::draw()
373 Log::getInstance()->log("VMediaList::draw", Log::DEBUG, "namestr=%s",dirlist->getCurrent()->getDisplayname());
375 SNPRINTF(title, 398, tr("Media - %s"), dirlist->getCurrent()->getDisplayname());
381 sl.setVisible(false);
383 drawText(tr("Loading..."), 240, 180, Colour::LIGHTTEXT);
387 //if (sl.getNumOptions() > 0) sl.draw();
391 // Put the status stuff at the bottom
396 w.nextSymbol = WSymbol::UP;
397 w.setPosition(20, 385);
400 w.nextSymbol = WSymbol::DOWN;
401 w.setPosition(50, 385);
404 w.nextSymbol = WSymbol::SKIPBACK;
405 w.setPosition(85, 385);
408 w.nextSymbol = WSymbol::SKIPFORWARD;
409 w.setPosition(115, 385);
412 w.nextSymbol = WSymbol::PLAY;
413 w.setPosition(150, 385);
420 void VMediaList::doShowingBar()
422 int topOption = sl.getTopOption() + 1;
423 if (sl.getNumOptions() == 0) topOption = 0;
426 const char* strmode=tr("Name");
437 SNPRINTF(showing, 250,tr("%i to %i of %i"),
438 topOption, sl.getBottomOption(), sl.getNumOptions());
441 // b.setSurfaceOffset(220, 385);
442 // b.setDimensions(160, 25);
443 // b.fillColour(Colour::VIEWBACKGROUND);
444 // b.drawText(showing, 0, 0, Colour::LIGHTTEXT);
446 rectangle(200, 384, 18, 16, Colour::VIDEOBLUE);
447 rectangle(220, 385, 220+160, 385+25, Colour::VIEWBACKGROUND);
448 drawText(strmode, 220, 385, Colour::LIGHTTEXT);
449 drawText(showing, 280, 385, Colour::LIGHTTEXT);
450 if (sl.getCurrentOptionData() != 0) Log::getInstance()->log("VMediaList",Log::DEBUG,"selected %s",((Media *)sl.getCurrentOptionData())->getDisplayName());
453 Media * VMediaList::getMedia(int ltype,ULONG move) {
454 int cur=sl.getCurrentOption();
458 int last=sl.getCurrentOption();
470 m=(Media*)sl.getCurrentOptionData();
471 if (m->getMediaType() & ltype) {
475 //stop if we are done
476 if (sl.getCurrentOption() == cur || sl.getCurrentOption() == last) break;
481 int VMediaList::handleCommand(int command)
487 sl.hintSetCurrent(0);
490 boxstack->update(this);
500 boxstack->update(this);
503 case Remote::DF_DOWN:
510 boxstack->update(this);
513 case Remote::SKIPBACK:
519 boxstack->update(this);
522 case Remote::SKIPFORWARD:
528 boxstack->update(this);
536 boxstack->update(this);
539 sortList(SORT_RANDOM);
540 boxstack->update(this);
544 boxstack->update(this);
552 if (mediaList) media = (Media*)sl.getCurrentOptionData();
553 if (media == NULL) return 2;
554 Log::getInstance()->log("VMediaList", Log::DEBUG, "activated %lu", media->index);
555 switch(media->getMediaType())
560 Log::getInstance()->log("VMediaList", Log::DEBUG, "create child for %s",media->getFileName());
561 if (media->getFileName() == NULL ) return 2;
562 if (sl.getNumOptions() >=1) {
563 dirlist->getCurrent()->setSelection(sl.getCurrentOption());
565 dirlist->getCurrent()->setSortorder(sortOrder);
566 dirlist->append(media->getFileName());
567 //same sort order for next level
568 dirlist->getCurrent()->setSortorder(sortOrder);
572 case MEDIA_TYPE_AUDIO:
573 Log::getInstance()->log("VMediaList", Log::DEBUG, "play audio file %s",
574 media->getFileName());
575 VAudioplayer::createPlayer(this,command==Remote::PLAY);
577 case MEDIA_TYPE_VIDEO:
578 Log::getInstance()->log("VMediaList", Log::DEBUG, "play video file %s",
579 media->getFileName());
582 case MEDIA_TYPE_PICTURE:
583 Log::getInstance()->log("VMediaList", Log::DEBUG, "show picture file %s",
584 media->getFileName());
585 VPicture::createViewer(this,command==Remote::PLAY);
589 Log::getInstance()->log("VMediaList", Log::DEBUG, "unknown media type %d file %s",
590 media->getMediaType(),media->getFileName());
594 VVideoLive* v = new VVideoLive(mediaList, media->type, this);
600 v->medianelChange(VVideoLive::NUMBER, media->number);
607 if (dirlist->getLevel() < 1) return 4;
612 // stop command getting to any more views
616 void VMediaList::processMessage(Message* m)
618 if (m->message == Message::MOUSE_MOVE)
620 if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
624 boxstack->update(this);
627 else if (m->message == Message::MOUSE_LBDOWN)
629 if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
631 boxstack->handleCommand(Remote::OK); //simulate OK press
634 { //check if press is outside this view! then simulate cancel
635 int x=(m->parameter>>16)-getScreenX();
636 int y=(m->parameter&0xFFFF)-getScreenY();
637 if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
639 boxstack->handleCommand(Remote::BACK); //simulate cancel press
645 int VMediaList::createList() {
646 Log::getInstance()->log("VMediaList::createList", Log::DEBUG, "");
647 VMediaList *vmn=new VMediaList();
648 //show the "loading" indicator
649 BoxStack::getInstance()->add(vmn);
652 BoxStack::getInstance()->remove(vmn);
657 void VMediaList::sortList(int newSort) {
658 if (sortOrder == newSort) return;
659 Log::getInstance()->log("VMediaList::sortList", Log::DEBUG, "p=%p,sort=%d, size=%d",this,newSort,mediaList->size());
660 if (mediaList->begin() != mediaList->end()) {
663 ::sort(mediaList->begin(),mediaList->end(),MediaSorterTime());
666 ::sort(mediaList->begin(),mediaList->end(),MediaSorterName());
669 ::sort(mediaList->begin(),mediaList->end(),MediaSorterRandom(time(NULL)));
678 int VMediaList::load() {
682 boxstack->update(this);
683 VDR* vdr=VDR::getInstance();
684 Log::getInstance()->log("VMediaList::load", Log::DEBUG, "load list for %s",dirlist->getPath());
685 if (vdr->isConnected()) {
686 MediaDirectory *md=dirlist->getCurrent();
687 MediaList *mn=vdr->getMediaList(md->getFullPath(),md->getMediaType());
691 boxstack->update(this);
695 if (! vdr->isConnected()) {
696 Command::getInstance()->connectionLost();
699 Log::getInstance()->log("VMediaList", Log::ERR, "unable to get MediaList for %s",dirlist->getPath());
701 VInfo* vi = new VInfo();
702 vi->setSize(400, 150);
706 vi->setTitleBarOn(0);
708 if (Video::getInstance()->getFormat() == Video::PAL)
709 vi->setPosition(170, 200);
711 vi->setPosition(160, 150);
712 vi->setOneLiner(tr("unable to get media list"));
715 Message* m = new Message();
716 m->message = Message::ADD_VIEW;
718 m->parameter = (ULONG)vi;
719 Command::getInstance()->postMessageNoLock(m);
724 const char * VMediaList::getDirname() const {
725 return dirlist->getCurrent()->getFullPath();