trunk 20080912
[gitenigma.git] / src / sselect.cpp
blob4cd1507db1f53f604feea99d38a42744f4a9fb73
1 #include <algorithm>
2 #include <list>
4 #include <enigma.h>
5 #include <enigma_epg.h>
6 #include <enigma_main.h>
7 #include <enigma_plugins.h>
8 #include <sselect.h>
10 #include <lib/picviewer/pictureviewer.h>
11 #include <lib/base/i18n.h>
12 #include <lib/driver/rc.h>
13 #include <lib/dvb/edvb.h>
14 #include <lib/dvb/dvb.h>
15 #include <lib/dvb/service.h>
16 #include <lib/dvb/dvbservice.h>
17 #include <lib/dvb/epgcache.h>
18 #include <lib/dvb/frontend.h>
19 #include <lib/dvb/serviceplaylist.h>
20 #include <lib/dvb/record.h>
21 #include <lib/dvb/servicemp3.h>
22 #include <lib/gdi/font.h>
23 #include <lib/gui/actions.h>
24 #include <lib/gui/eskin.h>
25 #include <lib/gui/elabel.h>
26 #include <lib/gui/numberactions.h>
27 #include <lib/system/info.h>
28 #include <lib/system/init.h>
29 #include <lib/system/init_num.h>
30 #include <enigma_streamer.h>
31 #include <enigma_picmanager.h>
32 #include <epgwindow.h>
34 gFont eListBoxEntryService::serviceFont;
35 gFont eListBoxEntryService::descrFont;
36 gFont eListBoxEntryService::numberFont;
37 gPixmap *eListBoxEntryService::folder=0;
38 gPixmap *eListBoxEntryService::marker=0;
39 gPixmap *eListBoxEntryService::locked=0;
40 gPixmap *eListBoxEntryService::newfound=0;
41 int eListBoxEntryService::maxNumSize=0;
42 std::set<eServiceReference> eListBoxEntryService::hilitedEntrys;
43 eListBoxEntryService *eListBoxEntryService::selectedToMove=0;
44 int eListBoxEntryService::nownextEPG = 0;
45 eStreamer streamer;
46 bool streaming = false;
47 eServiceReference streamingRef;
49 struct EPGStyleSelectorActions
51 eActionMap map;
52 eAction infoPressed;
53 EPGStyleSelectorActions():
54 map("EPGStyleSelector", _("EPG Style Selector")),
55 infoPressed(map, "infoPressed", _("open the EPG with selected style"), eAction::prioDialog)
59 eAutoInitP0<EPGStyleSelectorActions> i_EPGStyleSelectorActions(eAutoInitNumbers::actions, "EPG Style Selector actions");
61 eEPGStyleSelector::eEPGStyleSelector(int ssel)
62 :eListBoxWindow<eListBoxEntryText>(_("EPG Style"), 5, 350, true)
63 ,ssel(ssel)
65 addActionMap( &i_EPGStyleSelectorActions->map );
66 move(ePoint(100, 100));
67 int last=1;
68 if ( ssel )
69 eConfig::getInstance()->getKey("/ezap/serviceselector/lastEPGStyle", last);
70 else
71 eConfig::getInstance()->getKey("/ezap/lastEPGStyle", last);
72 eListBoxEntryText *sel[3];
73 sel[0] = new eListBoxEntryText(&list,_("Channel EPG"), (void*)1, 0, _("open EPG for selected Channel") );
74 sel[1] = new eListBoxEntryText(&list,_("Multi EPG"), (void*)2, 0, _("open EPG for next five channels") );
76 // only show external EPG Entry when it realy exist..
77 eZapPlugins plugins(eZapPlugins::StandardPlugin);
78 if ( plugins.execPluginByName("extepg.cfg",true) == "OK"
79 || plugins.execPluginByName("_extepg.cfg",true) == "OK" )
80 sel[2] = new eListBoxEntryText(&list,_("External EPG"), (void*)3, 0, _("open external plugin EPG") );
82 list.setCurrent(sel[last-1]);
83 CONNECT( list.selected, eEPGStyleSelector::entrySelected );
86 int eEPGStyleSelector::eventHandler( const eWidgetEvent &event )
88 switch (event.type)
90 case eWidgetEvent::evtAction:
91 if ( event.action == &i_EPGStyleSelectorActions->infoPressed )
92 entrySelected( list.getCurrent() );
93 else
94 break;
95 return 1;
96 default:
97 break;
99 return eWindow::eventHandler( event );
102 void eEPGStyleSelector::entrySelected( eListBoxEntryText* e )
104 if (e)
106 if ( ssel )
107 eConfig::getInstance()->setKey("/ezap/serviceselector/lastEPGStyle", (int)e->getKey());
108 else
109 eConfig::getInstance()->setKey("/ezap/lastEPGStyle", (int)e->getKey());
110 close( (int)e->getKey() );
112 else
113 close(-1);
116 struct serviceSelectorActions
118 eActionMap map;
119 eAction nextBouquet, prevBouquet, pathUp, showEPGSelector, showMenu,
120 addService, addServiceToUserBouquet, modeTV, modeRadio,
121 modeFile, toggleStyle, toggleFocus, gotoPrevMarker, gotoNextMarker,
122 showAll, showSatellites, showProvider, showBouquets, deletePressed,
123 markPressed, renamePressed, insertPressed;
124 serviceSelectorActions():
125 map("serviceSelector", _("service selector")),
126 nextBouquet(map, "nextBouquet", _("switch to next bouquet"), eAction::prioDialogHi),
127 prevBouquet(map, "prevBouquet", _("switch to previous bouquet"), eAction::prioDialogHi),
128 pathUp(map, "pathUp", _("go up a directory"), eAction::prioDialog),
129 showEPGSelector(map, "showEPGSelector", _("shows the EPG selector for the highlighted channel"), eAction::prioDialog),
130 showMenu(map, "showMenu", _("show service selector menu"), eAction::prioDialog),
131 addService(map, "addService", _("add service to playlist"), eAction::prioDialog),
132 addServiceToUserBouquet(map, "addServiceToUserBouquet", _("add service to a specific bouquet"), eAction::prioDialog),
133 modeTV(map, "modeTV", _("switch to TV mode"), eAction::prioDialog),
134 modeRadio(map, "modeRadio", _("switch to Radio mode"), eAction::prioDialog),
135 modeFile(map, "modeFile", _("switch to File mode"), eAction::prioDialog),
136 toggleStyle(map, "toggleStyle", _("toggle between classic and multi column style"), eAction::prioDialog),
137 toggleFocus(map, "toggleFocus", _("toggle focus between service and bouquet list (in combi column style)"), eAction::prioDialog),
138 gotoPrevMarker(map, "gotoPrevMarker", _("go to the prev Marker if exist.. else goto first service"), eAction::prioDialogHi),
139 gotoNextMarker(map, "gotoNextMarker", _("go to the next Marker if exist.. else goto last service"), eAction::prioDialogHi),
141 showAll(map, "showAll", _("show all services"), eAction::prioDialog),
142 showSatellites(map, "showSatellites", _("show satellite list"), eAction::prioDialog),
143 showProvider(map, "showProvider", _("show provider list"), eAction::prioDialog),
144 showBouquets(map, "showBouquets", _("show bouquet list"), eAction::prioDialog),
146 deletePressed(map, "delete", _("delete selected entry"), eAction::prioDialog),
147 markPressed(map, "mark", _("mark selected entry for move"), eAction::prioDialog),
148 renamePressed(map, "rename", _("rename selected entry"), eAction::prioDialog),
149 insertPressed(map, "marker", _("create new marker entry"), eAction::prioDialog)
153 eAutoInitP0<serviceSelectorActions> i_serviceSelectorActions(eAutoInitNumbers::actions, "service selector actions");
155 eListBoxEntryService::eListBoxEntryService(eListBoxExt<eListBoxEntryService> *lb, const eServiceReference &service, int flags, int num)
156 :eListBoxEntry((eListBox<eListBoxEntry>*)lb), numPara(0),
157 namePara(0), descrPara(0), nameXOffs(0), flags(flags),
158 num(num), curEventId(-1), service(service)
160 static char strfilter[4] = { 0xC2, 0x87, 0x86, 0x00 };
161 if (!(flags & flagIsReturn))
163 #if 0
164 sort=eString().sprintf("%06d", service->service_number);
165 #else
166 if( service.descr )
167 sort = service.descr.c_str();
168 else
170 const eService *pservice=eServiceInterface::getInstance()->addRef(service);
171 if ( pservice )
173 sort=pservice?pservice->service_name.c_str():"";
174 eServiceInterface::getInstance()->removeRef(service);
177 sort.upper();
179 // filter short name brakets...
180 for (eString::iterator it(sort.begin()); it != sort.end();)
181 strchr( strfilter, *it ) ? it = sort.erase(it) : it++;
183 #endif
184 } else
185 sort="";
188 eListBoxEntryService::~eListBoxEntryService()
190 invalidate();
193 int eListBoxEntryService::getEntryHeight()
195 if (!descrFont.pointSize)
196 descrFont = eSkin::getActive()->queryFont("eServiceSelector.Entry.Description");
198 return calcFontHeight(serviceFont)+4;
201 void eListBoxEntryService::invalidate()
203 if (numPara)
205 numPara->destroy();
206 numPara=0;
208 if (descrPara)
210 descrPara->destroy();
211 descrPara=0;
213 if (namePara)
215 namePara->destroy();
216 namePara=0;
220 void eListBoxEntryService::invalidateDescr()
222 if (descrPara)
224 descrPara->destroy();
225 descrPara=0;
228 struct eListBoxEntryService_countServices
230 Signal1<void,const eServiceReference&> &callback;
231 int type;
232 int DVBNamespace;
233 int* count;
234 bool onlyNew;
235 eListBoxEntryService_countServices(int type, int DVBNamespace, int* count,bool onlyNew=false)
236 : callback(callback), type(type), DVBNamespace(DVBNamespace), count(count),onlyNew(onlyNew)
239 void operator()(const eServiceReference &service)
241 eService *s = eTransponderList::getInstance()->searchService( service );
242 if ( !s ) // dont show "removed services"
243 return;
244 else if ( s->dvb && s->dvb->dxflags & eServiceDVB::dxDontshow )
245 return;
246 if ( onlyNew && !(s->dvb && s->dvb->dxflags & eServiceDVB::dxNewFound ) )
247 return;
248 int t = ((eServiceReferenceDVB&)service).getServiceType();
249 int nspace = ((eServiceReferenceDVB&)service).getDVBNamespace().get()&0xFFFF0000;
250 if (t < 0)
251 t=0;
252 if (t >= 31)
253 t=31;
254 if ( type & (1<<t) && // right dvb service type
255 ( (DVBNamespace==(int)0xFFFFFFFF) || // ignore namespace
256 ( (DVBNamespace&(int)0xFFFF0000) == nspace ) // right satellite
259 (*count)++;
263 const eString &eListBoxEntryService::redraw(gPainter *rc, const eRect &rect, gColor coActiveB, gColor coActiveF, gColor coNormalB, gColor coNormalF, int hilited)
265 bool b;
267 if ( (b = (hilited == 2)) )
268 hilited = 0;
270 if (this == selectedToMove)
271 drawEntryRect(rc, rect, eSkin::getActive()->queryColor("eServiceSelector.entrySelectedToMove"), coActiveF, coNormalB, coNormalF, hilited );
272 else
273 drawEntryRect(rc, rect, coActiveB, coActiveF, coNormalB, coNormalF, hilited );
275 const eService *pservice=eServiceInterface::getInstance()->addRef(service);
277 std::set<eServiceReference>::iterator it = hilitedEntrys.find( service );
278 if ( it != hilitedEntrys.end() )
279 rc->setForegroundColor( eSkin::getActive()->queryColor("eServiceSelector.entryHilited") );
281 if ( service.flags & eServiceReference::isDirectory && folder ) // we draw the folder pixmap
283 nameXOffs = folder->x + 20;
284 int ypos = (rect.height() - folder->y) / 2;
285 rc->blit( *folder, ePoint(10, rect.top()+ypos ), eRect(), gPixmap::blitAlphaTest);
287 else if ( service.flags & eServiceReference::isMarker && marker )
289 nameXOffs = marker->x + 20;
290 int ypos = (rect.height() - marker->y) / 2;
291 rc->blit( *marker, ePoint(10, rect.top()+ypos ), eRect(), gPixmap::blitAlphaTest);
293 else if (flags & flagShowNumber && listbox->getColumns() == 1 )
295 int n=-1;
296 if (flags & flagOwnNumber)
297 n=num;
298 else if ( pservice && pservice->dvb )
299 n=pservice->dvb->service_number;
301 if (n != -1)
303 if (!numPara)
305 numPara = new eTextPara( eRect( 0, 0, maxNumSize, rect.height() ) );
306 numPara->setFont( numberFont );
307 numPara->renderString( eString().setNum(n) );
308 numPara->realign(eTextPara::dirRight);
309 numYOffs = ((rect.height() - numPara->getBoundBox().height()) / 2 ) - numPara->getBoundBox().top();
310 nameXOffs = maxNumSize+numPara->getBoundBox().height();
312 rc->renderPara(*numPara, ePoint( rect.left(), rect.top() + numYOffs ) );
316 int newNameXOffs = nameXOffs;
317 if ( pservice && pservice->dvb && pservice->dvb->dxflags & eServiceDVB::dxNewFound && newfound )
319 int ypos = (rect.height() - locked->y) / 2;
320 rc->blit( *newfound, ePoint(rect.left() + nameXOffs, rect.top()+ypos ), eRect(), gPixmap::blitAlphaTest);
321 newNameXOffs += newfound->x+5;
324 if (!namePara)
326 eString sname;
327 if (service.descr.length())
328 sname=service.descr;
329 else if (pservice)
331 int count = 0;
332 switch (service.type)
334 case eServiceReference::idDVB:
335 switch (service.data[0])
337 case -2: // all TV or all Radio Services
338 eTransponderList::getInstance()->forEachServiceReference(eListBoxEntryService_countServices(service.data[1], service.data[2], &count));
339 sname= eString().sprintf("%s (%d)",pservice->service_name.c_str(),count);
340 break;
341 case -5: // all TV or all Radio Services (only services marked as new)
342 eTransponderList::getInstance()->forEachServiceReference(eListBoxEntryService_countServices(service.data[1], service.data[2], &count, true ));
343 sname= eString().sprintf("%s (%d)",pservice->service_name.c_str(),count);
344 break;
345 default:
346 sname=pservice->service_name;
347 break;
349 break;
350 default:
351 sname=pservice->service_name;
352 break;
355 else if (flags & flagIsReturn)
356 sname=_("[GO UP]");
357 else
358 sname=_("(removed service)");
360 namePara = new eTextPara( eRect( 0, 0, rect.width()-newNameXOffs, rect.height() ) );
361 namePara->setFont( serviceFont );
362 namePara->renderString( sname );
363 if (flags & flagIsReturn )
364 namePara->realign(eTextPara::dirCenter);
365 nameYOffs = ((rect.height() - namePara->getBoundBox().height()) / 2 ) - namePara->getBoundBox().top();
367 // we can always render namePara
368 rc->renderPara(*namePara, ePoint( rect.left() + newNameXOffs, rect.top() + nameYOffs ) );
370 if ( service.isLocked() && locked && eConfig::getInstance()->getParentalPin() )
372 int ypos = (rect.height() - locked->y) / 2;
373 rc->blit( *locked, ePoint(newNameXOffs+namePara->getBoundBox().width()+10, rect.top()+ypos ), eRect(), gPixmap::blitAlphaTest);
376 if ( listbox->getColumns() == 1 )
378 if ( !descrPara &&
379 service.type == eServiceReference::idDVB &&
380 (!(service.flags & eServiceReference::isDirectory)) &&
381 (!service.path.size()) ) // recorded dvb streams
383 eString sdescr;
384 if (pservice && service.type == eServiceReference::idDVB && !(service.flags & eServiceReference::isDirectory) )
386 EITEvent *e=eEPGCache::getInstance()->lookupEvent((const eServiceReferenceDVB&)service);
387 if (e)
389 if (eListBoxEntryService::nownextEPG)
391 time_t t = e->start_time+e->duration+1;
392 delete e;
393 e = eEPGCache::getInstance()->lookupEvent((const eServiceReferenceDVB&)service,t);
395 if (e)
397 eString descr;
398 LocalEventData led;
399 led.getLocalData(e, &descr);
400 if (descr.length())
402 if (eListBoxEntryService::nownextEPG)
404 tm *t=localtime(&e->start_time);
405 eString nexttime;
406 nexttime.sprintf("%02d:%02d", t->tm_hour, t->tm_min);
407 sdescr='('+nexttime+' '+descr+')';
409 else
410 sdescr='('+descr+')';
411 curEventId = e->event_id;
412 descrPara = new eTextPara( eRect( 0, 0, rect.width(), rect.height() ) );
413 descrPara->setFont( descrFont );
414 descrPara->renderString( sdescr );
415 descrXOffs = newNameXOffs+namePara->getBoundBox().width();
416 if ( service.isLocked() && locked && eConfig::getInstance()->getParentalPin() )
417 descrXOffs = descrXOffs + locked->x;
418 if (numPara)
419 descrXOffs += numPara->getBoundBox().height();
420 descrYOffs = ((rect.height() - descrPara->getBoundBox().height()) / 2 ) - descrPara->getBoundBox().top();
422 delete e;
427 if (descrPara) // only render descr Para, when avail...
428 rc->renderPara(*descrPara, ePoint( rect.left()+descrXOffs, rect.top() + descrYOffs ) );
431 if (b)
432 drawEntryBorder(rc, rect, coActiveB, coActiveF, coNormalB, coNormalF );
434 if ( pservice )
435 eServiceInterface::getInstance()->removeRef(service);
437 return sort;
440 void eServiceSelector::setKeyDescriptions( bool editMode )
442 if (!(key[0] && key[1] && key[2] && key[3]))
443 return;
445 if ( editMode )
447 key[0]->setText(_("delete"));
448 key[1]->setText(_("mark"));
449 key[2]->setText(_("rename"));
450 key[3]->setText(_("marker"));
451 return;
454 switch (eZapMain::getInstance()->getMode())
456 case eZapMain::modeTV:
457 case eZapMain::modeRadio:
458 key[0]->setText(_("All Services"));
459 if ( eSystemInfo::getInstance()->getFEType() == eSystemInfo::feSatellite )
460 key[1]->setText(_("Satellites"));
461 else
462 key[1]->setText("");
463 key[2]->setText(_("Providers"));
464 key[3]->setText(_("Bouquets"));
465 break;
466 #ifndef DISABLE_FILE
467 case eZapMain::modeFile:
468 key[0]->setText(_("Root"));
469 key[1]->setText(_("Movies"));
470 key[2]->setText(_("Playlist"));
471 key[3]->setText(_("Bouquets"));
472 break;
473 #endif
477 extern bool onSameTP(const eServiceReferenceDVB& ref1, const eServiceReferenceDVB &ref2); // implemented in timer.cpp
479 void eServiceSelector::addService(const eServiceReference &ref)
481 #ifndef DISABLE_FILE
482 if ( eZap::getInstance()->getServiceSelector() == this &&
483 eZapMain::getInstance()->getMode() != eZapMain::modeFile )
485 eServiceReferenceDVB temp;
486 eServiceReferenceDVB &Ref = (eServiceReferenceDVB&) ref;
487 eServiceReferenceDVB &rec =
488 eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift() ? eDVB::getInstance()->recorder->recRef :
489 streaming ? (eServiceReferenceDVB&) streamingRef :
490 temp;
491 if ( rec && !onSameTP(Ref,rec) )
492 return;
494 #endif
495 if (serviceentryflags & eListBoxEntryService::flagSameTransponder)
497 // only add Services on current transponder
498 eServiceReferenceDVB &Ref = (eServiceReferenceDVB&) ref;
499 eServiceReferenceDVB &cur = (eServiceReferenceDVB&) eServiceInterface::getInstance()->service;
501 if ( !onSameTP(Ref,cur) )
502 return;
505 if ( ref.isLocked() && (eConfig::getInstance()->pLockActive() & 2) )
506 return;
508 int flags=serviceentryflags & ~eListBoxEntryService::flagSameTransponder;
510 if ( ref.flags & eServiceReference::isDirectory)
511 flags &= ~ eListBoxEntryService::flagShowNumber;
512 new eListBoxEntryService(services, ref, flags);
515 void eServiceSelector::addBouquet(const eServiceReference &ref)
517 if ( ref.isLocked() && (eConfig::getInstance()->pLockActive() & 2) )
518 return;
519 if ( ref.flags & eServiceReference::canDescent && ref.flags & eServiceReference::isDirectory )
520 new eListBoxEntryService(bouquets, ref, serviceentryflags);
523 struct renumber
525 int &num;
526 bool invalidate;
527 ePlaylist *pl;
528 std::list<ePlaylistEntry>::const_iterator it;
529 renumber(int &num, ePlaylist *pl, bool invalidate=false)
530 :num(num), invalidate(invalidate), pl(pl), it(pl->getConstList().begin())
533 bool operator()(eListBoxEntryService& s)
535 if (!s.service || s.service.flags == eServiceReference::isMarker )
536 return 0;
537 if ( !(s.service.flags & (eServiceReference::isDirectory)) )
539 while ( !(it->service == s.service) )
541 if ( !(it->service.flags & eServiceReference::isMarker) )
542 ++num;
543 ++it;
545 s.num = num;
546 s.invalidate();
548 return 0;
552 void eServiceSelector::fillServiceList(const eServiceReference &_ref)
554 eString windowDescr;
555 eServicePath p = path;
557 eServiceReference ref;
558 streaming = eStreamer::getInstance()->getServiceReference(streamingRef);
560 // build complete path ... for window titlebar..
563 eServiceReference b=p.current();
564 const eService *pservice=eServiceInterface::getInstance()->addRef(b);
565 if (pservice && pservice->service_name.length() )
566 windowDescr=pservice->service_name+" > "+windowDescr;
567 ref = p.current();
568 p.up();
569 eServiceInterface::getInstance()->removeRef(b);
571 while ( ref != p.current() );
572 if (windowDescr.rfind(">") != eString::npos)
573 windowDescr.erase( windowDescr.rfind(">") );
574 setText( windowDescr );
576 ref=_ref;
578 services->beginAtomic();
579 services->clearList();
581 if ( !movemode )
583 if ( path.size() > 1 && style != styleCombiColumn )
585 goUpEntry = new eListBoxEntryService(services, eServiceReference(), eListBoxEntryService::flagIsReturn);
587 else
588 goUpEntry = 0;
591 eServiceInterface *iface=eServiceInterface::getInstance();
592 ASSERT(iface);
594 Signal1<void,const eServiceReference&> signal;
595 CONNECT(signal, eServiceSelector::addService);
597 serviceentryflags=eListBoxEntryService::flagShowNumber;
598 if (ref.data[0] == -6 && eZapMain::getInstance()->getMode() != eZapMain::modeFile)
600 serviceentryflags|=eListBoxEntryService::flagSameTransponder;
602 if ( eZap::getInstance()->getServiceSelector() == this
603 && (eDVB::getInstance()->recorder || ref.data[0] == -6) && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
604 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
606 int mask = eZapMain::getInstance()->getMode() == eZapMain::modeTV ? (1<<4)|(1<<1) : ( 1<<2 );
607 eServiceReference bla(eServiceReference::idDVB,
608 eServiceReference::flagDirectory|eServiceReference::shouldSort,
609 -2, mask, 0xFFFFFFFF );
610 iface->enterDirectory(bla, signal);
611 iface->leaveDirectory(bla);
612 services->sort();
614 else
616 if (ref.type == eServicePlaylistHandler::ID) // playlists have own numbers
617 serviceentryflags|=eListBoxEntryService::flagOwnNumber;
618 iface->enterDirectory(ref, signal);
619 iface->leaveDirectory(ref); // we have a copy.
622 if (ref.flags & eServiceReference::shouldSort)
623 services->sort();
625 if (serviceentryflags & eListBoxEntryService::flagOwnNumber)
627 int num = this == eZap::getInstance()->getServiceSelector() ?
628 getFirstBouquetServiceNum(ref,-1) :
629 getFirstBouquetServiceNum(ref,path.bottom().data[1] == (1<<2) ?
630 eZapMain::modeRadio : path.bottom().data[1] == (1<<1)|(1<<4) ?
631 eZapMain::modeTV : eZapMain::modeFile );
632 ePlaylist *pl = (ePlaylist*) eServiceInterface::getInstance()->addRef( path.top() );
633 if ( pl )
635 services->forEachEntry( renumber(num, pl) );
636 eServiceInterface::getInstance()->removeRef( path.top() );
640 /* // now we calc the x size of the biggest number we have;
641 if (num)
643 eTextPara *tmp = new eTextPara( eRect(0, 0, 100, 50) );
644 tmp->setFont( eListBoxEntryService::numberFont );
645 tmp->renderString( eString().setNum( num ) );
646 eListBoxEntryService::maxNumSize = tmp->getBoundBox().width()+10;
647 tmp->destroy();
649 else */
650 eListBoxEntryService::maxNumSize=45;
652 services->endAtomic();
655 void eServiceSelector::updateNumbers()
657 int num = (this == eZap::getInstance()->getServiceSelector()) ?
658 getFirstBouquetServiceNum(path.top(),-1) :
659 getFirstBouquetServiceNum(path.top(),path.bottom().data[1] == (1<<2) ?
660 eZapMain::modeRadio : path.bottom().data[1] == (1<<1)|(1<<4) ?
661 eZapMain::modeTV : eZapMain::modeFile );
662 services->beginAtomic();
663 ePlaylist *pl = (ePlaylist*) eServiceInterface::getInstance()->addRef( path.top() );
664 if ( pl )
666 services->forEachEntry( renumber(num, pl, true) );
667 eServiceInterface::getInstance()->removeRef( path.top() );
669 services->invalidateContent();
670 services->endAtomic();
673 void eServiceSelector::fillBouquetList( const eServiceReference& _ref)
675 bouquets->beginAtomic();
676 bouquets->clearList();
678 eServiceInterface *iface=eServiceInterface::getInstance();
679 ASSERT(iface);
681 Signal1<void,const eServiceReference&> signal;
682 CONNECT(signal, eServiceSelector::addBouquet );
684 eServiceReference ref=_ref;
686 iface->enterDirectory(ref, signal);
687 iface->leaveDirectory(ref); // we have a copy.
689 if (ref.flags & eServiceReference::shouldSort)
690 bouquets->sort();
692 bouquets->endAtomic();
695 struct moveFirstChar
697 char c;
699 moveFirstChar(char c): c(c)
703 bool operator()(const eListBoxEntryService& s)
705 if (s.sort[0] == c)
707 ( (eListBox<eListBoxEntryService>*) s.listbox)->setCurrent(&s);
708 return 1;
710 return 0;
714 struct moveServiceNum
716 int num;
718 moveServiceNum(int num): num(num)
722 bool operator()(const eListBoxEntryService& s)
724 if (s.num == num)
726 ( (eListBox<eListBoxEntryService>*) s.listbox)->setCurrent(&s);
727 return 1;
729 return 0;
733 bool eServiceSelector::selectService(int num)
735 return services->forEachEntry( moveServiceNum( num ) ) == eListBoxBase::OK;
738 struct findServiceNum
740 int& num;
741 const eServiceReference& service;
743 findServiceNum(const eServiceReference& service, int& num): num(num), service(service)
747 bool operator()(const eListBoxEntryService& s)
749 if (s.service == service)
751 num=s.getNum();
752 return 1;
754 return 0;
758 int eServiceSelector::getServiceNum( const eServiceReference &ref )
760 int ret=-1;
761 services->forEachEntry( findServiceNum(ref, ret ) );
762 return ret;
765 void eServiceSelector::gotoChar(char c)
767 // eDebug("gotoChar %d", c);
768 switch(c)
770 case 2:// A,B,C
771 if (BrowseChar >= 'A' && BrowseChar < 'C')
772 BrowseChar++;
773 else
774 BrowseChar = 'A';
775 break;
777 case 3:// D,E,F
778 if (BrowseChar >= 'D' && BrowseChar < 'F')
779 BrowseChar++;
780 else
781 BrowseChar = 'D';
782 break;
784 case 4:// G,H,I
785 if (BrowseChar >= 'G' && BrowseChar < 'I')
786 BrowseChar++;
787 else
788 BrowseChar = 'G';
789 break;
791 case 5:// J,K,L
792 if (BrowseChar >= 'J' && BrowseChar < 'L')
793 BrowseChar++;
794 else
795 BrowseChar = 'J';
796 break;
798 case 6:// M,N,O
799 if (BrowseChar >= 'M' && BrowseChar < 'O')
800 BrowseChar++;
801 else
802 BrowseChar = 'M';
803 break;
805 case 7:// P,Q,R,S
806 if (BrowseChar >= 'P' && BrowseChar < 'S')
807 BrowseChar++;
808 else
809 BrowseChar = 'P';
810 break;
812 case 8:// T,U,V
813 if (BrowseChar >= 'T' && BrowseChar < 'V')
814 BrowseChar++;
815 else
816 BrowseChar = 'T';
817 break;
819 case 9:// W,X,Y,Z
820 if (BrowseChar >= 'W' && BrowseChar < 'Z')
821 BrowseChar++;
822 else
823 BrowseChar = 'W';
824 break;
826 if (BrowseChar != 0)
828 BrowseTimer.start(5000);
829 services->beginAtomic();
830 services->forEachEntry(moveFirstChar(BrowseChar));
831 services->endAtomic();
835 struct updateEPGChangedService
837 int cnt;
838 eEPGCache* epg;
839 const tmpMap *updatedEntrys;
840 bool redrawOnly;
841 updateEPGChangedService( const tmpMap *u, bool redrawOnly=false ):
842 cnt(0), epg(eEPGCache::getInstance()), updatedEntrys(u), redrawOnly(redrawOnly)
846 bool operator()(eListBoxEntryService& l)
848 if ( l.service.type == eServiceReference::idDVB && !( l.service.flags & eServiceReference::isDirectory) )
850 tmpMap::const_iterator it;
851 if (updatedEntrys)
852 it = updatedEntrys->find( (const eServiceReferenceDVB&)l.service );
853 if ( (updatedEntrys && it != updatedEntrys->end()) ) // entry is updated
855 eventData *e=(eventData*)eEPGCache::getInstance()->lookupEvent((const eServiceReferenceDVB&)l.service, (time_t)0, true );
856 if (e)
858 if ( e->getEventID() != l.curEventId )
860 if ( redrawOnly )
861 ((eListBox<eListBoxEntryService>*) l.listbox)->invalidateEntry(cnt);
862 else
863 l.invalidateDescr();
868 cnt++;
869 return 0;
873 void eServiceSelector::EPGUpdated()
875 eEPGCache *epgcache = eEPGCache::getInstance();
876 epgcache->Lock();
877 tmpMap *tmp = epgcache->getUpdatedMap();
878 services->forEachEntry( updateEPGChangedService( tmp ) );
879 services->forEachVisibleEntry( updateEPGChangedService( tmp, true ) );
880 tmp->clear();
881 epgcache->Unlock();
884 struct invalidateServiceDescr
886 invalidateServiceDescr()
890 bool operator()(eListBoxEntryService& l)
892 l.invalidateDescr();
893 return 0;
896 void eServiceSelector::SwitchNowNext()
898 eListBoxEntryService::nownextEPG = 1-eListBoxEntryService::nownextEPG;
899 services->forEachEntry( invalidateServiceDescr() );
900 services->invalidate();
903 void eServiceSelector::pathUp()
905 if (!movemode)
907 if (path.size() > ( (style == styleCombiColumn) ? focus==bouquets? 2 : 3 : 1) )
909 services->beginAtomic();
910 eServiceReference last=path.current();
911 path.up();
912 actualize();
913 selectService( last );
914 services->endAtomic();
915 } else if ( style == styleCombiColumn && bouquets->isVisible() )
916 setFocus(bouquets);
919 struct moveServicePath
921 eString path;
923 moveServicePath(eString path): path(path)
927 bool operator()(const eListBoxEntryService& s)
929 if (s.service.path == path)
931 ( (eListBox<eListBoxEntryService>*) s.listbox)->setCurrent(&s);
932 return 1;
934 return 0;
938 void eServiceSelector::serviceSelected(eListBoxEntryService *entry)
940 if (entry)
942 if (entry->flags & eListBoxEntryService::flagIsReturn)
944 // dont change path in radio and tv mode when recording is running
945 if ( eZap::getInstance()->getServiceSelector() == this
946 && eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
947 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
948 return;
949 pathUp();
950 return;
952 eServiceReference ref=entry->service;
954 #ifndef DISABLE_FILE
955 #ifdef HAVE_DREAMBOX_HARDWARE
956 if ((ref.type == 0x2000) && (eSystemInfo::getInstance()->getHwType() >= eSystemInfo::DM7000)) // picviewer
957 #else
958 if (ref.type == 0x2000) // picviewer
959 #endif
961 hide();
962 ePictureViewer e(ref.path);
963 #ifndef DISABLE_LCD
964 e.setLCD( LCDTitle, LCDElement );
965 #endif
966 e.show();
967 e.exec();
968 e.hide();
969 eString path = e.GetCurrentFile();
970 services->forEachEntry( moveServicePath( path ) );
971 show();
972 return;
974 #endif
976 if (plockmode)
978 int doit=1;
979 if ( ref.flags & eServiceReference::isDirectory )
981 hide();
982 eMessageBox mb(_("Select No or press Abort to lock/unlock the complete directory"), _("Enter Directory"), eMessageBox::btYes|eMessageBox::btNo|eMessageBox::iconQuestion, eMessageBox::btNo );
983 mb.show();
984 if ( mb.exec() == eMessageBox::btYes )
985 doit=0;
986 mb.hide();
987 show();
989 if ( doit )
991 if ( ref.isLocked() )
992 ref.unlock();
993 else
994 ref.lock();
995 invalidateCurrent();
997 else
998 enterDirectory(ref);
999 return;
1002 if (movemode)
1004 const std::set<eString> &styles =
1005 eActionMapList::getInstance()->getCurrentStyles();
1007 if (eListBoxEntryService::selectedToMove)
1009 eListBoxEntryService *next=services->getNext();
1010 /*emit*/moveEntry(path.current(), ref, next ? next->service : eServiceReference());
1011 services->setMoveMode(0);
1012 eListBoxEntryService::selectedToMove=0;
1013 services->beginAtomic();
1014 actualize();
1015 selectService(ref);
1016 services->endAtomic();
1017 if ( styles.find("sselect_edit") != styles.end() )
1018 eZapMain::getInstance()->toggleMoveMode(this);
1019 return;
1021 else if ( ref )
1023 services->setMoveMode(1);
1024 eListBoxEntryService::selectedToMove=entry;
1025 services->invalidateCurrent();
1026 return;
1030 if (entry->service.flags & eServiceReference::isMarker )
1031 return;
1033 if (ref.flags & eServiceReference::isDirectory)
1034 enterDirectory(ref);
1035 else if (editMode) // edit user bouquet mode
1037 eServiceReference &ref = services->getCurrent()->service;
1038 std::set<eServiceReference>::iterator it = eListBoxEntryService::hilitedEntrys.find( ref );
1039 if ( it == eListBoxEntryService::hilitedEntrys.end() )
1041 /*emit*/ addServiceToUserBouquet(&selected, 1);
1042 eListBoxEntryService::hilitedEntrys.insert(ref);
1044 else
1046 /*emit*/ removeServiceFromUserBouquet( this );
1047 eListBoxEntryService::hilitedEntrys.erase(ref);
1049 services->invalidateCurrent();
1050 return;
1052 else
1054 result=&entry->service;
1055 close(0);
1060 void eServiceSelector::bouquetSelected(eListBoxEntryService*)
1062 if ( services->isVisible() )
1063 setFocus(services);
1066 void eServiceSelector::serviceSelChanged(eListBoxEntryService *entry)
1068 if (entry)
1070 selected = (((eListBoxEntryService*)entry)->service);
1071 ci->clear();
1073 if ( (!(selected.flags & eServiceReference::flagDirectory)) &&
1074 (( selected.type == eServiceReference::idDVB )
1075 #ifndef DISABLE_FILE
1076 || ( selected.type == eServiceReference::idUser &&
1077 ( (selected.data[0] == 0 /*eMP3Decoder::codecMPG*/) ||
1078 (selected.data[0] == 1 /*eMP3Decoder::codecMP3*/) ) )
1079 #endif
1081 ciDelay.start(selected.path.size() ? 100 : 500, true );
1085 void eServiceSelector::updateCi()
1087 if ( isVisible() )
1088 ci->update((const eServiceReferenceDVB&)selected);
1091 void eServiceSelector::forEachServiceRef( Signal1<void,const eServiceReference&> callback, bool fromBeg )
1093 eListBoxEntryService *safe = services->getCurrent(),
1094 *p, *beg;
1095 if ( fromBeg )
1097 services->moveSelection( eListBoxBase::dirFirst );
1098 beg = services->getCurrent();
1100 else
1101 beg = safe;
1102 p = beg;
1105 if (!p)
1106 break;
1107 if ( !(p->flags & eListBoxEntryService::flagIsReturn) )
1108 callback(p->service);
1109 p=services->goNext();
1111 while ( p && p != beg );
1113 if ( fromBeg )
1114 services->setCurrent(safe);
1117 int eServiceSelector::eventHandler(const eWidgetEvent &event)
1119 int num=0;
1120 eServicePath enterPath;
1121 switch (event.type)
1123 case eWidgetEvent::evtAction:
1124 if (event.action == &i_numberActions->key1 && !movemode && !editMode)
1126 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1127 num=1;
1129 else if (event.action == &i_numberActions->key2 && !movemode && !editMode)
1131 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1132 num=2;
1133 else
1134 gotoChar(2);
1136 else if (event.action == &i_numberActions->key3 && !movemode && !editMode)
1138 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1139 num=3;
1140 else
1141 gotoChar(3);
1143 else if (event.action == &i_numberActions->key4 && !movemode && !editMode)
1145 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1146 num=4;
1147 else
1148 gotoChar(4);
1150 else if (event.action == &i_numberActions->key5 && !movemode && !editMode)
1152 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1153 num=5;
1154 else
1155 gotoChar(5);
1157 else if (event.action == &i_numberActions->key6 && !movemode && !editMode)
1159 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1160 num=6;
1161 else
1162 gotoChar(6);
1164 else if (event.action == &i_numberActions->key7 && !movemode && !editMode)
1166 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1167 num=7;
1168 else
1169 gotoChar(7);
1171 else if (event.action == &i_numberActions->key8 && !movemode && !editMode)
1173 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1174 num=8;
1175 else
1176 gotoChar(8);
1178 else if (event.action == &i_numberActions->key9 && !movemode && !editMode)
1180 if ( serviceentryflags&eListBoxEntryService::flagOwnNumber )
1181 num=9;
1182 else
1183 gotoChar(9);
1185 else if (event.action == &i_serviceSelectorActions->prevBouquet && !movemode && path.size() > 1)
1187 // dont change path in radio and tv mode when recording is running
1188 if ( eZap::getInstance()->getServiceSelector() == this
1189 && eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
1190 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1191 return 1;
1192 ci->clear();
1193 services->beginAtomic();
1194 if (style == styleCombiColumn)
1196 if (bouquets->goPrev()->flags & eListBoxEntryService::flagIsReturn)
1197 bouquets->goPrev();
1198 } else
1200 eServiceReference last=path.current();
1201 path.up();
1202 fillServiceList(path.current());
1203 selectService( last );
1204 eListBoxEntryService* p=0;
1206 p = services->goPrev();
1207 while ( p && ( p->flags&eListBoxEntryService::flagIsReturn ||
1208 ( p->service != last &&
1209 !(p->service.flags & eServiceReference::canDescent) &&
1210 !(p->service.flags & eServiceReference::isDirectory))));
1211 if (p)
1213 path.down( p->service );
1214 fillServiceList( p->service );
1215 if (!selectService( eServiceInterface::getInstance()->service ))
1216 next();
1219 services->endAtomic();
1221 else if (event.action == &i_serviceSelectorActions->nextBouquet && !movemode && path.size()>1 )
1223 // dont change path in radio and tv mode when recording is running
1224 if ( eZap::getInstance()->getServiceSelector() == this
1225 && eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
1226 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1227 return 1;
1228 ci->clear();
1229 services->beginAtomic();
1230 if (style == styleCombiColumn)
1232 if (bouquets->goNext()->flags & eListBoxEntryService::flagIsReturn)
1233 bouquets->goNext();
1234 } else
1236 eServiceReference last=path.current();
1237 path.up();
1238 fillServiceList(path.current());
1239 selectService( last );
1240 eListBoxEntryService* p=0;
1242 p = services->goNext();
1243 while ( p && ( p->flags&eListBoxEntryService::flagIsReturn ||
1244 ( p->service != last &&
1245 !(p->service.flags & eServiceReference::canDescent) &&
1246 !(p->service.flags & eServiceReference::isDirectory))));
1247 if (p)
1249 path.down( p->service );
1250 fillServiceList( p->service );
1251 if (!selectService( eServiceInterface::getInstance()->service ))
1252 next();
1255 services->endAtomic();
1257 else if (event.action == &i_serviceSelectorActions->showEPGSelector
1258 && !movemode && !editMode && this == eZap::getInstance()->getServiceSelector() )
1260 hide();
1261 #ifndef DISABLE_FILE
1262 #ifdef HAVE_DREAMBOX_HARDWARE
1263 if ((selected.type == 0x2000) && (eSystemInfo::getInstance()->getHwType() >= eSystemInfo::DM7000)) // Picture
1264 #else
1265 if (selected.type == 0x2000) // Picture
1266 #endif
1268 ePicViewerSettings f;
1269 #ifndef DISABLE_LCD
1270 f.setLCD( LCDTitle, LCDElement );
1271 #endif
1272 f.show();
1273 f.exec();
1274 f.hide();
1276 show();
1278 else
1279 #endif
1281 eEPGStyleSelector e(1);
1282 #ifndef DISABLE_LCD
1283 e.setLCD( LCDTitle, LCDElement );
1284 #endif
1285 e.show();
1286 int ret = e.exec();
1287 e.hide();
1288 switch ( ret )
1290 case 1:
1291 /*emit*/ showEPGList((eServiceReferenceDVB&)selected);
1292 show();
1293 break;
1294 case 2:
1295 showMultiEPG();
1296 break;
1297 default:
1298 show();
1299 break;
1303 else if (event.action == &i_serviceSelectorActions->pathUp)
1305 // dont change path in radio and tv mode when recording is running
1306 if ( eZap::getInstance()->getServiceSelector() == this
1307 && eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
1308 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1309 return 1;
1310 pathUp();
1312 else if (event.action == &i_serviceSelectorActions->toggleStyle && !movemode && !editMode)
1314 int newStyle = lastSelectedStyle;
1315 if (newStyle == styleMultiColumn)
1316 newStyle = styleCombiColumn;
1317 else
1318 newStyle++;
1319 setStyle(lastSelectedStyle=newStyle);
1321 else if (event.action == &i_serviceSelectorActions->toggleFocus && !movemode && path.size() > 1)
1323 if ( style == styleCombiColumn )
1324 if (focus == services)
1325 setFocus( bouquets );
1326 else
1327 setFocus( services );
1328 if ( style == styleSingleColumn )
1329 SwitchNowNext();
1331 else if (event.action == &i_serviceSelectorActions->showMenu && focus != bouquets && !plockmode )
1333 hide();
1334 /*emit*/ showMenu(this);
1335 show();
1337 else if (event.action == &i_serviceSelectorActions->addService && !movemode && !editMode)
1338 /*emit*/ addServiceToPlaylist(selected);
1339 else if (event.action == &i_serviceSelectorActions->addServiceToUserBouquet && !movemode && !editMode)
1341 hide();
1342 /*emit*/ addServiceToUserBouquet(&selected, 0);
1343 show();
1345 else if (event.action == &i_serviceSelectorActions->modeTV && !movemode && !editMode)
1347 if ( this == eZap::getInstance()->getServiceSelector() )
1348 /*emit*/ setMode(eZapMain::modeTV);
1349 else
1351 setPath(eServiceReference(eServiceReference::idDVB,
1352 eServiceReference::flagDirectory|eServiceReference::shouldSort,
1353 -2, (1<<4)|(1<<1), 0xFFFFFFFF ));
1356 else if (event.action == &i_serviceSelectorActions->modeRadio && !movemode && !editMode)
1358 if ( this == eZap::getInstance()->getServiceSelector() )
1359 /*emit*/ setMode(eZapMain::modeRadio);
1360 else
1362 setPath(eServiceReference(eServiceReference::idDVB,
1363 eServiceReference::flagDirectory|eServiceReference::shouldSort,
1364 -2, 1<<2, 0xFFFFFFFF ));
1367 #ifndef DISABLE_FILE
1368 else if (event.action == &i_serviceSelectorActions->modeFile && !movemode && !editMode)
1369 /*emit*/ setMode(eZapMain::modeFile);
1370 #endif
1371 else if (event.action == &i_serviceSelectorActions->gotoPrevMarker)
1373 ePlaylist *p = 0;
1374 if ( path.current().type == eServicePlaylistHandler::ID )
1375 p = (ePlaylist*) eServicePlaylistHandler::getInstance()->addRef(path.current());
1376 if ( p )
1378 std::list<ePlaylistEntry>::const_iterator it =
1379 std::find( p->getConstList().begin(), p->getConstList().end(), selected );
1380 if ( it != p->getConstList().end() )
1382 for (--it ; it != p->getConstList().end(); --it )
1383 if ( it->service.flags & eServiceReference::isMarker )
1385 selectService( it->service );
1386 break;
1389 if ( it == p->getConstList().end() )
1390 services->moveSelection(services->dirFirst);
1392 else
1393 services->moveSelection(services->dirFirst);
1395 else if (event.action == &i_serviceSelectorActions->gotoNextMarker)
1397 ePlaylist *p = 0;
1398 if ( path.current().type == eServicePlaylistHandler::ID )
1399 p = (ePlaylist*) eServicePlaylistHandler::getInstance()->addRef(path.current());
1400 if ( p )
1402 std::list<ePlaylistEntry>::const_iterator it;
1403 eListBoxEntryService *cur = services->getCurrent();
1404 if ( cur && cur->flags & eListBoxEntryService::flagIsReturn )
1405 it = p->getConstList().begin();
1406 else
1407 it = std::find( p->getConstList().begin(), p->getConstList().end(), selected );
1408 if ( it != p->getConstList().end() )
1410 for ( ++it ; it != p->getConstList().end(); ++it )
1411 if ( it->service.flags & eServiceReference::isMarker )
1413 selectService( it->service );
1414 break;
1417 if ( it == p->getConstList().end() )
1418 services->moveSelection(services->dirLast);
1420 else
1421 services->moveSelection(services->dirLast);
1423 else if (event.action == &i_serviceSelectorActions->showAll && !movemode)
1425 if ( this == eZap::getInstance()->getServiceSelector() )
1426 enterPath = /*emit*/ getRoot(listAll, -1);
1427 else
1428 enterPath = /*emit*/ getRoot(listAll, path.bottom().data[1] == (1<<2) ? eZapMain::modeRadio :
1429 path.bottom().data[1] == (1<<1)|(1<<4) ? eZapMain::modeTV : eZapMain::modeFile );
1430 if ( style == styleCombiColumn && eZapMain::getInstance()->getMode() == eZapMain::modeFile )
1431 enterPath.down(eServiceReference());
1433 else if (event.action == &i_serviceSelectorActions->showSatellites && !movemode)
1435 if ( this == eZap::getInstance()->getServiceSelector() )
1436 enterPath = /*emit*/ getRoot(listSatellites,-1);
1437 else
1438 enterPath = /*emit*/ getRoot(listSatellites, path.bottom().data[1] == (1<<2) ? eZapMain::modeRadio :
1439 path.bottom().data[1] == (1<<1)|(1<<4) ? eZapMain::modeTV : eZapMain::modeFile );
1441 // On Cable and Terrestrial Boxes dont handle green button.. expect in file mode..
1442 if ( eSystemInfo::getInstance()->getFEType() != eSystemInfo::feSatellite && enterPath.size() &&
1443 enterPath.bottom().data[0] == -4 ) // Satellite list..
1444 enterPath=eServicePath(); // clear enterPath
1446 if ( style == styleCombiColumn && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1447 enterPath.down(eServiceReference());
1449 else if (event.action == &i_serviceSelectorActions->showProvider && !movemode)
1451 if ( this == eZap::getInstance()->getServiceSelector() )
1452 enterPath = /*emit*/ getRoot(listProvider,-1);
1453 else
1454 enterPath = /*emit*/ getRoot(listProvider, path.bottom().data[1] == (1<<2) ? eZapMain::modeRadio :
1455 path.bottom().data[1] == (1<<1)|(1<<4) ? eZapMain::modeTV : eZapMain::modeFile );
1456 if ( style == styleCombiColumn && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1457 enterPath.down(eServiceReference());
1459 else if (event.action == &i_serviceSelectorActions->showBouquets && !movemode)
1461 if ( this == eZap::getInstance()->getServiceSelector() )
1462 enterPath = /*emit*/ getRoot(listBouquets,-1);
1463 else
1464 enterPath = /*emit*/ getRoot(listBouquets, path.bottom().data[1] == (1<<2) ? eZapMain::modeRadio :
1465 path.bottom().data[1] == (1<<1)|(1<<4) ? eZapMain::modeTV : eZapMain::modeFile );
1466 if ( style == styleCombiColumn )
1467 enterPath.down(eServiceReference());
1469 else if (event.action == &i_cursorActions->cancel)
1471 if (movemode)
1472 eZapMain::getInstance()->toggleMoveMode(this);
1473 if (editMode)
1474 eZapMain::getInstance()->toggleEditMode(this);
1475 break;
1477 else if ( event.action == &i_serviceSelectorActions->markPressed )
1479 if ( services->getCurrent() && !(services->getCurrent()->flags & eListBoxEntryService::flagIsReturn) )
1481 if (path.current().type == eServicePlaylistHandler::ID)
1483 if ( movemode )
1484 serviceSelected( services->getCurrent() );
1485 else
1487 eZapMain::getInstance()->toggleMoveMode(this);
1488 serviceSelected( services->getCurrent() );
1493 else if ( event.action == &i_serviceSelectorActions->deletePressed )
1494 /*emit*/ deletePressed( this );
1495 else if ( event.action == &i_serviceSelectorActions->renamePressed )
1497 hide();
1498 if ( selected.type == eServicePlaylistHandler::ID )
1499 /*emit*/ renameBouquet( this );
1500 else
1501 /*emit*/ renameService( this );
1502 show();
1504 else if ( event.action == &i_serviceSelectorActions->insertPressed )
1506 if ( path.current().type == eServicePlaylistHandler::ID )
1507 /*emit*/ newMarkerPressed( this );
1508 else if ( selected.flags & eServiceReference::flagDirectory )
1510 if ( selected.type == eServiceReference::idDVB
1511 && (selected.data[0] == -2 || selected.data[0] == -3) )
1512 /*emit*/ copyToBouquetList(this);
1514 else if ( selected.type == eServiceReference::idDVB
1515 #ifndef DISABLE_FILE
1516 || ( selected.type == eServiceReference::idUser
1517 && ( (selected.data[0] == eMP3Decoder::codecMPG)
1518 || (selected.data[0] == eMP3Decoder::codecMP3) ) ) )
1519 #else
1521 #endif
1523 hide();
1524 /*emit*/ addServiceToUserBouquet(&selected, 0);
1525 show();
1528 else
1529 break;
1530 if (enterPath.size())
1532 // dont change path in radio and tv mode when recording is running
1533 if ( eZap::getInstance()->getServiceSelector() == this
1534 && eDVB::getInstance()->recorder && !eZapMain::getInstance()->isRecordingPermanentTimeshift()
1535 && eZapMain::getInstance()->getMode() != eZapMain::modeFile )
1536 return 1;
1537 ci->clear();
1538 if ( path.bottom() == enterPath.bottom() )
1539 pathUp();
1540 else
1541 setPath(enterPath);
1543 else if (num)
1545 hide();
1546 eServiceNumberWidget s(num);
1547 s.show();
1548 num = s.exec();
1549 s.hide();
1550 if (num != -1)
1552 if (selectService( num ))
1554 result=&services->getCurrent()->service;
1555 close(0);
1557 else
1558 show();
1560 else
1561 show();
1563 return 1;
1564 default:
1565 break;
1567 return eWindow::eventHandler(event);
1570 struct _selectService
1572 eServiceReference service;
1574 _selectService(const eServiceReference& e): service(e)
1578 bool operator()(const eListBoxEntryService& s)
1580 if (service == s.service)
1582 ((eListBox<eListBoxEntryService>*) s.listbox)->setCurrent(&s);
1583 return 1;
1585 return 0;
1589 #if 0
1590 struct copyEntry
1592 std::list<eServiceReference> &dest;
1594 copyEntry(std::list<eServiceReference> &dest)
1595 :dest(dest)
1599 bool operator()(const eListBoxEntryService& s)
1601 dest.push_back(s.service);
1602 return 0;
1606 bool eServiceSelector::selectServiceRecursive( eServiceReference &ref )
1608 services->beginAtomic();
1609 bool b = selServiceRec( ref );
1610 services->endAtomic();
1611 return b;
1614 bool eServiceSelector::selServiceRec( eServiceReference &ref )
1616 std::list<eServiceReference> tmp;
1618 // copy all entrys to temp list
1619 services->forEachEntry( copyEntry( tmp ) );
1621 for ( std::list<eServiceReference>::iterator it( tmp.begin() ); it != tmp.end(); it++ )
1623 if ( it->flags & eServiceReference::isDirectory )
1625 path.down(*it);
1626 actualize();
1627 if ( selServiceRec( ref ) )
1628 return true;
1629 else
1631 path.up();
1632 actualize();
1635 else if ( selectService(ref) )
1636 return true;
1638 return false;
1640 #endif
1642 bool eServiceSelector::selectService(const eServiceReference &ref)
1644 if ( services->forEachEntry( _selectService(ref) ) )
1646 // services->moveSelection( eListBox<eListBoxEntryService>::dirFirst );
1647 // ersten service NICHT selecten (warum auch - evtl. ist ja der aktuelle sinnvoller,
1648 // und bei einem entsprechenden returncode kann ja jeder sehen was er will)
1649 return false;
1651 else
1652 return true;
1655 void eServiceSelector::setStyle(int newStyle, bool force)
1657 eServicePath p = path;
1658 eServiceReference currentService;
1659 if (style != newStyle || force )
1661 ci->hide();
1662 if ( services )
1664 // save currentSelected Service
1665 if ( services->getCount() )
1666 currentService = services->getCurrent()->service;
1668 services->hide();
1669 delete services;
1671 if ( bouquets )
1673 bouquets->hide();
1674 delete bouquets;
1677 if (key[0])
1678 delete key[0];
1679 if (key[1])
1680 delete key[1];
1681 if (key[2])
1682 delete key[2];
1683 if (key[3])
1684 delete key[3];
1686 if (newStyle == styleSingleColumn)
1688 eListBoxEntryService::folder = eSkin::getActive()->queryImage("sselect_folder");
1689 eListBoxEntryService::marker = eSkin::getActive()->queryImage("sselect_marker");
1690 eListBoxEntryService::locked = eSkin::getActive()->queryImage("sselect_locked");
1691 eListBoxEntryService::newfound = eSkin::getActive()->queryImage("sselect_newfound");
1692 eListBoxEntryService::numberFont = eSkin::getActive()->queryFont("eServiceSelector.singleColumn.Entry.Number");
1693 eListBoxEntryService::serviceFont = eSkin::getActive()->queryFont("eServiceSelector.singleColumn.Entry.Name");
1694 i_serviceSelectorActions->toggleFocus.setDescription(_("toggle between now and next epg entries in single column list"));
1696 else if (newStyle == styleMultiColumn)
1698 eListBoxEntryService::folder = 0;
1699 eListBoxEntryService::marker = eSkin::getActive()->queryImage("sselect_marker_small");
1700 eListBoxEntryService::locked = eSkin::getActive()->queryImage("sselect_locked_small");
1701 eListBoxEntryService::newfound = eSkin::getActive()->queryImage("sselect_newfound_small");
1702 eListBoxEntryService::numberFont = eSkin::getActive()->queryFont("eServiceSelector.multiColumn.Entry.Number");
1703 eListBoxEntryService::serviceFont = eSkin::getActive()->queryFont("eServiceSelector.multiColumn.Entry.Name");
1704 i_serviceSelectorActions->toggleFocus.setDescription(_("toggle focus between service and bouquet list (in combi column style)"));
1706 else
1708 eListBoxEntryService::folder = 0;
1709 eListBoxEntryService::marker = eSkin::getActive()->queryImage("sselect_marker_small");
1710 eListBoxEntryService::locked = eSkin::getActive()->queryImage("sselect_locked_small");
1711 eListBoxEntryService::newfound = eSkin::getActive()->queryImage("sselect_newfound_small");
1712 eListBoxEntryService::numberFont = eSkin::getActive()->queryFont("eServiceSelector.combiColumn.Entry.Number");
1713 eListBoxEntryService::serviceFont = eSkin::getActive()->queryFont("eServiceSelector.combiColumn.Entry.Name");
1714 i_serviceSelectorActions->toggleFocus.setDescription(_("toggle focus between service and bouquet list (in combi column style)"));
1716 services = new eListBoxExt<eListBoxEntryService>(this);
1717 services->setName("services");
1718 services->setActiveColor(eSkin::getActive()->queryScheme("eServiceSelector.highlight.background"), eSkin::getActive()->queryScheme("eServiceSelector.highlight.foreground"));
1719 services->hide();
1721 bouquets = new eListBoxExt<eListBoxEntryService>(this);
1722 bouquets->setName("bouquets");
1723 bouquets->setActiveColor(eSkin::getActive()->queryScheme("eServiceSelector.highlight.background"), eSkin::getActive()->queryScheme("eServiceSelector.highlight.foreground"));
1724 bouquets->hide();
1726 eString styleName="eServiceSelector_";
1727 if ( newStyle == styleSingleColumn )
1728 styleName+="singleColumn";
1729 else if ( newStyle == styleMultiColumn )
1730 styleName+="multiColumn";
1731 else
1733 styleName+="combiColumn";
1734 CONNECT( bouquets->selchanged, eServiceSelector::bouquetSelChanged );
1735 CONNECT( bouquets->selected, eServiceSelector::bouquetSelected );
1736 bouquets->show();
1738 int showButtons=0;
1739 eConfig::getInstance()->getKey("/ezap/serviceselector/showButtons", showButtons );
1740 if ( showButtons )
1742 styleName+="_buttons";
1743 key[0] = new eLabel(this);
1744 key[0]->setName("key_red");
1745 key[1] = new eLabel(this);
1746 key[1]->setName("key_green");
1747 key[2] = new eLabel(this);
1748 key[2]->setName("key_yellow");
1749 key[3] = new eLabel(this);
1750 key[3]->setName("key_blue");
1751 for (int i=0; i < 4; i++)
1752 key[i]->show();
1754 else
1755 key[0] = key[1] = key[2] = key[3] = 0;
1757 if (eSkin::getActive()->build(this, styleName.c_str()))
1758 eFatal("Service selector widget \"%s\" build failed!",styleName.c_str());
1760 style = newStyle;
1761 CONNECT(services->selected, eServiceSelector::serviceSelected);
1762 CONNECT(services->selchanged, eServiceSelector::serviceSelChanged);
1763 actualize();
1764 selectService( currentService ); // select the old service
1765 services->show();
1766 if ( services->isVisible() )
1767 setFocus(services);
1768 setKeyDescriptions();
1770 ci->show();
1773 void eServiceSelector::bouquetSelChanged( eListBoxEntryService *entry)
1775 if ( entry && entry->service )
1777 ci->clear();
1778 services->beginAtomic();
1779 path.up();
1780 path.down(entry->service);
1781 fillServiceList( entry->service );
1782 if (!selectService( eServiceInterface::getInstance()->service ))
1783 services->moveSelection( eListBox<eListBoxEntryService>::dirFirst );
1784 services->endAtomic();
1788 void eServiceSelector::actualize()
1790 if ( movemode & 2 )
1791 return;
1792 if (style == styleCombiColumn)
1794 bouquets->beginAtomic();
1795 if ( path.size() > 1 )
1797 eServiceReference currentBouquet = path.current();
1798 path.up();
1799 eServiceReference allBouquets = path.current();
1800 path.down( currentBouquet );
1801 fillBouquetList( allBouquets );
1803 if ( bouquets->forEachEntry( _selectService( currentBouquet ) ) )
1804 bouquets->moveSelection( eListBox<eListBoxEntryService>::dirFirst );
1806 else
1808 bouquets->clearList();
1809 fillServiceList(path.current());
1811 bouquets->endAtomic();
1813 else
1814 fillServiceList(path.current());
1817 eServiceSelector::eServiceSelector()
1818 :eWindow(0), result(0), services(0), bouquets(0)
1819 ,style(styleInvalid), lastSelectedStyle(styleSingleColumn)
1820 ,BrowseChar(0), BrowseTimer(eApp), ciDelay(eApp), movemode(0)
1821 ,editMode(0), plockmode(0)
1823 init_eServiceSelector();
1826 void eServiceSelector::init_eServiceSelector()
1828 ci = new eChannelInfo(this);
1829 ci->setName("channelinfo");
1831 CONNECT(eDVB::getInstance()->bouquetListChanged, eServiceSelector::actualize);
1832 CONNECT(BrowseTimer.timeout, eServiceSelector::ResetBrowseChar);
1833 CONNECT(ciDelay.timeout, eServiceSelector::updateCi );
1835 addActionMap(&i_serviceSelectorActions->map);
1836 addActionMap(&i_numberActions->map);
1838 setHelpID(33);
1839 if ( !eZap::getInstance()->getServiceSelector() )
1841 addActionToHelpList(&i_serviceSelectorActions->deletePressed);
1842 addActionToHelpList(&i_serviceSelectorActions->markPressed);
1843 addActionToHelpList(&i_serviceSelectorActions->renamePressed);
1844 addActionToHelpList(&i_serviceSelectorActions->insertPressed);
1846 addActionToHelpList(&i_serviceSelectorActions->showAll);
1847 if ( eSystemInfo::getInstance()->getFEType() == eSystemInfo::feSatellite )
1848 addActionToHelpList(&i_serviceSelectorActions->showSatellites);
1849 addActionToHelpList(&i_serviceSelectorActions->showProvider);
1850 addActionToHelpList(&i_serviceSelectorActions->showBouquets);
1851 if ( !eZap::getInstance()->getServiceSelector() )
1852 addActionToHelpList(&i_serviceSelectorActions->showMenu);
1853 addActionToHelpList(&i_serviceSelectorActions->toggleStyle);
1854 addActionToHelpList(&i_serviceSelectorActions->toggleFocus);
1855 addActionToHelpList(&i_serviceSelectorActions->gotoPrevMarker);
1856 addActionToHelpList(&i_serviceSelectorActions->gotoNextMarker);
1857 if ( !eZap::getInstance()->getServiceSelector() )
1858 addActionToHelpList(&i_serviceSelectorActions->showEPGSelector);
1859 addActionToHelpList(&i_serviceSelectorActions->pathUp);
1860 addActionToHelpList(&i_serviceSelectorActions->modeTV);
1861 addActionToHelpList(&i_serviceSelectorActions->modeRadio);
1862 #ifndef DISABLE_FILE
1863 if ( !eZap::getInstance()->getServiceSelector() )
1864 addActionToHelpList(&i_serviceSelectorActions->modeFile);
1865 #endif
1867 key[0] = key[1] = key[2] = key[3] = 0;
1869 CONNECT(eDVB::getInstance()->serviceListChanged, eServiceSelector::actualize );
1870 eActionMapList::getInstance()->activateStyle("sselect_default");
1873 eServiceSelector::~eServiceSelector()
1877 void eServiceSelector::enterDirectory(const eServiceReference &ref)
1879 path.down(ref);
1880 setPath(path);
1883 void eServiceSelector::showMultiEPG()
1885 eZapEPG epg;
1887 int direction = 2;
1888 epg.show();
1891 epg.buildPage(direction);
1892 direction = epg.exec();
1894 while ( direction > 0 );
1895 epg.hide();
1896 if ( !direction ) // switch to service requested...
1898 selectService( epg.getCurSelected()->service );
1899 result=&selected;
1900 close(0);
1902 else
1903 show();
1906 void eServiceSelector::ResetBrowseChar()
1908 BrowseChar=0;
1911 const eServiceReference *eServiceSelector::choose(int irc)
1913 ASSERT(this);
1914 services->beginAtomic();
1915 result=0;
1917 switch (irc)
1919 case dirUp:
1920 services->moveSelection(eListBox<eListBoxEntryService>::dirUp);
1921 break;
1922 case dirDown:
1923 services->moveSelection(eListBox<eListBoxEntryService>::dirDown);
1924 break;
1925 case dirFirst:
1926 services->moveSelection(eListBox<eListBoxEntryService>::dirFirst);
1927 break;
1928 case dirLast:
1929 services->moveSelection(eListBox<eListBoxEntryService>::dirLast);
1930 break;
1931 default:
1932 break;
1934 services->endAtomic();
1936 if ( !services->getCount() )
1937 ci->clear();
1939 show();
1941 if (exec())
1942 result=0;
1944 hide();
1945 return result;
1948 const eServiceReference *eServiceSelector::next()
1950 services->beginAtomic();
1951 selectService(eServiceInterface::getInstance()->service);
1953 eListBoxEntryService *s=0, *cur=services->getCurrent();
1955 s=services->goNext();
1956 while ( s != cur && s &&
1957 ( s->flags & eListBoxEntryService::flagIsReturn ||
1958 s->service.flags == eServiceReference::isMarker ||
1959 s->service.flags & eServiceReference::isNotPlayable ) );
1961 services->endAtomic();
1962 if (s)
1963 return &s->service;
1964 else
1965 return 0;
1968 const eServiceReference *eServiceSelector::prev()
1970 services->beginAtomic();
1971 selectService(eServiceInterface::getInstance()->service);
1972 eListBoxEntryService *s=0, *cur=services->getCurrent();
1974 s=services->goPrev();
1975 while ( s != cur && s &&
1976 ( s->flags & eListBoxEntryService::flagIsReturn ||
1977 s->service.flags & eServiceReference::isMarker ||
1978 s->service.flags & eServiceReference::isNotPlayable ) );
1980 services->endAtomic();
1981 if (s)
1982 return &s->service;
1983 else
1984 return 0;
1987 void eServiceSelector::setPath(const eServicePath &newpath, const eServiceReference &select)
1989 path=newpath;
1990 if (services)
1992 bool ret=false;
1993 services->beginAtomic();
1994 actualize();
1995 if (select)
1996 ret=selectService(select);
1997 else
1999 eServiceReference &sref = eServiceInterface::getInstance()->service;
2000 if (!(ret=selectService(sref)))
2002 if ( sref.type == eServiceReference::idDVB && !sref.path )
2004 eServiceReferenceDVB &dvb_ref = (eServiceReferenceDVB&) sref;
2005 eString tmp;
2006 tmp.sprintf("1:15:fffffffe:12:%x:0:0:0:0:0:", dvb_ref.getDVBNamespace().get());
2007 eServiceReference sat_ref(tmp);
2008 if (!(ret=selectService(sat_ref)))
2010 eServiceDVB *service = eTransponderList::getInstance()->searchService(sref);
2011 if ( service )
2013 eBouquet *b = eDVB::getInstance()->settings->getBouquet(eString(service->service_provider).upper());
2014 if (b)
2016 tmp.sprintf("1:15:fffffffd:12:%x:%x:0:0:0:0:", b->bouquet_id, dvb_ref.getDVBNamespace().get() );
2017 eServiceReference bref(tmp);
2018 if (!(ret=selectService(bref)))
2020 tmp.sprintf("1:15:fffffffd:12:%x:ffffffff:0:0:0:0:", b->bouquet_id, dvb_ref.getDVBNamespace().get() );
2021 eServiceReference bref(tmp);
2022 ret=selectService(bref);
2031 if (!ret)
2032 services->moveSelection( eListBox<eListBoxEntryService>::dirFirst );
2034 // we have a problem when selection not changes..
2035 // the listbox don't emit "selected"... then our current
2036 // selected entry is not valid.. to prevent this we set
2037 // it manual...
2038 eListBoxEntryService *cur = services->getCurrent();
2039 if ( cur )
2040 selected = cur->service;
2041 else
2042 selected = eServiceReference();
2044 services->endAtomic();
2048 void eServiceSelector::removeCurrent(bool selNext)
2050 eListBoxEntryService *cur = services->getCurrent();
2051 if ( !cur )
2052 return;
2053 services->beginAtomic();
2054 if ( selNext )
2055 services->goNext();
2056 else
2057 services->goPrev();
2058 services->remove( cur, true );
2059 services->endAtomic();
2062 void eServiceSelector::invalidateCurrent( eServiceReference ref )
2064 eListBoxEntryService *cur = services->getCurrent();
2065 if ( !cur )
2066 return;
2067 if ( ref )
2068 cur->service = ref;
2069 cur->invalidate();
2070 services->invalidateCurrent();
2073 int eServiceSelector::toggleMoveMode()
2075 if ( editMode ) // don't editmode and movemode at the same time..
2076 eZapMain::getInstance()->toggleEditMode(this);
2078 services->beginAtomic();
2079 movemode^=1;
2080 if (!movemode)
2082 eListBoxEntryService::selectedToMove=0;
2083 services->setMoveMode(0);
2084 if ( goUpEntry )
2085 services->append( goUpEntry, true, true );
2087 else if ( goUpEntry )
2088 services->take(goUpEntry, true);
2090 services->endAtomic();
2091 return movemode;
2094 int eServiceSelector::toggleEditMode()
2096 if ( movemode ) // don't editmode and movemode at the same time..
2097 eZapMain::getInstance()->toggleMoveMode(this);
2098 editMode^=1;
2099 return editMode;