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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "vmedialist.h"
27 #include "vaudioplayer.h"
31 class MediaDirectory {
40 void setDirname(const char * n) {
41 if (dirname) delete dirname;
44 dirname=new char[strlen(n)+1];
47 void setDisplayname(const char * n) {
48 if (displayname) delete displayname;
51 displayname=new char[strlen(n)+1];
52 strcpy(displayname,n);
54 void setFullpath(const char * n) {
55 if (fullpath) delete fullpath;
58 fullpath=new char[strlen(n)+1];
61 void setSelection(int s) {
64 void setMediaType(ULONG n) {mtype=n;}
65 void setSortorder(int s) {
68 const char * getDirname() {
71 const char * getDisplayname() {
72 if (displayname) return displayname;
73 if (fullpath) return fullpath;
74 if (dirname) return dirname;
77 const char * getFullPath() {
83 ULONG getMediaType(){return mtype;}
88 MediaDirectory(const char *d) : dirname(NULL),displayname(NULL),fullpath(NULL),selection(0),
89 sortorder(0),mtype(MEDIA_TYPE_ALL){
92 MediaDirectory(MediaDirectory &c) {
93 MediaDirectory(c.getDirname());
94 setDisplayname(c.getDisplayname());
95 setSelection(c.getSelection());
96 setMediaType(c.getMediaType());
97 setSortorder(c.getSortorder());
100 if (dirname) delete dirname;
101 if (displayname) delete displayname;
102 if (fullpath) delete fullpath;
106 typedef vector<MediaDirectory*> MDirList;
114 list.push_back(new MediaDirectory(NULL));
117 MDirList::iterator it;
118 for (it=list.begin();it<list.end();it++) {
122 MediaDirectory *getCurrent() {
123 return list[current];
125 const char * getPath() {
126 return getCurrent()->getFullPath();
136 int append(const char *dirname) {
137 if (! dirname) return current;
138 MediaDirectory* md=new MediaDirectory(dirname);
139 const char *cp=getCurrent()->getFullPath();
140 int len=strlen(dirname)+2;
141 if (cp) len+=strlen(cp);
142 char * fp=new char[len];
148 else if (*dirname != '/' ) strcpy(fp,"/");
164 class MediaSorterName
167 bool operator() (const Media* a, const Media* b)
169 if (b->getMediaType() == MEDIA_TYPE_DIR &&
170 a->getMediaType() != MEDIA_TYPE_DIR)
172 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
173 a->getMediaType() == MEDIA_TYPE_DIR)
175 int c = strcmp(b->getFileName(), a->getFileName());
176 if (c > 0) return true;
181 //a sorter with a randomly initialized order
182 class MediaSorterRandom
185 MediaSorterRandom(int start) {
188 bool operator() (const Media* a, const Media* b)
190 if (b->getMediaType() == MEDIA_TYPE_DIR &&
191 a->getMediaType() != MEDIA_TYPE_DIR)
193 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
194 a->getMediaType() == MEDIA_TYPE_DIR)
196 unsigned char suma=sum(a->getFileName(),(unsigned char)mystart);
197 unsigned char sumb=sum(b->getFileName(),(unsigned char)mystart);
198 if (sumb > suma) return true;
202 unsigned char sum(const char *name,unsigned char start) {
203 for (;*name!=0;name++) start=start ^ (unsigned char)*name;
210 struct MediaSorterTime
212 bool operator() (const Media* a, const Media* b)
214 if (b->getMediaType() == MEDIA_TYPE_DIR &&
215 a->getMediaType() != MEDIA_TYPE_DIR)
217 if ( b->getMediaType() != MEDIA_TYPE_DIR &&
218 a->getMediaType() == MEDIA_TYPE_DIR)
220 if (b->getTime()>a->getTime()) return true;
226 VMediaList::VMediaList()
228 dirlist=new DirList();
229 Log::getInstance()->log("VMediaList::VMediaList", Log::DEBUG, "dirlist=%p,curren=%p",dirlist,dirlist->getCurrent());
230 dirlist->getCurrent()->setSortorder(SORT_NAME);
232 if (Video::getInstance()->getFormat() == Video::PAL)
234 setScreenPos(80, 70);
238 setScreenPos(70, 35);
241 setBackgroundColour(Colour::VIEWBACKGROUND);
243 setTitleBarColour(Colour::TITLEBARBACKGROUND);
245 sl.setSurface(surface);
246 sl.setSurfaceOffset(10, 30 + 5);
247 sl.setDimensions(area.w - 20, area.h - 30 - 15 - 30);
257 VMediaList::~VMediaList()
263 void VMediaList::clearMediaList() {
266 for (UINT i = 0; i < mediaList->size(); i++)
268 delete (*mediaList)[i];
278 int VMediaList::getNumEntries(int mediaType,int lowerThen) {
279 if (mediaType == MEDIA_TYPE_ALL && lowerThen < 0) return mediaList->size();
280 if (lowerThen < 0) lowerThen=mediaList->size();
282 for (int i=0;i<(int)(mediaList->size()) && i <= lowerThen;i++) {
283 if ((*mediaList)[i]->getMediaType() & mediaType) rt++;
288 void VMediaList::setList(MediaList* tlist)
290 if (mediaList != tlist) {
295 sortList(dirlist->getCurrent()->getSortorder());
296 updateSelectList(dirlist->getCurrent()->getSelection());
300 void VMediaList::updateSelectList(){
301 updateSelectList(-1);
303 void VMediaList::updateSelectList(int currentNumber){
305 char tempA[Media::TIMEBUFLEN];
306 Log::getInstance()->log("VMediaList::updateSelectList", Log::DEBUG, "media=%p",mediaList);
308 ULONG currentSelection=0;
309 if (sl.getNumOptions() >= 1 && currentNumber < 0) {
310 currentSelection=sl.getCurrentOptionData();
318 for (UINT i = 0; i < mediaList->size(); i++)
320 media = (*mediaList)[i];
321 if (media->getMediaType() == MEDIA_TYPE_DIR) {
322 sprintf(str, "%04u %s [%s]", i,media->getTimeString(tempA), media->getDisplayName());
323 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
324 media->index = sl.addOption(str, (ULONG)media, first);
327 sprintf(str, "%04u %s %s", i,media->getTimeString(tempA), media->getDisplayName());
328 //Log::getInstance()->log("VMediaList", Log::DEBUG, "add to select list %s",str);
329 media->index = sl.addOption(str, (ULONG)media, first);
334 if (currentNumber >= 0) sl.hintSetCurrent(currentNumber);
335 else sl.hintSetCurrent(0);
336 if (currentSelection != 0) {
338 //position to the previous selection
339 for (int i=0;i<sl.getNumOptions();i++) {
340 sl.hintSetCurrent(i);
341 if (sl.getCurrentOptionData() == currentSelection) {
346 if (! found) sl.hintSetCurrent(0);
349 if (sl.getNumOptions() > 0)
354 void VMediaList::highlightMedia(Media* media)
356 sl.hintSetCurrent(media->index);
359 ViewMan::getInstance()->updateView(this);
362 void VMediaList::draw()
364 Log::getInstance()->log("VMediaList::draw", Log::DEBUG, "namestr=%s",dirlist->getCurrent()->getDisplayname());
366 SNPRINTF(title, 398, tr("Media - %s"), dirlist->getCurrent()->getDisplayname());
372 drawText(tr("Loading..."), 240, 180, Colour::LIGHTTEXT);
375 if (sl.getNumOptions() > 0) sl.draw();
377 // Put the status stuff at the bottom
380 w.setSurface(surface);
382 w.nextSymbol = WSymbol::UP;
383 w.setSurfaceOffset(20, 385);
386 w.nextSymbol = WSymbol::DOWN;
387 w.setSurfaceOffset(50, 385);
390 w.nextSymbol = WSymbol::SKIPBACK;
391 w.setSurfaceOffset(85, 385);
394 w.nextSymbol = WSymbol::SKIPFORWARD;
395 w.setSurfaceOffset(115, 385);
398 w.nextSymbol = WSymbol::PLAY;
399 w.setSurfaceOffset(150, 385);
406 void VMediaList::doShowingBar()
408 int topOption = sl.getTopOption() + 1;
409 if (sl.getNumOptions() == 0) topOption = 0;
412 char * strmode=tr("Name");
423 snprintf(showing, 250,tr("%i to %i of %i"),
424 topOption, sl.getBottomOption(), sl.getNumOptions());
427 // b.setSurfaceOffset(220, 385);
428 // b.setDimensions(160, 25);
429 // b.fillColour(Colour::VIEWBACKGROUND);
430 // b.drawText(showing, 0, 0, Colour::LIGHTTEXT);
432 rectangle(200, 384, 18, 16, Colour::VIDEOBLUE);
433 rectangle(220, 385, 220+160, 385+25, Colour::VIEWBACKGROUND);
434 drawText(strmode, 220, 385, Colour::LIGHTTEXT);
435 drawText(showing, 280, 385, Colour::LIGHTTEXT);
436 if (sl.getCurrentOptionData() != 0) Log::getInstance()->log("VMediaList",Log::DEBUG,"selected %s",((Media *)sl.getCurrentOptionData())->getDisplayName());
439 Media * VMediaList::getMedia(int ltype,ULONG move) {
440 int cur=sl.getCurrentOption();
444 int last=sl.getCurrentOption();
456 m=(Media*)sl.getCurrentOptionData();
457 if (m->getMediaType() & ltype) {
461 //stop if we are done
462 if (sl.getCurrentOption() == cur || sl.getCurrentOption() == last) break;
467 int VMediaList::handleCommand(int command)
473 sl.hintSetCurrent(0);
476 ViewMan::getInstance()->updateView(this);
486 ViewMan::getInstance()->updateView(this);
489 case Remote::DF_DOWN:
496 ViewMan::getInstance()->updateView(this);
499 case Remote::SKIPBACK:
505 ViewMan::getInstance()->updateView(this);
508 case Remote::SKIPFORWARD:
514 ViewMan::getInstance()->updateView(this);
522 ViewMan::getInstance()->updateView(this);
525 sortList(SORT_RANDOM);
526 ViewMan::getInstance()->updateView(this);
530 ViewMan::getInstance()->updateView(this);
538 if (mediaList) media = (Media*)sl.getCurrentOptionData();
539 if (media == NULL) return 2;
540 Log::getInstance()->log("VMediaList", Log::DEBUG, "activated %lu", media->index);
541 switch(media->getMediaType())
546 Log::getInstance()->log("VMediaList", Log::DEBUG, "create child for %s",media->getFileName());
547 if (media->getFileName() == NULL ) return 2;
548 if (sl.getNumOptions() >=1) {
549 dirlist->getCurrent()->setSelection(sl.getCurrentOption());
551 dirlist->getCurrent()->setSortorder(sortOrder);
552 dirlist->append(media->getFileName());
553 //same sort order for next level
554 dirlist->getCurrent()->setSortorder(sortOrder);
558 case MEDIA_TYPE_AUDIO:
559 Log::getInstance()->log("VMediaList", Log::DEBUG, "play audio file %s",
560 media->getFileName());
561 VAudioplayer::createPlayer(this,command==Remote::PLAY);
563 case MEDIA_TYPE_VIDEO:
564 Log::getInstance()->log("VMediaList", Log::DEBUG, "play video file %s",
565 media->getFileName());
568 case MEDIA_TYPE_PICTURE:
569 Log::getInstance()->log("VMediaList", Log::DEBUG, "show picture file %s",
570 media->getFileName());
571 VPicture::createViewer(this,command==Remote::PLAY);
575 Log::getInstance()->log("VMediaList", Log::DEBUG, "unknown media type %d file %s",
576 media->getMediaType(),media->getFileName());
580 VVideoLive* v = new VVideoLive(mediaList, media->type, this);
583 ViewMan::getInstance()->add(v);
584 ViewMan::getInstance()->updateView(v);
586 v->medianelChange(VVideoLive::NUMBER, media->number);
593 if (dirlist->getLevel() < 1) return 4;
598 // stop command getting to any more views
602 void VMediaList::processMessage(Message* m)
604 if (m->message == Message::MOUSE_MOVE)
606 if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
610 ViewMan::getInstance()->updateView(this);
613 else if (m->message == Message::MOUSE_LBDOWN)
615 if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
617 ViewMan::getInstance()->handleCommand(Remote::OK); //simulate OK press
620 { //check if press is outside this view! then simulate cancel
621 int x=(m->parameter>>16)-getScreenX();
622 int y=(m->parameter&0xFFFF)-getScreenY();
623 if (x<0 || y <0 || x>getWidth() || y>getHeight())
625 ViewMan::getInstance()->handleCommand(Remote::BACK); //simulate cancel press
631 int VMediaList::createList() {
632 Log::getInstance()->log("VMediaList::createList", Log::DEBUG, "");
633 VMediaList *vmn=new VMediaList();
634 //show the "loading" indicator
635 ViewMan::getInstance()->add(vmn);
638 ViewMan::getInstance()->removeView(vmn);
643 void VMediaList::sortList(int newSort) {
644 if (sortOrder == newSort) return;
645 Log::getInstance()->log("VMediaList::sortList", Log::DEBUG, "p=%p,sort=%d, size=%d",this,newSort,mediaList->size());
646 if (mediaList->begin() != mediaList->end()) {
649 ::sort(mediaList->begin(),mediaList->end(),MediaSorterTime());
652 ::sort(mediaList->begin(),mediaList->end(),MediaSorterName());
655 ::sort(mediaList->begin(),mediaList->end(),MediaSorterRandom(time(NULL)));
664 int VMediaList::load() {
668 ViewMan::getInstance()->updateView(this);
669 VDR* vdr=VDR::getInstance();
670 Log::getInstance()->log("VMediaList::load", Log::DEBUG, "load list for %s",dirlist->getPath());
671 if (vdr->isConnected()) {
672 MediaDirectory *md=dirlist->getCurrent();
673 MediaList *mn=vdr->getMediaList(md->getFullPath(),md->getMediaType());
677 ViewMan::getInstance()->updateView(this);
681 if (! vdr->isConnected()) {
682 Command::getInstance()->connectionLost();
685 Log::getInstance()->log("VMediaList", Log::ERR, "unable to get MediaList for %s",dirlist->getPath());
686 VInfo* vi = new VInfo();
687 vi->create(400, 150);
690 vi->setTitleBarOn(0);
692 if (Video::getInstance()->getFormat() == Video::PAL)
693 vi->setScreenPos(170, 200);
695 vi->setScreenPos(160, 150);
696 vi->setOneLiner(tr("unable to get media list"));
699 Message* m = new Message();
700 m->message = Message::ADD_VIEW;
701 m->to = ViewMan::getInstance();
702 m->parameter = (ULONG)vi;
703 Command::getInstance()->postMessageNoLock(m);
708 const char * VMediaList::getDirname() const {
709 return dirlist->getCurrent()->getFullPath();