diff options
Diffstat (limited to 'vdr_menu.c')
-rw-r--r-- | vdr_menu.c | 1390 |
1 files changed, 543 insertions, 847 deletions
@@ -1,10 +1,9 @@ -/*! +/*! * \file vdr_menu.c * \brief Implements menu handling for browsing media libraries within VDR * - * \version $Revision: 1.27 $ - * \date $Date$ - * \author Ralf Klueber, Lars von Wedel, Andreas Kellner + * \version $Revision: 1.27 $ * \date $Date$ + * \author Ralf Klueber, Lars von Wedel, Andreas Kellner, Wolfgang Rohdewald * \author Responsible author: $Author$ * * $Id$ @@ -14,10 +13,6 @@ #include <string> #include <vector> -// #include <cstring> - -#include <mysql/mysql.h> - #include <menuitems.h> #include <tools.h> #include <config.h> @@ -28,965 +23,666 @@ #include <vdr/skins.h> #endif -#include "muggle.h" +#include "vdr_setup.h" #include "vdr_menu.h" #include "vdr_player.h" #include "i18n.h" -#include "mg_content_interface.h" -#include "mg_playlist.h" #define DEBUG #include "mg_tools.h" -#include "mg_media.h" -#include "mg_filters.h" -#include "gd_content_interface.h" - -// ----------------------- mgMenuTreeItem ------------------ +#include <config.h> +#if VDRVERSNUM >= 10307 +#include <vdr/interface.h> +#include <vdr/skins.h> +#endif -mgMenuTreeItem::mgMenuTreeItem( mgSelectionTreeNode *node ) - : m_node( node ) +void +mgStatus::OsdCurrentItem(const char* Text) { - Set(); + cOsdItem* i = main->Get(main->Current()); + if (!i) return; + if (i == IgnoreNextEventOn) + { + IgnoreNextEventOn = NULL; + return; + } + mgAction * a = dynamic_cast<mgAction *>(i); + if (!a) + mgError("mgStatus::OsdCurrentItem expected an mgAction*"); + a->Notify(); +} + +void Play(mgSelection *sel,const bool select) { + mgSelection *s = new mgSelection(sel); + if (select) s->select(); + if (s->empty()) + { + delete s; + return; + } + mgPlayerControl *c = PlayerControl (); + if (c) + c->NewPlaylist (s); + else + cControl::Launch (new mgPlayerControl (s)); } -mgSelectionTreeNode* mgMenuTreeItem::Node() + +//! \brief queue the selection for playing, abort ongoing instant play +void +mgMainMenu::PlayQueue() { - return m_node; + queue_playing=true; + instant_playing=false; + Play(playselection()); } -void mgMenuTreeItem::Set() +//! \brief queue the selection for playing, abort ongoing queue playing +void +mgMainMenu::PlayInstant(const bool select) { - char *buffer = 0; - asprintf( &buffer, m_node->getLabel().c_str() ); - SetText( buffer, false ); + instant_playing=true; + Play(selection(),select); } -// ----------------------- mgMainMenu ---------------------- -mgMainMenu::mgMainMenu(mgMedia *media, mgSelectionTreeNode *root, - mgPlaylist *playlist, cCommands *playlist_commands) - : cOsdMenu( "" ), m_media(media), m_root(root), - m_current_playlist(playlist), m_playlist_commands(playlist_commands) +bool +mgMainMenu::ShowingCollections() { - mgDebug( 1, "Creating Muggle Main Menu" ); - - SetTitle( tr("Muggle Media Database") ); - SetButtons(); + return (UsingCollection && selection ()->level () == 0); +} - DisplayTree( m_root ); - strncpy( m_listname, playlist->getListname().c_str(), 31 ); - m_listname[31] = '\0'; - m_editing_listname = false; +bool +mgMainMenu::DefaultCollectionSelected() +{ + string this_sel = trim(selection ()->getCurrentValue()); + return (ShowingCollections () && this_sel == default_collection); } -mgSelectionTreeNode *mgMainMenu::CurrentNode() + +bool +mgMainMenu::DefaultCollectionEntered() { - mgMenuTreeItem *item = (mgMenuTreeItem *)Get( Current() ); - return item? item->Node(): 0; + if (!UsingCollection) return false; + if (selection()->level()==0) return false; + string collection = trim(selection ()->getKeyValue(0)); + return (collection == default_collection); } -mgMenuTreeItem *mgMainMenu::CurrentItem() -{ - mgMenuTreeItem *item = (mgMenuTreeItem *)Get( Current() ); - return item; +mgMenu * +mgMainMenu::Parent () +{ + if (Menus.size () < 2) + return NULL; + return Menus[Menus.size () - 2]; } -void mgMainMenu::SetButtons( ) + +mgOsdItem* +mgMenu::GenerateAction(const mgActions action) { - SetHasHotkeys(); + mgOsdItem *result = actGenerate(action); + if (result) + { + result->SetMenu(this); + if (!result->Enabled()) + { + delete result; + result=NULL; + } + } + return result; +} - if( m_state == TREE ) - { - SetHelp( tr("Add"), tr("Cycle tree"), tr("Playlist"), tr("Submenu") ); - } - else if( m_state == TREE_SUBMENU ) - { - SetHelp( tr("Instant Play"), tr("2"), tr("3"), tr("Mainmenu") ); - } - else if( m_state == PLAYLIST ) - { - SetHelp( tr("Play"), tr("Move"), tr("Filter"), tr("Submenu") ); - } - else if( m_state == PLAYLIST_SUBMENU ) - { - SetHelp( tr("Load"), tr("Save"), tr("Delete"), tr("Mainmenu") ); - } - else if( m_state == FILTER ) +void +mgMenu::ExecuteAction(const mgActions action) +{ + mgAction *a = GenerateAction (action); + if (a) { - SetHelp( tr("Query"), tr("Other Search"), tr("Browser"), tr("Submenu") ); + a->Execute (); + delete a; } - else - { - SetHelp( "t", "o", "d", "o" ); - } } -void mgMainMenu::Move( int from, int to ) -{ - m_current_playlist->move( from, to ); - cOsdMenu::Move( from, to ); - Display(); +mgPlayerControl * +PlayerControl () +{ + mgPlayerControl *result = NULL; + cControl *control = cControl::Control (); + if (control && typeid (*control) == typeid (mgPlayerControl)) +// is there a running MP3 player? + result = static_cast < mgPlayerControl * >(control); + return result; } -eOSState mgMainMenu::ProcessKey(eKeys key) -{ - MGLOG( "mgMainMenu::ProcessKey" ); - eOSState state = cOsdMenu::ProcessKey(key); - if( m_state == TREE ) - { - mgDebug( 1, "mgMainMenu: in state TREE" ); - // Navigate with up/dn, left/right (pgup, pgdn) - // Expand with OK, Collapse with Back - if( state == osUnknown ) - { - switch( key ) - { - case kOk: - { - m_history.push_back( Current() ); - mgSelectionTreeNode *child = CurrentNode(); - DisplayTree( child ); - - state = osContinue; - } break; - case kRed: - { - mgSelectionTreeNode *current = CurrentNode(); - if( current ) - { - mgDebug( 1, "mgMainMenu: add selection %s to playlist", current->getLabel().c_str() ); - // Add selection to Play - std::vector<mgContentItem*> *tracks = current->getTracks(); - - if( tracks ) - { - - char *buffer = 0; - asprintf( &buffer, tr("%d tracks sent to current playlist"), (int) tracks->size() ); - m_current_playlist->appendList(tracks); -#if VDRVERSNUM >= 10307 - Skins.Message(mtInfo,buffer); - Skins.Flush(); -#else - Interface->Status( buffer ); - Interface->Flush(); -#endif - free( buffer ); - } - else - { - mgDebug(1, "No tracks for current selection" ); - } - } - else - { - mgDebug(1, "Cannot find currently selected node!" ); - } - state = osContinue; - } break; - case kGreen: - { - mgDebug( 1, "mgMainMenu: cycle treeviews (todo)" ); - - state = osContinue; - } break; - case kYellow: - { - mgDebug( 1, "mgMainMenu: cycle to playlist view" ); - - DisplayPlaylist(); - } break; - case kBlue: - { - m_last_osd_index = Current(); - m_menu_item = CurrentItem()->Node(); - DisplayTreeSubmenu(); - - state = osContinue; - } break; - default: - { - state = osContinue; - } break; - } - } - else if( state == osBack ) - { - mgSelectionTreeNode *parent = m_node->getParent(); - - if( parent ) - { - mgDebug( 1, "mgMainMenu: collapse current node" ); - - m_node->collapse(); +mgMenu::mgMenu () +{ + m_osd = NULL; + TreeRedAction = mgActions(0); + TreeGreenAction = mgActions(0); + TreeYellowAction = mgActions(0); + CollRedAction = mgActions(0); + CollGreenAction = mgActions(0); + CollYellowAction = mgActions(0); +} - // restore last selected entry - int last = m_history.back(); - m_history.pop_back(); - DisplayTree( parent, last ); - - state = osContinue; - } - else - { - // Back pressed on root level... Go back to Main VDR menu - state = osBack; +// ----------------------- mgMainMenu ---------------------- - // state = osContinue; - } - } - } - else if( m_state == TREE_SUBMENU ) - { - if( state == osUnknown ) - { - switch( key ) - { - case k0 ... k9: - { - int n = key - k0; - TreeSubmenuAction( n ); - - state = osContinue; - } break; - case kRed: - { - state = TreeSubmenuAction( 0 ); - } break; - case kBlue: - { - m_state = TREE; - - // restore last selected entry - int last = m_history.back(); - DisplayTree( m_node, last ); - - state = osContinue; - } break; - case kOk: - { - state = TreeSubmenuAction( Current() ); - } break; - default: - { - state = osContinue; - } break; - } - } - else if( state == osBack ) - { - m_state = TREE; - // restore last selected entry - int last = m_history.back(); - DisplayTree( m_node, last ); - - state = osContinue; - } - } - else if( m_state == PLAYLIST ) - { - if( state == osUnknown ) - { - switch( key ) - { - case kOk: - { - // start replay at selected index - unsigned idx = Current(); - Play( m_current_playlist, idx ); - state = osContinue; - } break; - case kRed: - { - // TODO: what happens if the user presses play and the player is already active? - // TODO: resume? - unsigned resume = mgMuggle::getResumeIndex(); - Play( m_current_playlist, resume ); - state = osEnd; - } break; - case kGreen: - { - Mark(); - - state = osContinue; - } break; - case kYellow: - { - DisplayFilter(); - state = osContinue; - } break; - case kBlue: - { - // Submenu - m_last_osd_index = Current(); - DisplayPlaylistSubmenu(); - - state = osContinue; - } break; - default: - { - state = osContinue; - }; - } - } - } - else if( m_state == LOAD_PLAYLIST ) - { - if( state == osUnknown ) - { - switch( key ) - { - case kOk: - { - // load the selected playlist - - m_current_playlist -> clear(); - delete m_current_playlist; - - std::string selected = (*m_plists)[ Current() ]; - m_current_playlist = m_media->loadPlaylist( selected.c_str() ); - - // clean the list of playlist - m_plists->clear(); - m_last_osd_index =0; - DisplayPlaylist(0); - state = osContinue; - } break; - default: - { - state = osContinue; - }; - } - } - } - else if( m_state == PLAYLIST_SUBMENU ) - { - if( state == osUnknown ) - { - switch( key ) - { - case k0 ... k9: - { - int n = key - k0; - PlaylistSubmenuAction( n ); - - state = osContinue; - } break; - case kYellow: - { - PlaylistSubmenuAction( 3 ); - } break; - case kBlue: - { - m_state = PLAYLIST; - DisplayPlaylist( m_last_osd_index ); - - state = osContinue; - } break; - case kOk: - { - if( Current() != 0 ) - { // not editing playlist name - state = PlaylistSubmenuAction( Current() ); - } - else - { // editing playlist name - m_editing_listname = !m_editing_listname; - if( m_editing_listname = false ) - { // we just changed from true to false so editing was terminated - RenamePlaylist( std::string( m_listname ) ); - - } - } - } break; - default: - { - state = osContinue; - } break; - } - } - else if( state == osBack ) - { - m_state = PLAYLIST; - DisplayPlaylist( m_last_osd_index ); - - state = osContinue; - } - } - else if( m_state == PLAYLIST_COMMANDS ) - { - if( state == osUnknown ) - { - switch( key ) - { - case kOk: - { - state = ExecutePlaylistCommand( Current() ); - } break; - default: - { - } - } - } - else if( state == osBack ) - { - m_state = PLAYLIST_SUBMENU; - DisplayPlaylistSubmenu(); - - state = osContinue; - } - } - else if( m_state == FILTER ) - { - if( state == osUnknown ) - { - switch( key ) - { - case kRed: // - { - mgDebug( 1, "mgMainMenu: query and display results" ); - - if( m_root ) - { - delete m_root; - } - - m_root = m_media->applyActiveFilter(); - // collapse all? - DisplayTree( m_root ); - - state = osContinue; - } break; - case kGreen: - { - // cycle FILTER -> TREE - mgDebug( 1, "mgMainMenu: next filters " ); - - m_media->nextFilterSet(); - DisplayFilter(); - - state = osContinue; - } break; - case kYellow: - { - // Green: treeview - mgDebug( 1, "mgMainMenu: switch to treeview" ); - - DisplayTreeViewSelector(); - - state = osContinue; - } break; - case kBlue: - { - mgDebug( 1, "mgMainMenu: submenu" ); - state = osContinue; - } break; - default: - { - state = osContinue; - } - } - } - else if( state == osBack ) - { - // m_media->resetFilters();? - } - // RaK: Verhindert, dass die Help Buttons verschwinden, - // ist aber keine schöne Lösung - //SetHelp( tr("Query"), tr("Other Search"), tr("Browser"), tr("Submenu") ); - } - else - { - mgDebug(1, "Process key: else"); - mgDebug(1, "Process key: %d", (int) state); - } - - return state; +void mgMainMenu::SaveState() +{ + char *b; + asprintf(&b,"%s/muggle.state",cPlugin::ConfigDirectory ("muggle")); + FILE *f = fopen(b,"w"); + free(b); + if (!f) return; + 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)); + mgValmap nsel("tree"); + m_treesel.DumpState(nsel); + mgValmap ncol("collection"); + m_collectionsel.DumpState(ncol); + nmain.Write(f); + nsel.Write(f); + ncol.Write(f); + fclose(f); } -void mgMainMenu::DisplayTree( mgSelectionTreeNode* node, int select ) +mgMainMenu::mgMainMenu ():cOsdMenu ("") { - m_state = TREE; + m_Status = new mgStatus(this); + m_message = NULL; + queue_playing=false; + instant_playing=false; + play_collection = tr("play"); + mgValmap nsel("tree"); + mgValmap ncol("collection"); + mgValmap nmain("MainMenu"); + + // define defaults for values missing in state file: + ncol.put("Keys.0.Choice","Collection"); + ncol.put("Keys.1.Choice","Collection item"); + 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)); + + // load values from state file + char *b; + asprintf(&b,"%s/muggle.state",cPlugin::ConfigDirectory ("muggle")); + FILE *f = fopen(b,"r"); + free(b); + if (f) { + nsel.Read(f); + ncol.Read(f); + nmain.Read(f); + fclose(f); + } - if( node->expand( ) ) + // get values from mgValmaps + default_collection = nmain.getstr("DefaultCollection"); + UsingCollection = nmain.getbool("UsingCollection"); + InitMapFromSetup(nsel); + m_treesel.InitFrom (nsel); + InitMapFromSetup(ncol); + m_collectionsel.InitFrom (ncol); + m_playsel.InitFrom(ncol); + + // initialize + m_collectionsel.CreateCollection(default_collection); + m_collectionsel.CreateCollection(play_collection); + m_playsel.setKey(0,"Collection"); + m_playsel.setKey(1,"Collection item"); + m_playsel.enter(play_collection); + UseNormalSelection (); + unsigned int posi = selection()->gotoPosition(); + mgMenu *root = new mgTree; + root->TreeRedAction = mgActions(nmain.getuint("TreeRedAction")); + root->TreeGreenAction = mgActions(nmain.getuint("TreeGreenAction")); + root->TreeYellowAction = mgActions(nmain.getuint("TreeYellowAction")); + root->CollRedAction = mgActions(nmain.getuint("CollRedAction")); + root->CollGreenAction = mgActions(nmain.getuint("CollGreenAction")); + root->CollYellowAction = mgActions(nmain.getuint("CollYellowAction")); + AddMenu (root); + + SetCurrent (Get (posi)); + +// Read commands for collections in etc. /video/muggle/playlist_commands.conf + external_commands = new cCommands (); + + char * + cmd_file = (char *) AddDirectory (cPlugin::ConfigDirectory ("muggle"), + "playlist_commands.conf"); + mgDebug (1, "mgMuggle::Start: Looking for file %s", cmd_file); + bool have_cmd_file = external_commands->Load ((const char *) cmd_file); + + if (!have_cmd_file) { - Clear(); - - char buffer[256]; - sprintf( buffer, "Muggle - %s", node->getLabel().c_str() ); - - SetTitle( buffer ); - SetButtons(); - - m_node = node; - std::vector<mgSelectionTreeNode*> children = node->getChildren(); - - for( std::vector<mgSelectionTreeNode*>::iterator iter = children.begin(); - iter != children.end(); - iter ++ ) - { - Add( new mgMenuTreeItem( *iter ) ); - } - - cOsdItem *item = Get( select ); - SetCurrent( item ); - - RefreshCurrent(); - DisplayCurrent(true); + delete external_commands; + external_commands = NULL; } - Display(); + forcerefresh = false; } -void mgMainMenu::DisplayTreeViewSelector() +mgMainMenu::~mgMainMenu() { - m_history.clear(); - // collapse all! - DisplayTree( m_root ); + delete m_Status; } -void mgMainMenu::DisplayTreeSubmenu() +void +mgMainMenu::InitMapFromSetup (mgValmap& nv) { - m_state = TREE_SUBMENU; - - Clear(); - SetButtons(); + // values from setup override saved values + nv["Host"] = the_setup.DbHost; + nv["User"] = the_setup.DbUser; + nv["Password"] = the_setup.DbPass; + nv["Directory"] = cPlugin::ConfigDirectory ("muggle"); + nv["ToplevelDir"] = the_setup.ToplevelDir; +} - char *buffer; - asprintf( &buffer, "Muggle - %s", tr("Tree View Commands") ); - SetTitle( buffer ); - free( buffer ); +void +mgMenu::AddAction (const mgActions action, const bool hotkey) +{ + mgOsdItem *a = GenerateAction(action); + if (!a) return; + const char *mn = a->MenuName(); + if (strlen(mn)==0) + mgError("AddAction(%d):MenuName is empty",int(action)); + if (hotkey) + a->SetText(osd()->hk(mn)); + else + a->SetText(mn); + free(const_cast<char*>(mn)); + osd()->Add(a); +} - // Add items - Add( new cOsdItem( "Instant play" ) ); - Display(); +void +mgMenu::AddExternalAction(const mgActions action, const char *title) +{ + mgOsdItem *a = GenerateAction(action); + if (!a) return; + a->SetText(osd()->hk(title)); + osd()->Add(a); } -eOSState mgMainMenu::TreeSubmenuAction( int n ) +void +mgMenu::AddSelectionItems () { - eOSState state = osContinue; - - switch( n ) + for (unsigned int i = 0; i < selection()->values.size (); i++) + { + mgOsdItem *a = GenerateAction(actEntry); + if (!a) continue; + a->SetText(a->MenuName(i+1,selection()->values[i]),false); + osd()->Add(a); + } + if (osd()->ShowingCollections ()) { - case 0: - { - // action 0: instant play of current node, might need a security question - - mgSelectionTreeNode *current = CurrentNode(); - if( current ) - { - // append current node - std::vector<mgContentItem*> *tracks = m_menu_item->getTracks(); - - if( tracks ) - { - // clear playlist - m_current_playlist->clear(); - m_current_playlist->appendList( tracks ); - - // play - mgMuggle::setResumeIndex( 0 ); - Play( m_current_playlist, 0 ); - - state = osEnd; - } - } - } break; - case 1: - { - // action 0 - } break; - default: - { - // undefined action - } break; + mgCreateCollection *a = new mgCreateCollection; + if (!a) return; + a->SetMenu(this); + if (!a->Enabled()) + { + delete a; + a=NULL; + } + if (!a) return; + a->SetText(a->MenuName(),false); + osd()->Add(a); } - - return state; } -void mgMainMenu::DisplayPlaylist( int index_current ) -{ - m_state = PLAYLIST; - - // make sure we have a current playlist - Clear(); - SetButtons(); - std::vector<mgContentItem*>* list = m_current_playlist-> getAll(); - static char titlestr[80]; - sprintf( titlestr, "Muggle - %s (%d %s)",tr("Playlist"), - list->size() , - tr("items") ); - SetTitle( titlestr ); +const char * +mgMenu::BlueName () +{ + if (typeid (*this) == typeid (mgTree)) + return tr("Commands"); + else + return tr ("List"); +} - for( unsigned int i = 0; i < m_current_playlist->getNumItems(); i++) +void +mgMenu::SetHelpKeys() +{ + const char *Red = NULL; + const char *Green = NULL; + const char *Yellow = NULL; + mgOsdItem *a; + if (osd()->UsingCollection) { - std::string label = m_current_playlist->getLabel( i, " " ); - Add( new cOsdItem( label.c_str() ) ); + if ((a = GenerateAction (CollRedAction))) + Red = a->ButtonName (); + if ((a = GenerateAction (CollGreenAction))) + Green = a->ButtonName (); + if ((a = GenerateAction (CollYellowAction))) + Yellow = a->ButtonName (); } - - if( index_current >= 0 ) + else { - cOsdItem *item = Get( m_last_osd_index ); - SetCurrent( item ); - RefreshCurrent(); - DisplayCurrent( true ); - } - - Display(); -} - -void mgMainMenu::LoadPlaylist() -{ - m_state = LOAD_PLAYLIST; - static char titlestr[80]; - - // make sure we have a current playlist - Clear(); - SetButtons(); - sprintf( titlestr, "Muggle - %s %s ",tr("load"), tr("Playlist")); - SetTitle( titlestr ); - - // retrieve list of available playlists - m_plists = m_media->getStoredPlaylists(); - - for(std::vector<std::string>::iterator iter = m_plists->begin(); - iter != m_plists->end() ; iter++) - { - Add( new cOsdItem( iter->c_str() ) ); + if ((a = GenerateAction (TreeRedAction))) + Red = a->ButtonName (); + if ((a = GenerateAction (TreeGreenAction))) + Green = a->ButtonName (); + if ((a = GenerateAction (TreeYellowAction))) + Yellow = a->ButtonName (); } - - Display(); + osd()->SetHelpKeys(Red,Green,Yellow,BlueName()); } -void mgMainMenu::SavePlaylist() -{ - if(m_current_playlist->getListname() == "") - { - // create dummy listname with current date and time - time_t currentTime = time(NULL); - m_current_playlist->setListname(ctime(¤tTime)); - } - m_current_playlist->storePlaylist(); -} -void mgMainMenu::RenamePlaylist( std::string name ) +void +mgMenu::InitOsd (const char *title,const bool hashotkeys) { - // dummy function. USes current date as name - m_current_playlist->setListname( name ); - - // confirmation -#if VDRVERSNUM >= 10307 - Skins.Message(mtInfo, "Playlist renamed" ); - Skins.Flush(); -#else - Interface->Status( "Playlist renamed" ); - Interface->Flush(); -#endif + osd ()->InitOsd (title,hashotkeys); } -void mgMainMenu::DisplayPlaylistSubmenu() + +void +mgMainMenu::InitOsd (const char *title,const bool hashotkeys) { - static const char allowed[] = { "abcdefghijklmnopqrstuvwxyz0123456789-_" }; + Clear (); + SetTitle (title); + if (hashotkeys) SetHasHotkeys (); +} - m_state = PLAYLIST_SUBMENU; - Clear(); - SetButtons(); - SetTitle( "Muggle - Playlist View Commands" ); +void +mgSubmenu::BuildOsd () +{ + static char b[100]; + snprintf(b,99,tr("Commands:%s"),trim(osd()->selection()->getCurrentValue()).c_str()); + InitOsd (b); + mgMenu *p = osd ()->Parent (); + if (!p) + return; + AddAction(actInstantPlay); + AddAction(actAddThisToCollection); + AddAction(actRemoveThisFromCollection); + AddAction(actToggleSelection); + AddAction(actSetDefault); + AddAction(actDeleteCollection); + AddAction(actChooseSearch); + AddAction(actExportTracklist); + cCommand *command; + if (osd()->external_commands) + { + int idx=0; + while ((command = osd ()->external_commands->Get (idx)) != NULL) + { + if (idx>actExternalHigh-actExternal0) + { + mgWarning("Too many external commands"); + break; + } + AddExternalAction (mgActions(idx+int(actExternal0)),command->Title()); + idx++; + } + } + TreeRedAction = actSetButton; + TreeGreenAction = actSetButton; + TreeYellowAction = actSetButton; + CollRedAction = actSetButton; + CollGreenAction = actSetButton; + CollYellowAction = actSetButton; +} - // Add items - Add( new cMenuEditStrItem( tr("Playlist name"), m_listname, 31, allowed ) ); - Add( new cOsdItem( tr("Load playlist" ) ) ); - Add( new cOsdItem( tr("Save playlist" ) ) ); - Add( new cOsdItem( tr("Clear playlist" ) ) ); - Add( new cOsdItem( tr("Remove entry from list" ) ) ); - Add( new cOsdItem( tr("Export playlist" ) ) ); - if( m_playlist_commands ) +eOSState +mgTree::Process (eKeys key) +{ + eOSState result = osUnknown; + switch (key) { - Add( new cOsdItem( tr("External playlist commands" ) ) ); + case kRed: + if (osd()->UsingCollection) + ExecuteAction (CollRedAction); + else + ExecuteAction (TreeRedAction); + return osContinue; + case kGreen: + if (osd()->UsingCollection) + ExecuteAction (CollGreenAction); + else + ExecuteAction (TreeGreenAction); + return osContinue; + case kYellow: + if (osd()->UsingCollection) + ExecuteAction (CollYellowAction); + else + ExecuteAction (TreeYellowAction); + return osContinue; + default: + result = osUnknown; + break; } + return result; +} - Display(); +void +mgTree::BuildOsd () +{ + InitOsd (selection ()->getListname ().c_str (), false); + AddSelectionItems (); } -void mgMainMenu::DisplayPlaylistCommands() +void +mgMainMenu::Message1(const char *msg, const char *arg1) { - m_state = PLAYLIST_COMMANDS; + if (strlen(msg)==0) return; + asprintf (&m_message, tr (msg), arg1); +} - cCommand *command; - int i = 0; - Clear(); - SetTitle( "Muggle - External Playlist Commands" ); +eOSState mgMainMenu::ProcessKey (eKeys key) +{ + eOSState result = osContinue; + if (key!=kNone) + mgDebug (3, "MainMenu::ProcessKey(%d)", (int) key); - while( ( command = m_playlist_commands->Get(i) ) != NULL ) + if (Menus.size()<1) + mgError("mgMainMenu::ProcessKey: Menus is empty"); + + mgPlayerControl * c = PlayerControl (); + if (c) { - Add( new cOsdItem( hk( command->Title() ) ) ); - i++; + if (!c->Active ()) + { + c->Shutdown (); + if (instant_playing && queue_playing) { + PlayQueue(); + } + else + { + instant_playing = false; + queue_playing = false; + } + } + else + { + switch (key) + { + case kPause: + c->Pause (); + break; + case kStop: + if (instant_playing && queue_playing) { + PlayQueue(); + } + else + { + queue_playing = false; + c->Stop (); + } + break; + case kChanUp: + c->Forward (); + break; + case kChanDn: + c->Backward (); + break; + default: + goto otherkeys; + } + goto pr_exit; + } } + else + if (key==kPlay) { + PlayQueue(); + goto pr_exit; + } +otherkeys: + newmenu = Menus.back(); // Default: Stay in current menu + newposition = -1; - Display(); -} - -eOSState mgMainMenu::ExecutePlaylistCommand( int current ) -{ - cCommand *command = m_playlist_commands->Get( current ); - if( command ) { - char *buffer = NULL; - bool confirmed = true; - if( command->Confirm() ) - { - asprintf( &buffer, "%s?", command->Title() ); -//#if VDRVERSNUM < 10307 - confirmed = Interface->Confirm( buffer ); -//#else -//#endif - free( buffer ); - } - if( confirmed ) - { - asprintf( &buffer, "%s...", command->Title() ); -#if VDRVERSNUM >= 10307 - Skins.Message(mtInfo,buffer); - Skins.Flush(); -#else - Interface->Status( buffer ); - Interface->Flush(); -#endif - free( buffer ); + mgMenu * oldmenu = newmenu; - std::string tmp_m3u_file = (char *) AddDirectory( cPlugin::ConfigDirectory("muggle"), "current.m3u" ); - m_current_playlist->exportM3U( tmp_m3u_file ); +// item specific key logic: + result = cOsdMenu::ProcessKey (key); - char *result = (char *)command->Execute( tmp_m3u_file.c_str() ); +// mgMenu specific key logic: + if (result == osUnknown) + result = oldmenu->Process (key); + } +// catch osBack for empty OSD lists +// (because if the list was empty, no mgOsdItem::ProcessKey was ever called) + if (result == osBack) + { + // do as if there was an entry + mgOsdItem *a = Menus.back()->GenerateAction(actEntry); + if (a) + { + result = a->Back(); + delete a; + } + } - /* What to do? Recode cMenuText (not much)? - if( result ) - { - return AddSubMenu( new cMenuText( command->Title(), result ) ); - } - */ - - free( result ); +// do nothing for unknown keys: + if (result == osUnknown) + goto pr_exit; - return osEnd; - } +// change OSD menu as requested: + if (newmenu == NULL) + { + if (Menus.size () > 1) + { + Menus.pop_back (); + forcerefresh = true; + } + else + { + result = osBack; // game over + goto pr_exit; + } } - return osContinue; -} - -eOSState mgMainMenu::PlaylistSubmenuAction( int n ) -{ - std::cout << "mgMainMenu::PlaylistSubmenuAction: " << n << std::endl << std::flush; - eOSState state = osContinue; - - switch( n ) + else if (newmenu != Menus.back ()) { - case 0: - { // rename playlist - should never get here! - state = osContinue; - } break; - - case 1: - { - LoadPlaylist(); -#if VDRVERSNUM < 10307 - Interface->Flush(); -#else - Skins.Flush(); -#endif - // jump to playlist view from here? - } break; - case 2: - { - SavePlaylist(); -#if VDRVERSNUM >= 10307 - Skins.Message(mtInfo,"Playlist saved"); - Skins.Flush(); -#else - Interface->Status( "Playlist saved"); - Interface->Flush(); -#endif - } break; - case 3: - { // clear playlist + AddMenu (newmenu); + } - cControl *control = cControl::Control(); - std::string buffer; + if (UsingCollection) + forcerefresh |= m_collectionsel.cacheIsEmpty(); + else + forcerefresh |= m_treesel.cacheIsEmpty(); - if( control && typeid(*control) == typeid(mgPlayerControl) ) - { - buffer = "Cannot clear playlist while playing."; - } - else - { - m_current_playlist->clear(); + forcerefresh |= (newposition>=0); - buffer = "Playlist cleared"; - } - - // confirmation -#if VDRVERSNUM >= 10307 - Skins.Message( mtInfo, buffer.c_str() ); - Skins.Flush(); -#else - Interface->Status( buffer.c_str() ); - Interface->Flush(); -#endif - - state = osContinue; - } break; - case 4: - { // remove selected title - bool res = m_current_playlist->remove( m_last_osd_index ); - - if( m_last_osd_index > 0 ) - { - m_last_osd_index --; - } - DisplayPlaylist( m_last_osd_index ); - - // confirmation - std::string confirm = res? "Entry deleted": "Cannot delete entry"; + if (forcerefresh) + { + mgDebug(2,"forced refresh"); + forcerefresh = false; + if (newposition<0) + newposition = selection()->gotoPosition(); + Menus.back ()->Display (newposition); + } +pr_exit: + showMessage(); + return result; +} +void +mgMainMenu::showMessage() +{ + if (m_message) + { #if VDRVERSNUM >= 10307 - Skins.Message( mtInfo, confirm.c_str() ); - Skins.Flush(); + Skins.Message (mtInfo, m_message); + Skins.Flush (); #else - Interface->Status( confirm.c_str() ); - Interface->Flush(); + Interface->Status (m_message); + Interface->Flush (); #endif - } break; - case 5: - { - std::string m3u_file = AddDirectory( cPlugin::ConfigDirectory("muggle"), - m_current_playlist->getListname().c_str() ); - m_current_playlist->exportM3U( m3u_file ); - } break; - case 6: - { - DisplayPlaylistCommands(); - } break; - default: - { - // undefined action - } break; + free(m_message); + m_message = NULL; } - - return state; } -void mgMainMenu::DisplayFilter() -{ - m_state = FILTER; - Clear(); - SetButtons(); +void +mgMainMenu::AddMenu (mgMenu * m) +{ + Menus.push_back (m); + m->setosd (this); + m->Display (0); +} - SetTitle( m_media->getActiveFilterTitle().c_str() ); - std::vector<mgFilter*> *filter_list = m_media->getActiveFilters(); - - int i=0; - for( std::vector<mgFilter*>::iterator iter = filter_list->begin(); - iter != filter_list->end(); - iter ++ ) - { - mgDebug( 1, "Filter %d/%dint filter %s='%s'", - i, filter_list->size(), - (*iter)->getName(), - (*iter)->getStrVal().c_str()); - switch( (*iter)->getType() ) - { - case mgFilter::INT: - { - mgFilterInt *fi = (mgFilterInt *) (*iter); - - Add( new cMenuEditIntItem( fi->getName(), - &(fi->m_intval), - fi->getMin(), fi->getMax() ) ); - } break; - case mgFilter::STRING: - { - mgFilterString *fs = (mgFilterString *) (*iter); - - // BUG: This might be buggy as fs->getAllowedChars() may become - // invalid while VDR is still trying to access it - Add( new cMenuEditStrItem( fs->getName(), fs->m_strval, - fs->getMaxLength(), - fs->getAllowedChars().c_str() ) ); - - } break; - case mgFilter::BOOL: - { - mgFilterBool *fb = (mgFilterBool *) (*iter); - Add( new cMenuEditBoolItem( fb->getName(), &( fb->m_bval), - fb->getTrueString().c_str(), - fb->getFalseString().c_str() ) ); - } break; - case mgFilter::CHOICE: - { - mgFilterChoice *fc = (mgFilterChoice *) (*iter); - std::vector<std::string> choices = fc->getChoices(); - - char **choices_str = new (char *)[ choices.size() ]; - - int j = 0; - for( std::vector<std::string>::iterator iter = choices.begin(); - iter != choices.end(); - iter ++, j ++ ) - { - // BUG: Is this a big memory leak!? When to delete and who? - // RaK: zweiter Iterator war "i" richtig: "j" - // choices_str[j] = strndup( choices[i].c_str(), 128 ); - choices_str[j] = strndup( choices[j].c_str(), 128 ); - } - - Add( new cMenuEditStraItem( fc->getName(), &( fc->m_selval ), - choices.size(), choices_str ) ); - - // delete all choices_str elements! - // delete[] choices_str; // ??? - - } break; - default: - case mgFilter::UNDEF: - { - } break; - } - i++; - } - - Display(); +eOSState +mgSubmenu::Process (eKeys key) +{ + return osUnknown; } -void mgMainMenu::DisplayFilterSelector() + +void +mgTreeViewSelector::BuildOsd () { - // show available filters, load on OK? + InitOsd (tr ("Tree View Selection")); + AddAction(actSearchCollItem); + AddAction(actSearchArtistAlbumTitle); + AddAction(actSearchArtistTitle); + AddAction(actSearchAlbumTitle); + AddAction(actSearchGenreYearTitle); + AddAction(actSearchGenreArtistAlbumTitle); } -void mgMainMenu::Play( mgPlaylist *plist, unsigned first ) +void +mgMainMenu::DisplayGoto (unsigned int select) { - MGLOG( "mgMainMenu::Play" ); - cControl *control = cControl::Control(); - - if( control && typeid(*control) == typeid(mgPlayerControl) ) - { // is there a running MP3 player? - static_cast<mgPlayerControl*>(control)->NewPlaylist(plist, first); // signal the running player to load the new playlist - } - else + if (select >= 0) { - cControl::Launch( new mgPlayerControl(plist, first) ); + SetCurrent (Get (select)); + RefreshCurrent (); } + Display (); + DisplayMenu()->SetTabs(25); +} + + +void +mgMenu::Display (const unsigned int position) +{ + BuildOsd (); + osd ()->DisplayGoto (position); } + |