summaryrefslogtreecommitdiff
path: root/vdr_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'vdr_menu.c')
-rw-r--r--vdr_menu.c442
1 files changed, 246 insertions, 196 deletions
diff --git a/vdr_menu.c b/vdr_menu.c
index b683e0b..015b22d 100644
--- a/vdr_menu.c
+++ b/vdr_menu.c
@@ -26,17 +26,15 @@
#include <skins.h>
#endif
-#include "vdr_setup.h"
+#include "mg_setup.h"
#include "vdr_menu.h"
#include "vdr_player.h"
-
#include "mg_incremental_search.h"
-#include "mg_selection.h"
-
+#include "mg_thread_sync.h"
#include "i18n.h"
-#define DEBUG
#include "mg_tools.h"
+#include "mg_sel_gd.h"
void
mgStatus::OsdCurrentItem(const char* Text)
@@ -50,9 +48,13 @@ mgStatus::OsdCurrentItem(const char* Text)
a->TryNotify();
}
-void Play(mgSelection *sel,const bool select) {
- mgSelection *s = new mgSelection(sel);
- if (select) s->select();
+void Play(mgSelection *sel, bool enter)
+{
+ mgSelection *s = GenerateSelection(sel);
+ if (s->ordersize()==0)
+ s->InitDefaultOrder(1);
+ if (enter)
+ s->enter();
s->skipItems(0); // make sure we start with a valid item
if (s->empty()) // no valid item exists
{
@@ -66,6 +68,11 @@ void Play(mgSelection *sel,const bool select) {
cControl::Launch (new mgPlayerControl (s));
}
+mgSelection*
+GenerateSelection(const mgSelection* s)
+{
+ return new mgSelectionGd(s);
+}
//! \brief queue the selection for playing, abort ongoing instant play
void
@@ -78,35 +85,52 @@ mgMainMenu::PlayQueue()
//! \brief queue the selection for playing, abort ongoing queue playing
void
-mgMainMenu::PlayInstant(const bool select)
+mgMainMenu::PlayInstant(bool enter)
{
instant_playing=true;
- Play(selection(),select);
+ Play(selection(),enter);
}
-void
-mgMainMenu::setOrder(mgSelection *sel,unsigned int idx)
+bool
+mgMainMenu::SwitchSelection()
{
- mgOrder* o = getOrder(idx);
- if (o->size()>0)
+ UseNormalSelection();
+ mgSelection* newsel = getSelection(Current());
+ if (newsel->ordersize()>0)
{
- m_current_order = idx;
- sel->setOrder(o);
+ newsel->CopyKeyValues(selection());
+ newsel->Activate();
+ m_current_selection = Current();
+ newposition = selection()->getPosition();
+ SaveState();
+ return true;
}
else
- mgWarning("mgMainMenu::setOrder: orders[%u] is empty",idx);
+ {
+ Message1(tr("Order is undefined"),"");
+ return false;
+ }
+}
+
+void mgMainMenu::setSelection(unsigned int idx,mgSelection *s)
+{
+ if (idx>=selections.size())
+ mgError("mgMainMenu::getSelection(%u): selections.size() is %d",
+ idx,selections.size());
+ delete selections[idx];
+ selections[idx] = s;
}
-mgOrder* mgMainMenu::getOrder(unsigned int idx)
+mgSelection* mgMainMenu::getSelection(unsigned int idx)
{
- if (idx>=orders.size())
- mgError("mgMainMenu::getOrder(%u): orders.size() is %d",
- idx,orders.size());
- return orders[idx];
+ if (idx>=selections.size())
+ mgError("mgMainMenu::getSelection(%u): selections.size() is %d",
+ idx,selections.size());
+ return selections[idx];
}
void
-mgMainMenu::CollectionChanged(string name)
+mgMainMenu::CollectionChanged(string name,bool added)
{
delete moveselection;
moveselection = NULL;
@@ -117,7 +141,7 @@ mgMainMenu::CollectionChanged(string name)
mgPlayerControl *c = PlayerControl();
if (c)
c->ReloadPlaylist();
- else
+ else if (added)
PlayQueue();
}
if (CollectionEntered(name) || selection()->isCollectionlist())
@@ -127,7 +151,7 @@ mgMainMenu::CollectionChanged(string name)
bool
mgMainMenu::ShowingCollections()
{
- return (UsingCollection && selection ()->level () == 0);
+ return (UsingCollection && selection ()->orderlevel () == 0);
}
@@ -142,8 +166,8 @@ bool
mgMainMenu::CollectionEntered(string name)
{
if (!UsingCollection) return false;
- if (selection()->level()==0) return false;
- return trim(selection ()->getKeyItem(0).value()) == name;
+ if (selection()->orderlevel()==0) return false;
+ return trim(selection ()->getKeyItem(0)->value()) == name;
}
@@ -217,53 +241,60 @@ mgMenu::mgMenu ()
void
-mgMainMenu::DumpOrders(mgValmap& nv)
+mgMainMenu::DumpSelections(mgValmap& nv)
{
- for (unsigned int idx=0;idx<orders.size();idx++)
+ for (unsigned int idx=0;idx<selections.size();idx++)
{
- mgOrder *o = orders[idx];
- if (!o)
- mgError("DumpOrders:order[%u] is 0",idx);
+ mgSelection *s = selections[idx];
+ if (!s)
+ mgError("DumpSelections:selection[%u] is 0",idx);
char prefix[20];
sprintf(prefix,"order%u",idx);
- o->DumpState(nv,prefix);
+ s->DumpState(nv,prefix);
}
}
void
mgMainMenu::SaveState()
{
- char *b;
- asprintf(&b,"%s/muggle.state",cPlugin::ConfigDirectory ("muggle"));
- FILE *f = fopen(b,"w");
+ char *oldfile;
+ char *newfile;
+ char *statefile;
+ mgValmap nmain("MainMenu");
+ mgValmap nsel("tree");
+ mgValmap ncol("collection");
+ asprintf(&oldfile,"%s/muggle.state.old",cPlugin::ConfigDirectory ("muggle"));
+ asprintf(&newfile,"%s/muggle.state.new",cPlugin::ConfigDirectory ("muggle"));
+ asprintf(&statefile,"%s/muggle.state",cPlugin::ConfigDirectory ("muggle"));
+ FILE *f = fopen(newfile,"w");
if (!f)
{
if (!m_save_warned)
- mgWarning("Cannot write %s",b);
+ mgWarning("Cannot write %s",newfile);
m_save_warned=true;
- free(b);
- return;
+ goto err_exit;
}
- free(b);
- mgValmap nmain("MainMenu");
- nmain.put("DefaultCollection",default_collection);
- nmain.put("UsingCollection",UsingCollection);
- nmain.put("TreeRedAction",int(Menus.front()->TreeRedAction));
- nmain.put("TreeGreenAction",int(Menus.front()->TreeGreenAction));
- nmain.put("TreeYellowAction",int(Menus.front()->TreeYellowAction));
- nmain.put("CollRedAction",int(Menus.front()->CollRedAction));
- nmain.put("CollGreenAction",int(Menus.front()->CollGreenAction));
- nmain.put("CollYellowAction",int(Menus.front()->CollYellowAction));
- nmain.put("CurrentOrder",m_current_order);
- DumpOrders(nmain);
- mgValmap nsel("tree");
- m_treesel->DumpState(nsel);
- mgValmap ncol("collection");
- m_collectionsel->DumpState(ncol);
+ nmain.put(default_collection,"DefaultCollection");
+ nmain.put(UsingCollection,"UsingCollection");
+ nmain.put(int(Menus.front()->TreeRedAction),"TreeRedAction");
+ nmain.put(int(Menus.front()->TreeGreenAction),"TreeGreenAction");
+ nmain.put(int(Menus.front()->TreeYellowAction),"TreeYellowAction");
+ nmain.put(int(Menus.front()->CollRedAction),"CollRedAction");
+ nmain.put(int(Menus.front()->CollGreenAction),"CollGreenAction");
+ nmain.put(int(Menus.front()->CollYellowAction),"CollYellowAction");
+ nsel.put(m_current_selection,"CurrentSelection");
+ DumpSelections(nsel);
+ m_collectionsel->DumpState(ncol,"collection");
nmain.Write(f);
nsel.Write(f);
ncol.Write(f);
fclose(f);
+ rename(statefile,oldfile);
+ rename(newfile,statefile);
+err_exit:
+ free(oldfile);
+ free(newfile);
+ free(statefile);
}
mgMainMenu::mgMainMenu ():cOsdMenu ("",25)
@@ -282,15 +313,17 @@ mgMainMenu::mgMainMenu ():cOsdMenu ("",25)
mgValmap nmain("MainMenu");
// define defaults for values missing in state file:
- nsel.put("FallThrough",true);
- nmain.put("DefaultCollection",play_collection);
- nmain.put("UsingCollection","false");
- nmain.put("TreeRedAction",int(actAddThisToCollection));
- nmain.put("TreeGreenAction",int(actInstantPlay));
- nmain.put("TreeYellowAction",int(actToggleSelection));
- nmain.put("CollRedAction",int(actAddThisToCollection));
- nmain.put("CollGreenAction",int(actInstantPlay));
- nmain.put("CollYellowAction",int(actToggleSelection));
+ nsel.put(true,"FallThrough");
+ nmain.put(play_collection,"DefaultCollection");
+ nmain.put(false,"UsingCollection");
+ nmain.put(int(actAddThisToCollection),"TreeRedAction");
+ nmain.put(int(actInstantPlay),"TreeGreenAction");
+ nmain.put(int(actToggleSelection),"TreeYellowAction");
+ nmain.put(int(actAddThisToCollection),"CollRedAction");
+ nmain.put(int(actInstantPlay),"CollGreenAction");
+ nmain.put(int(actToggleSelection),"CollYellowAction");
+ nmain.put(0,"CurrentOrder");
+
// load values from state file
char *b;
@@ -305,36 +338,29 @@ mgMainMenu::mgMainMenu ():cOsdMenu ("",25)
}
// get values from mgValmaps
- LoadOrders(nmain);
- default_collection = nmain.getstr("DefaultCollection");
- UsingCollection = nmain.getbool("UsingCollection");
InitMapFromSetup(nsel);
InitMapFromSetup(ncol);
- m_treesel = new mgSelection;
- m_treesel->setOrder(getOrder(m_current_order));
- m_treesel->InitFrom (nsel);
- m_treesel->CreateCollection(default_collection);
+ LoadSelections(nsel);
+ default_collection = nmain.getstr("DefaultCollection");
+ UsingCollection = nmain.getbool("UsingCollection");
+ selections[m_current_selection]->CreateCollection(default_collection);
if (default_collection!=play_collection)
- m_treesel->CreateCollection(play_collection);
- vector<mgKeyTypes> kt;
- kt.push_back(keyCollection);
- kt.push_back(keyCollectionItem);
- mgOrder o;
- o.setKeys(kt);
- m_collectionsel = new mgSelection;
- m_collectionsel->setOrder(&o);
- m_collectionsel->InitFrom (ncol);
- m_playsel = new mgSelection;
- m_playsel->setOrder(&o);
- m_playsel->InitFrom(ncol);
-
+ selections[m_current_selection]->CreateCollection(play_collection);
+ m_collectionsel = GenerateSelection();
+ m_collectionsel->InitFrom ("order0",ncol);
+ m_collectionsel->MakeCollection();
+ m_playsel = GenerateSelection();
+ m_playsel->InitFrom("order0",ncol);
+ m_playsel->MakeCollection();
// initialize
- if (m_playsel->level()!=1)
+ if (m_playsel->orderlevel()!=1)
{
m_playsel->leave_all();
m_playsel->enter(play_collection);
}
- UseNormalSelection ();
+ mgSelection *s = selections[m_current_selection];
+ s->CopyKeyValues(s);
+ s->Activate();
unsigned int posi = selection()->gotoPosition();
LoadExternalCommands(); // before AddMenu()
m_root = new mgTree;
@@ -349,56 +375,54 @@ mgMainMenu::mgMainMenu ():cOsdMenu ("",25)
}
void
-mgMainMenu::AddOrder()
+mgMainMenu::AddSelection()
{
- orders.push_back(new mgOrder);
+ selections.push_back(GenerateSelection());
+ newposition = selections.size()-1;
}
void
-mgMainMenu::DeleteOrder()
+mgMainMenu::DeleteSelection()
{
- mgOrder *o = orders[Current()];
+ mgSelection *o = selections[Current()];
delete o;
- orders.erase(orders.begin()+Current());
+ selections.erase(selections.begin()+Current());
}
void
-mgMainMenu::LoadOrders(mgValmap& nv)
+mgMainMenu::LoadSelections(mgValmap& nv)
{
for (unsigned int idx=0;idx<1000;idx++)
{
- char b[10];
- sprintf(b,"order%u",idx);
- mgOrder *o = new mgOrder(nv,b);
- if (o->size()==0)
+ char prefix[10];
+ sprintf(prefix,"order%u",idx);
+ mgSelection *s = GenerateSelection();
+ s->InitFrom(prefix,nv);
+ if (s->ordersize())
+ selections.push_back(s);
+ else
{
- delete o;
+ delete s;
break;
}
- orders.push_back(o);
}
- m_current_order = nv.getuint("CurrentOrder");
- if (m_current_order >= orders.size())
- m_current_order=0;
- if (orders.size()>0) return;
-
- nv.put("order0.Keys.0.Type",keyArtist);
- nv.put("order0.Keys.1.Type",keyAlbum);
- nv.put("order0.Keys.2.Type",keyTrack);
-
- nv.put("order1.Keys.0.Type",keyAlbum);
- nv.put("order1.Keys.1.Type",keyTrack);
-
- nv.put("order2.Keys.0.Type",keyGenres);
- nv.put("order2.Keys.1.Type",keyArtist);
- nv.put("order2.Keys.2.Type",keyAlbum);
- nv.put("order2.Keys.3.Type",keyTrack);
-
- nv.put("order3.Keys.0.Type",keyArtist);
- nv.put("order3.Keys.1.Type",keyTrack);
-
- nv.put("CurrentOrder",0);
- LoadOrders(nv);
+ if (selections.size()==0)
+ {
+ for (unsigned int i=1; i<100;i++)
+ {
+ mgSelection* s=GenerateSelection();
+ if (s->InitDefaultOrder(i))
+ selections.push_back(s);
+ else
+ {
+ delete s;
+ break;
+ }
+ }
+ }
+ m_current_selection = nv.getuint("CurrentSelection");
+ if (m_current_selection >= selections.size())
+ m_current_selection=0;
}
void
@@ -429,15 +453,14 @@ mgMainMenu::LoadExternalCommands()
mgMainMenu::~mgMainMenu()
{
- delete m_treesel;
delete m_collectionsel;
delete m_playsel;
delete m_Status;
delete moveselection;
delete m_root;
delete external_commands;
- for (unsigned int i=0;i<orders.size();i++)
- delete orders[i];
+ for (unsigned int i=0;i<selections.size();i++)
+ delete selections[i];
}
void
@@ -476,14 +499,18 @@ mgMenu::AddExternalAction(const mgActions action, const char *title)
void
mgMainMenu::AddOrderActions(mgMenu* m)
{
- for (unsigned int idx=0;idx<orders.size();idx++)
+ for (unsigned int idx=0;idx<selections.size();idx++)
{
- mgOrder *o = orders[idx];
+ mgSelection *o = selections[idx];
if (!o)
- mgError("AddOrderAction:orders[%u] is 0",idx);
+ mgError("AddOrderAction:selections[%u] is 0",idx);
mgAction *a = m->GenerateAction(actOrder,actNone);
assert(a);
- a->SetText(hk(o->Name().c_str()));
+ string name = o->Name(); // do not combine these 2 lines!
+ const char *oname = name.c_str();
+ if (strlen(oname)==0)
+ oname = tr("Order is undefined");
+ a->SetText(hk(oname));
AddItem(a);
}
}
@@ -491,20 +518,12 @@ mgMainMenu::AddOrderActions(mgMenu* m)
void
mgMenu::AddSelectionItems (mgSelection *sel,mgActions act)
{
+ sel->Activate();
for (unsigned int i = 0; i < sel->listitems.size (); i++)
{
mgAction *a = GenerateAction(act, actEntry);
if (!a) continue;
const char *name = a->MenuName(i+1,sel->listitems[i]);
- // add incremental filter here
-#if 0
- // example:
- if (name[0]!='C')
- continue;
- // adapt newposition since it refers to position in mgSelection:
- if ((signed int)i==osd()->newposition)
- osd()->newposition = osd()->Count();
-#endif
a->SetText(name,false);
a->setHandle(i);
osd()->AddItem(a);
@@ -697,22 +716,10 @@ mgMenu::Process (eKeys key)
void
mgTree::UpdateSearchPosition()
{
- int position = -1;
if( !m_incsearch || m_filter.empty() )
- position = m_start_position;
+ osd()->newposition = m_start_position;
else
- {
- // find the first item starting with m_filter
- mgSelection::mgListItems& listitems = osd()->selection()->listitems;
- for (unsigned int idx = 0 ; idx < listitems.size(); idx++)
- if( strncasecmp( listitems[idx].value().c_str(), m_filter.c_str(), m_filter.size() )>=0 )
- {
- position = idx;
- break;
- }
- }
- osd()->newposition = position;
- osd()->DisplayGoto();
+ osd()->newposition = osd()->selection()->searchPosition(m_filter);
}
bool
@@ -830,7 +837,7 @@ eOSState mgMainMenu::ProcessKey (eKeys key)
mgPlayerControl * c = PlayerControl ();
if (c)
{
- if (!c->Active ())
+ if (!c->Playing ())
{
c->Shutdown ();
if (instant_playing && queue_playing) {
@@ -926,10 +933,7 @@ otherkeys:
else if (newmenu != Menus.back ())
AddMenu (newmenu,newposition);
- if (UsingCollection)
- forcerefresh |= m_collectionsel->cacheIsEmpty();
- else
- forcerefresh |= m_treesel->cacheIsEmpty();
+ forcerefresh |= selection()->cacheIsEmpty();
forcerefresh |= (newposition>=0);
@@ -959,46 +963,48 @@ mgMainMenu::showMessage()
{
if (m_message)
{
- showmessage(m_message);
+ showmessage(0,m_message);
free(m_message);
m_message = NULL;
}
}
void
-showmessage(const char * msg,int duration)
+showmessage(int duration,const char * msg, ...)
{
+ va_list ap;
+ va_start(ap,msg);
+ char buffer[200];
+ vsnprintf(buffer,199,tr(msg),ap);
#if VDRVERSNUM >= 10307
- Skins.Message (mtInfo, msg,duration);
+ if (!duration) duration=2;
+ Skins.Message (mtInfo, buffer,duration);
Skins.Flush ();
#else
- Interface->Status (msg);
+ Interface->Status (buffer);
Interface->Flush ();
#endif
+ va_end(ap);
}
void
-showimportcount(unsigned int count,bool final=false)
+showimportcount(unsigned int impcount,bool final=false)
{
- char b[100];
+#if 0
+ // we should not write to the OSD since this is not the
+ // foreground thread. We could go thru port 2001.
if (final)
- {
- sprintf(b,tr("Import done:Imported %d items"),count);
- assert(strlen(b)<100);
- showmessage(b,1);
- }
+ showmessage(1,"Import done:Imported %d items",impcount);
else
- {
- sprintf(b,tr("Imported %d items..."),count);
- assert(strlen(b)<100);
- showmessage(b);
- }
+ showmessage(2,"Imported %d items...",impcount);
+#endif
}
void
mgMainMenu::AddMenu (mgMenu * m,unsigned int position)
{
Menus.push_back (m);
+ selection()->Activate();
m->setosd (this);
m->setParentIndex(Current());
if (Get(Current()))
@@ -1039,40 +1045,47 @@ mgMenuOrders::BuildOsd ()
mgMenuOrder::mgMenuOrder()
{
- m_order=0;
+ m_selection=0;
+ m_orgselection = 0;
}
mgMenuOrder::~mgMenuOrder()
{
- if (m_order)
- delete m_order;
+ if (m_selection)
+ delete m_selection;
}
string
mgMenuOrder::Title() const
{
- return m_order->Name();
+ return m_selection->Name();
}
void
mgMenuOrder::BuildOsd ()
{
- if (!m_order)
- {
- m_order = new mgOrder;
- *m_order = *(osd()->getOrder(getParentIndex()));
- }
+ if (!m_orgselection)
+ m_orgselection = osd()->getSelection(getParentIndex());;
+ if (!m_selection)
+ m_selection = GenerateSelection(m_orgselection);
+ if (m_selection->ordersize()==0)
+ m_selection->InitDefaultOrder(1);
InitOsd ();
m_keytypes.clear();
- m_keytypes.reserve(mgKeyTypesNr+1);
m_keynames.clear();
- m_keynames.reserve(50);
- m_orderbycount = m_order->getOrderByCount();
- for (unsigned int i=0;i<m_order->size();i++)
+ m_orderbycount = m_selection->getOrderByCount();
+ for (unsigned int i=0;i<m_selection->ordersize();i++)
{
+ if (m_selection->getKeyType(i)==keyGdUnique)
+ break;
unsigned int kt;
- m_keynames.push_back(m_order->Choices(i,&kt));
+ m_keynames.push_back(m_selection->Choices(i,&kt));
m_keytypes.push_back(kt);
+ }
+ for (unsigned int i=0;i<m_selection->ordersize();i++)
+ {
+ if (m_selection->getKeyType(i)==keyGdUnique)
+ break;
char buf[20];
sprintf(buf,tr("Key %d"),i+1);
mgAction *a = actGenerateKeyItem(buf,(int*)&m_keytypes[i],m_keynames[i].size(),&m_keynames[i][0]);
@@ -1085,31 +1098,39 @@ mgMenuOrder::BuildOsd ()
}
bool
-mgMenuOrder::ChangeOrder(eKeys key)
+mgMenuOrder::ChangeSelection(eKeys key)
{
- vector <mgKeyTypes> newtypes;
+ vector <const char*> newtypes;
newtypes.clear();
for (unsigned int i=0; i<m_keytypes.size();i++)
- newtypes.push_back(ktValue(m_keynames[i][m_keytypes[i]]));
- mgOrder n = mgOrder(newtypes);
- n.setOrderByCount(m_orderbycount);
- bool result = !(n == *m_order);
- *m_order = n;
- if (result)
+ newtypes.push_back(m_keynames[i][m_keytypes[i]]);
+ mgSelection *newsel = GenerateSelection(m_orgselection);
+ newsel->setKeys(newtypes);
+ newsel->setOrderByCount(m_orderbycount);
+ bool changed = !newsel->SameOrder(m_selection);
+ if (changed)
{
+ delete m_selection;
+ m_selection = newsel;
osd()->forcerefresh = true;
int np = osd()->Current();
if (key==kUp && np) np--;
if (key==kDown) np++;
osd()->newposition = np;
}
- return result;
+ else
+ delete newsel;
+ return changed;
}
void
-mgMenuOrder::SaveOrder()
+mgMenuOrder::SaveSelection()
{
- *(osd()->getOrder(getParentIndex())) = *m_order;
+ m_selection->CopyKeyValues(osd()->selection());
+ m_selection->Activate();
+ osd()->setSelection(getParentIndex(),m_selection);
+ m_selection = 0;
+ m_orgselection = 0;
osd()->SaveState();
}
@@ -1177,3 +1198,32 @@ mgMenu::Display ()
osd ()->DisplayGoto ();
}
+bool
+create_question()
+{
+ char *b;
+ asprintf(&b,tr("Create database %s?"),the_setup.DbName);
+ bool result = Interface->Confirm(b);
+ free(b);
+ return result;
+}
+
+bool
+import()
+{
+ if (!Interface->Confirm(tr("Import items?")))
+ return false;
+ mgThreadSync *s = mgThreadSync::get_instance();
+ if (!s)
+ return false;
+ static char *tld_arg[] = { ".", 0};
+ int res = chdir(the_setup.ToplevelDir);
+ if (res)
+ {
+ showmessage(2,tr("Cannot access directory %s:%d"),
+ the_setup.ToplevelDir,errno);
+ return false;
+ }
+ s->Sync(tld_arg);
+ return true;
+}