diff options
-rw-r--r-- | HISTORY | 4 | ||||
-rw-r--r-- | i18n.c | 136 | ||||
-rw-r--r-- | mg_content.c | 91 | ||||
-rw-r--r-- | mg_content.h | 14 | ||||
-rw-r--r-- | mg_mysql.c | 3 | ||||
-rw-r--r-- | mg_order.c | 117 | ||||
-rw-r--r-- | mg_order.h | 33 | ||||
-rw-r--r-- | mg_selection.c | 286 | ||||
-rw-r--r-- | mg_selection.h | 54 | ||||
-rw-r--r-- | mg_sync.c | 52 | ||||
-rw-r--r-- | mg_tools.c | 21 | ||||
-rw-r--r-- | mg_tools.h | 2 | ||||
-rw-r--r-- | mg_valmap.c | 2 | ||||
-rw-r--r-- | muggle.c | 7 | ||||
-rw-r--r-- | muggle.h | 1 | ||||
-rwxr-xr-x | mugglei.c | 2 | ||||
-rw-r--r-- | vdr_actions.c | 72 | ||||
-rw-r--r-- | vdr_actions.h | 4 | ||||
-rw-r--r-- | vdr_decoder.c | 10 | ||||
-rw-r--r-- | vdr_menu.c | 24 | ||||
-rw-r--r-- | vdr_player.c | 7 |
21 files changed, 590 insertions, 352 deletions
@@ -177,3 +177,7 @@ XXXXXXXXXX: Version 0.0.8-ALPHA sequence, up to now not giving any argument to muggle called the server on localhost using TCP, now it uses the faster sockets. You can still request TCP by using -h 127.0.0.1 + +NEXT VERSION +- killing vdr could still result in an empty muggle.state. Fixed. +- new sorting fields: Only by the first character of artist or title @@ -455,6 +455,23 @@ const tI18nPhrase Phrases[] = "", // TODO }, { + "ArtistABC", + "InterpretABC", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "InterprèteABC", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { "Play all", "Spiele alles", "", // TODO @@ -1016,6 +1033,23 @@ const tI18nPhrase Phrases[] = "", // TODO }, { + "TitleABC", + "TitelABC", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "TitreABC", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { "Track", "Track", "", // TODO @@ -1117,5 +1151,107 @@ const tI18nPhrase Phrases[] = "", // TODO "", // TODO }, + { + "Synchronize database", + "Datenbank synchronisieren", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "Synchroniser la base des données", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { + "Create database %s?", + "Datenbank %s anlegen?", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "Générer la base des données %s?", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { + "Synchronize database with track files?", + "Datenbank mit Trackdateien synchronisieren?", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "Synchroniser la base des données avec les tracks?", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { + "Import tracks?", + "Tracks importieren?", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "Importer les tracks?", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { + "Imported %d tracks...", + "%d Tracks importiert...", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "%d tracks importés...", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, + { + "Import done:imported %d tracks", + "Import fertig:%d Tracks importiert", + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "Import finis:%d tracks importés...", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + "", // TODO + }, {NULL} }; diff --git a/mg_content.c b/mg_content.c index 5e8ecf6..74b9fce 100644 --- a/mg_content.c +++ b/mg_content.c @@ -12,42 +12,47 @@ #include <stdio.h> #include "i18n.h" #include "mg_selection.h" -#include "vdr_setup.h" +#include "mg_setup.h" #include "mg_tools.h" -string -mgContentItem::getKeyId(mgKeyTypes kt) -{ - if (m_id<0) - return ""; - switch (kt) { - case keyGenres: - case keyGenre1: - case keyGenre2: - case keyGenre3: return m_genre1_id; - default: return getKeyValue(kt); - } -} - -string -mgContentItem::getKeyValue(mgKeyTypes kt) -{ - if (m_id<0) - return ""; - switch (kt) { - case keyGenres: - case keyGenre1: - case keyGenre2: - case keyGenre3: return getGenre(); - case keyArtist: return getArtist(); - case keyAlbum: return getAlbum(); - case keyYear: return string(ltos(getYear())); - case keyDecade: return string(ltos(int((getYear() % 100) / 10) * 10)); - case keyTitle: return getTitle(); - case keyTrack: return getTitle(); - default: return ""; +mgSelItem* +mgContentItem::getKeyItem(mgKeyTypes kt) +{ + string val; + string id; + if (m_trackid>=0) + { + switch (kt) { + case keyGenres: + case keyGenre1: + case keyGenre2: + case keyGenre3: val = getGenre();id=m_genre1_id;break; + case keyArtist: val = id = getArtist();break; + case keyArtistABC: val = id = getArtist()[0];break; + case keyAlbum: val = id = getAlbum();break; + case keyYear: val = id = string(ltos(getYear()));break; + case keyDecade: val = id = string(ltos(int((getYear() % 100) / 10) * 10));break; + case keyTitle: val = id = getTitle();break; + case keyTitleABC: val = id = getTitle()[0];break; + case keyTrack: val = id = getTitle();break; + case keyLanguage: val = getLanguage();id=m_language_id ; break; + case keyRating: val = id = getRating();break; + case keyFolder1: + case keyFolder2: + case keyFolder3: + case keyFolder4: + { + char *folders[4]; + char *fbuf=SeparateFolders(m_mp3file.c_str(),folders,4); + val = id = folders[int(kt)-int(keyFolder1)]; + free(fbuf); + break; + } + default: return new mgSelItem; + } } + return new mgSelItem(val,id); } @@ -66,6 +71,11 @@ string mgContentItem::getGenre () const } +string mgContentItem::getLanguage() const +{ + return m_language; +} + string mgContentItem::getBitrate () const { return m_bitrate; @@ -115,12 +125,12 @@ int mgContentItem::getChannels () const mgContentItem::mgContentItem () { - m_id = -1; + m_trackid = -1; } mgContentItem::mgContentItem (const mgContentItem* c) { - m_id = c->m_id; + m_trackid = c->m_trackid; m_title = c->m_title; m_mp3file = c->m_mp3file; m_artist = c->m_artist; @@ -129,6 +139,8 @@ mgContentItem::mgContentItem (const mgContentItem* c) m_genre2_id = c->m_genre2_id; m_genre1 = c->m_genre1; m_genre2 = c->m_genre2; + m_language = c->m_language; + m_language_id = c->m_language_id; m_bitrate = c->m_bitrate; m_year = c->m_year; m_rating = c->m_rating; @@ -139,7 +151,7 @@ mgContentItem::mgContentItem (const mgContentItem* c) static char *mg_readline(FILE *f) { - static char buffer[MAXPARSEBUFFER]; + static char buffer[10000]; if (fgets(buffer, sizeof(buffer), f) > 0) { int l = strlen(buffer) - 1; if (l >= 0 && buffer[l] == '\n') @@ -186,7 +198,7 @@ mgContentItem::getSourceFile(bool AbsolutePath) const mgContentItem::mgContentItem (const mgSelection* sel,const MYSQL_ROW row) { - m_id = atol (row[0]); + m_trackid = atol (row[0]); if (row[1]) m_title = row[1]; else @@ -241,5 +253,12 @@ mgContentItem::mgContentItem (const mgSelection* sel,const MYSQL_ROW row) m_channels = atol (row[12]); else m_channels = 0; + if (row[13]) + { + m_language_id = row[13]; + m_language = sel->value(keyLanguage,row[13]); + } + else + m_language_id = "NULL"; }; diff --git a/mg_content.h b/mg_content.h index 313b54b..ee97745 100644 --- a/mg_content.h +++ b/mg_content.h @@ -34,8 +34,7 @@ class mgContentItem public: mgContentItem (); - string getKeyValue(mgKeyTypes kt); - string getKeyId(mgKeyTypes kt); + mgSelItem* getKeyItem(mgKeyTypes kt); //! \brief copy constructor mgContentItem(const mgContentItem* c); @@ -43,9 +42,9 @@ class mgContentItem //! \brief construct an item from an SQL row mgContentItem (const mgSelection* sel, const MYSQL_ROW row); //! \brief returns track id - long getId () const + long getTrackid () const { - return m_id; + return m_trackid; } //! \brief returns title @@ -69,6 +68,9 @@ class mgContentItem //! \brief returns the name of genre string getGenre () const; +//! \brief returns the name of the language + string getLanguage () const; + //! \brief returns the bitrate string getBitrate () const; @@ -91,7 +93,7 @@ class mgContentItem int getChannels () const; private: - long m_id; + long m_trackid; string m_title; string m_mp3file; string m_artist; @@ -101,6 +103,8 @@ class mgContentItem string m_genre1; string m_genre2; string m_bitrate; + string m_language_id; + string m_language; int m_year; int m_rating; int m_duration; @@ -541,8 +541,7 @@ mgmySql::Connect () { if (!Connected()) if (!createtime) - mgWarning("Database %s not found:%s", - the_setup.DbName,mysql_error(m_db)); + mgWarning(mysql_error(m_db)); } } if (!needGenre2_set && Connected()) @@ -4,7 +4,7 @@ #include <stdio.h> #include <assert.h> -const char * EMPTY = "XNICHTGESETZTX"; +mgSelItem zeroitem; bool iskeyGenre(mgKeyTypes kt) { @@ -100,26 +100,81 @@ ltos (long l) return s.str (); } +mgSelItem::mgSelItem() +{ + m_valid=false; + m_count=0; +} + +mgSelItem::mgSelItem(string v,string i,unsigned int c) +{ + set(v,i,c); +} + +void +mgSelItem::set(string v,string i,unsigned int c) +{ + m_valid=true; + m_value=v; + m_id=i; + m_count=c; +} + +void +mgSelItem::operator=(const mgSelItem& from) +{ + m_valid=from.m_valid; + m_value=from.m_value; + m_id=from.m_id; + m_count=from.m_count; +} + +void +mgSelItem::operator=(const mgSelItem* from) +{ + m_valid=from->m_valid; + m_value=from->m_value; + m_id=from->m_id; + m_count=from->m_count; +} + +bool +mgSelItem::operator==(const mgSelItem& other) const +{ + return m_value == other.m_value + && m_id == other.m_id; +} + class mgKeyNormal : public mgKey { public: mgKeyNormal(const mgKeyNormal& k); - mgKeyNormal(const mgKeyTypes kt, string table, string field); + mgKeyNormal(const mgKeyTypes kt, string table, string field); virtual mgParts Parts(mgmySql &db,bool orderby=false) const; string value() const; string id() const; - void set(string value,string id); + bool valid() const; + void set(mgSelItem& item); + mgSelItem& get(); mgKeyTypes Type() const { return m_kt; } virtual string expr() const { return m_table + "." + m_field; } virtual string table() const { return m_table; } protected: string IdClause(mgmySql &db,string what,string::size_type start=0,string::size_type len=string::npos) const; void AddIdClause(mgmySql &db,mgParts &result,string what) const; - string m_id; + mgSelItem m_item; string m_field; private: mgKeyTypes m_kt; string m_table; - string m_value; +}; + +class mgKeyABC : public mgKeyNormal { + public: + mgKeyABC(const mgKeyNormal& k) : mgKeyNormal(k) {} + mgKeyABC(const mgKeyTypes kt, string table, string field) : mgKeyNormal(kt,table,field) {} + virtual string expr() const { return "substring("+mgKeyNormal::expr()+",1,1)"; } + protected: + //void AddIdClause(mgmySql &db,mgParts &result,string what) const; }; class mgKeyDate : public mgKeyNormal { @@ -246,7 +301,7 @@ mgKeyGenres::GenreClauses(mgmySql &db,bool orderby) const g2.push_back("substring(tracks.genre2,1,"+ltos(genrelevel())+")=genre.id"); } - if (id() != EMPTY) + if (valid()) { unsigned int len=genrelevel(); if (len==4) len=0; @@ -317,13 +372,19 @@ class mgKeyDecade : public mgKeyNormal { string mgKeyNormal::id() const { - return m_id; + return m_item.id(); +} + +bool +mgKeyNormal::valid() const +{ + return m_item.valid(); } string mgKeyNormal::value() const { - return m_value; + return m_item.value(); } @@ -332,7 +393,7 @@ mgKeyNormal::mgKeyNormal(const mgKeyNormal& k) m_kt = k.m_kt; m_table = k.m_table; m_field = k.m_field; - m_id = k.m_id; + m_item = k.m_item; } mgKeyNormal::mgKeyNormal(const mgKeyTypes kt, string table, string field) @@ -340,14 +401,18 @@ mgKeyNormal::mgKeyNormal(const mgKeyTypes kt, string table, string field) m_kt = kt; m_table = table; m_field = field; - m_id = EMPTY; } void -mgKeyNormal::set(string value, string id) +mgKeyNormal::set(mgSelItem& item) { - m_value = value; - m_id = id; + m_item=item; +} + +mgSelItem& +mgKeyNormal::get() +{ + return m_item; } mgParts::mgParts() @@ -393,7 +458,7 @@ mgKeyNormal::IdClause(mgmySql &db,string what,string::size_type start,string::si void mgKeyNormal::AddIdClause(mgmySql &db,mgParts &result,string what) const { - if (id() != EMPTY) + if (valid()) result.clauses.push_back(IdClause(db,what)); } @@ -406,7 +471,7 @@ mgKeyTrack::Parts(mgmySql &db,bool orderby) const if (orderby) { // if you change tracks.title, please also - // change mgContentItem::getKeyValue() + // change mgContentItem::getKeyItem() result.fields.push_back("tracks.title"); result.orders.push_back("tracks.tracknb"); } @@ -656,7 +721,7 @@ mgOrder::InitFrom(const mgOrder &from) for (unsigned int i = 0; i < from.size();i++) { mgKey *k = ktGenerate(from.getKeyType(i)); - k->set(from.getKeyValue(i),from.getKeyId(i)); + k->set(from.getKeyItem(i)); Keys.push_back(k); } m_orderByCount=from.m_orderByCount; @@ -737,18 +802,11 @@ mgOrder::getKeyType(unsigned int idx) const return Keys[idx]->Type(); } -string -mgOrder::getKeyValue(unsigned int idx) const -{ - assert(idx<Keys.size()); - return Keys[idx]->value(); -} - -string -mgOrder::getKeyId(unsigned int idx) const +mgSelItem& +mgOrder::getKeyItem(unsigned int idx) const { assert(idx<Keys.size()); - return Keys[idx]->id(); + return Keys[idx]->get(); } void @@ -861,8 +919,7 @@ mgOrder::Parts(mgmySql &db,unsigned int level,bool orderby) const if (kn) { mgKeyTypes knt = kn->Type(); - if (iskeyGenre(knt) - && knt>kt && kn->id()!=EMPTY) + if (iskeyGenre(knt) && knt>kt && !kn->id().empty()) goto next; } } @@ -962,7 +1019,9 @@ ktGenerate(const mgKeyTypes kt) case keyFolder3:result = new mgKeyFolder3;break; case keyFolder4:result = new mgKeyFolder4;break; case keyArtist: result = new mgKeyNormal(kt,"tracks","artist");break; + case keyArtistABC: result = new mgKeyABC(kt,"tracks","artist");break; case keyTitle: result = new mgKeyNormal(kt,"tracks","title");break; + case keyTitleABC: result = new mgKeyABC(kt,"tracks","title");break; case keyTrack: result = new mgKeyTrack;break; case keyDecade: result = new mgKeyDecade;break; case keyAlbum: result = new mgKeyAlbum;break; @@ -992,7 +1051,9 @@ ktName(const mgKeyTypes kt) case keyFolder3: result = "Folder3";break; case keyFolder4: result = "Folder4";break; case keyArtist: result = "Artist";break; + case keyArtistABC: result = "ArtistABC";break; case keyTitle: result = "Title";break; + case keyTitleABC: result = "TitleABC";break; case keyTrack: result = "Track";break; case keyDecade: result = "Decade";break; case keyAlbum: result = "Album";break; @@ -15,8 +15,6 @@ typedef list<string> strlist; strlist& operator+=(strlist&a, strlist b); -extern const char * EMPTY; - //! \brief adds string n to string s, using string sep to separate them string& addsep (string & s, string sep, string n); @@ -39,6 +37,8 @@ enum mgKeyTypes { keyFolder4, keyCreated, keyModified, + keyArtistABC, + keyTitleABC, keyCollection, keyCollectionItem, }; @@ -75,14 +75,36 @@ private: mgParts ConnectToTracks(string table) const; }; +class mgSelItem +{ + public: + mgSelItem(); + mgSelItem(string v,string i,unsigned int c=0); + void set(string v,string i,unsigned int c=0); + void operator=(const mgSelItem& from); + void operator=(const mgSelItem* from); + bool operator==(const mgSelItem& other) const; + string value() const { return m_value; } + string id() const { return m_id; } + unsigned int count() const { return m_count; } + bool valid() const { return m_valid; } + private: + bool m_valid; + string m_value; + string m_id; + unsigned int m_count; +}; + class mgKey { public: virtual ~mgKey() {}; virtual mgParts Parts(mgmySql &db,bool orderby=false) const = 0; virtual string id() const = 0; + virtual bool valid() const = 0; virtual string value () const = 0; //!\brief translate field into user friendly string - virtual void set(string value, string id) = 0; + virtual void set(mgSelItem& item) = 0; + virtual mgSelItem& get() = 0; virtual mgKeyTypes Type() const = 0; virtual string map_idfield() const { return ""; } virtual string map_valuefield() const { return ""; } @@ -150,8 +172,7 @@ public: void clear(); mgKey* Key(unsigned int idx) const; mgKeyTypes getKeyType(unsigned int idx) const; - string getKeyValue(unsigned int idx) const; - string getKeyId(unsigned int idx) const; + mgSelItem& getKeyItem(unsigned int idx) const; void setKeys(vector<mgKeyTypes> kt); string Name(); void setOrderByCount(bool orderbycount) { m_orderByCount = orderbycount;} @@ -166,4 +187,6 @@ private: bool operator==(const mgOrder& a,const mgOrder&b); //! \brief compares only the order, not the current key values +extern mgSelItem zeroitem; + #endif // _MG_SQL_H diff --git a/mg_selection.c b/mg_selection.c index 3656aa2..464bddb 100644 --- a/mg_selection.c +++ b/mg_selection.c @@ -20,7 +20,7 @@ #include "mg_selection.h" #include "vdr_setup.h" #include "mg_tools.h" -#include "mg_sync.h" +#include "mg_thread_sync.h" #include <mpegfile.h> #include <flacfile.h> @@ -53,43 +53,90 @@ comma (string & s, string n) } -static string zerostring; +void +mgSelection::mgSelItems::clear() +{ + m_items.clear(); +} bool -mgSelection::mgSelStrings::operator==(const mgSelStrings&x) const +mgSelection::mgSelItems::operator==(const mgSelItems&x) const { - bool result = strings.size()==x.strings.size(); + bool result = m_items.size()==x.m_items.size(); if (result) for (unsigned int i=0;i<size();i++) - result &= strings[i]==x.strings[i]; + result &= m_items[i]==x.m_items[i]; return result; } size_t -mgSelection::mgSelStrings::size() const +mgSelection::mgSelItems::size() const { if (!m_sel) - mgError("mgSelStrings: m_sel is 0"); + mgError("mgSelItems: m_sel is 0"); m_sel->refreshValues(); - return strings.size(); + return m_items.size(); } -string& -mgSelection::mgSelStrings::operator[](unsigned int idx) +mgSelItem& +mgSelection::mgSelItems::operator[](unsigned int idx) { if (!m_sel) - mgError("mgSelStrings: m_sel is 0"); + mgError("mgSelItems: m_sel is 0"); m_sel->refreshValues(); - if (idx>=strings.size()) return zerostring; - return strings[idx]; + if (idx>=size()) return zeroitem; + return m_items[idx]; } void -mgSelection::mgSelStrings::setOwner(mgSelection* sel) +mgSelection::mgSelItems::setOwner(mgSelection* sel) { m_sel = sel; } +unsigned int +mgSelection::mgSelItems::valindex (const string v) const +{ + return index(v,true); +} + +unsigned int +mgSelection::mgSelItems::idindex (const string i) const +{ + return index(i,true); +} + +unsigned int +mgSelection::mgSelItems::index (const string s,bool val,bool second_try) const +{ + if (!m_sel) + mgError("mgSelItems::index(%s): m_sel is 0",s.c_str()); + m_sel->refreshValues(); + for (unsigned int i = 0; i < size (); i++) + { + if (val) + { + if (m_items[i].value() == s) + return i; + } + else + { + if (m_items[i].id() == s) + return i; + } + } + // nochmal mit neuen Werten: + if (second_try) { + esyslog("index: Gibt es nicht:%s",s.c_str()); + return 0; + } + else + { + m_sel->clearCache(); + return index(s,val,true); + } +} + void mgSelection::clearCache() const { @@ -100,19 +147,13 @@ mgSelection::clearCache() const string mgSelection::getCurrentValue() { - return values[gotoPosition()]; -} - -string -mgSelection::getKeyValue(const unsigned int level) const -{ - return order.getKeyValue(level); + return items[gotoPosition()].value(); } -unsigned int -mgSelection::getKeyIndex(const unsigned int level) const +mgSelItem& +mgSelection::getKeyItem(const unsigned int level) const { - return valindex(getKeyValue(level)); + return order.getKeyItem(level); } @@ -153,11 +194,11 @@ mgSelection::Shuffle() const { case SM_NONE: { - long id = m_tracks[getTrackPosition()].getId (); + long trackid = m_tracks[getTrackPosition()].getTrackid (); m_current_tracks = ""; // force a reload tracksize = getNumTracks(); // getNumTracks also reloads for (unsigned int i = 0; i < tracksize; i++) - if (m_tracks[i].getId () == id) + if (m_tracks[i].getTrackid () == trackid) { setTrackPosition(i); break; @@ -233,7 +274,7 @@ mgSelection::AddToCollection (const string Name) long first = atol(m_db.get_col0(sql).c_str()) - tracksize + 1; // replace the place holder trackid by the correct value: - m_db.exec_sql("UPDATE playlistitem SET trackid="+ltos(m_tracks[tracksize-1].getId())+ + m_db.exec_sql("UPDATE playlistitem SET trackid="+ltos(m_tracks[tracksize-1].getTrackid())+ " WHERE playlist="+listid+" AND trackid="+trackid); // insert all other tracks: @@ -242,7 +283,7 @@ mgSelection::AddToCollection (const string Name) for (unsigned int i = 0; i < tracksize-1; i++) { string item = "(" + listid + "," + ltos (first + i) + "," + - ltos (m_tracks[i].getId ()) + ")"; + ltos (m_tracks[i].getTrackid ()) + ")"; comma(sql, item); if ((i%100)==99) { @@ -315,7 +356,7 @@ string mgSelection::exportM3U () mgContentItem& t = m_tracks[i]; fprintf (listfile, "#EXTINF:%d,%s\n", t.getDuration (), t.getTitle ().c_str ()); - fprintf (listfile, "#MUGGLE:%ld\n", t.getId()); + fprintf (listfile, "#MUGGLE:%ld\n", t.getTrackid()); fprintf (listfile, "%s\n", t.getSourceFile (false).c_str ()); } fclose (listfile); @@ -328,7 +369,7 @@ mgSelection::empty() if (m_level>= order.size ()-1) return ( getNumTracks () == 0); else - return ( values.size () == 0); + return ( items.size () == 0); } void @@ -362,11 +403,11 @@ mgSelection::gotoPosition () return gotoTrackPosition(); else { - unsigned int valsize = values.size(); - if (valsize==0) + unsigned int itemsize = items.size(); + if (itemsize==0) m_position = 0; - else if (m_position >= valsize) - m_position = valsize -1; + else if (m_position >= itemsize) + m_position = itemsize -1; return m_position; } } @@ -448,7 +489,7 @@ string mgSelection::getListname () const { list<string> st; for (unsigned int i = 0; i < m_level; i++) - st.push_back(order.getKeyValue(i)); + st.push_back(order.getKeyItem(i).value()); st.unique(); string result=""; for (list < string >::iterator it = st.begin (); it != st.end (); ++it) @@ -502,6 +543,7 @@ mgSelection::tracks () const p.fields.push_back("tracks.length"); p.fields.push_back("tracks.samplerate"); p.fields.push_back("tracks.channels"); + p.fields.push_back("tracks.lang"); p.tables.push_back("tracks"); p.tables.push_back("album"); for (unsigned int i = m_level; i<order.size(); i++) @@ -537,7 +579,7 @@ void mgSelection::InitSelection() { else m_loop_mode = LM_NONE; clearCache(); - values.setOwner(this); + items.setOwner(this); } @@ -591,9 +633,12 @@ mgSelection::InitFrom(mgValmap& nv) m_db.Create(); if (Interface->Confirm(tr("Import tracks?"))) { - mgSync *s = new mgSync; - s->Sync(argv); - delete s; + mgThreadSync *s = mgThreadSync::get_instance(); + if (s) + { + extern char *sync_args[]; + s->Sync(sync_args,the_setup.DeleteStaleReferences); + } } } free(b); @@ -644,49 +689,11 @@ mgSelection::ordersize () } unsigned int -mgSelection::valindex (const string val,const bool second_try) const -{ - for (unsigned int i = 0; i < values.size (); i++) - { - if (values[i] == val) - return i; - } - // nochmal mit neuen Werten: - clearCache(); - refreshValues(); - if (second_try) { - esyslog("valindex: Gibt es nicht:%s",val.c_str()); - return 0; - } - else - return valindex(val,true); -} - -unsigned int mgSelection::valcount (string value) { - assert(m_counts.size()==values.size()); - return m_counts[valindex(value)]; + return items[items.valindex(value)].count(); } -unsigned int -mgSelection::idindex (const string id,const bool second_try) const -{ - for (unsigned int i = 0; i < m_ids.size (); i++) - if (m_ids[i] == id) - return i; - // nochmal mit neuen Werten: - clearCache(); - refreshValues(); - if (second_try) { - mgWarning("idindex: Gibt es nicht:%s",id.c_str()); - return 0; - } - else - return idindex(id,true); -} - - void mgSelection::refreshValues () const { @@ -697,9 +704,7 @@ mgSelection::refreshValues () const { mgParts p = order.Parts(m_db,m_level); m_current_values = p.sql_select(); - values.strings.clear (); - m_ids.clear (); - m_counts.clear(); + items.clear (); MYSQL_RES *rows = m_db.exec_sql (m_current_values); if (rows) { @@ -709,22 +714,17 @@ mgSelection::refreshValues () const { if (!row[0]) continue; string r0 = row[0]; - if (r0=="NULL") // there is a genre NULL! + if (!strcmp(row[0],"NULL")) // there is a genre NULL! continue; + mgSelItem n; if (num_fields==3) { if (!row[1]) continue; - string r1 = row[1]; - values.strings.push_back (r0); - m_ids.push_back (r1); - m_counts.push_back(atol(row[2])); + n.set(row[0],row[1],atol(row[2])); } else - { - values.strings.push_back (value(order.Key(m_level),r0)); - m_ids.push_back (r0); - m_counts.push_back(atol(row[1])); - } + n.set(value(order.Key(m_level),r0),r0,atol(row[1])); + items.push_back(n); } mysql_free_result (rows); } @@ -734,7 +734,7 @@ mgSelection::refreshValues () const unsigned int mgSelection::count () const { - return values.size (); + return items.size (); } @@ -746,18 +746,17 @@ bool mgSelection::enter (unsigned int position) return false; setPosition (position); position = gotoPosition(); // reload adjusted position - if (values.size()==0) + if (items.size()==0) return false; - string value = values[position]; - string id = m_ids[position]; - mgSelStrings prev; - if (m_fall_through && values.size()<10) - prev=values; + mgSelItem item = items[position]; + mgSelItems prev; + if (m_fall_through && items.size()<10) + prev=items; while (1) { if (m_level >= order.size () - 1) return false; - order[m_level++]->set (value,id); + order[m_level++]->set (item); clearCache(); if (m_level >= order.size()) mgError("mgSelection::enter(%u): level greater than order.size() %u", @@ -766,13 +765,12 @@ bool mgSelection::enter (unsigned int position) refreshValues(); if (count()==0) break; - value = values[0]; - id = m_ids[0]; + item=items[0]; if (!m_fall_through) break; if (m_level==order.size()-1) break; - if (count () > 1 && !(prev==values)) + if (count () > 1 && !(prev==items)) break; } return true; @@ -785,9 +783,9 @@ bool mgSelection::select (unsigned int position) { if (getNumTracks () <= position) return false; - order[m_level]->set (values[position],m_ids[position]); + order[m_level]->set (items[position]); m_level++; - m_trackid = m_tracks[position].getId (); + m_trackid = m_tracks[position].getTrackid (); clearCache(); return true; @@ -808,28 +806,28 @@ mgSelection::leave () if (m_level == order.size ()) { m_level--; - prevvalue=order.getKeyValue(m_level); - order[m_level]->set("",EMPTY); + prevvalue=order.getKeyItem(m_level).value(); + order[m_level]->set(zeroitem); m_trackid = -1; clearCache(); setPosition(prevvalue); return true; } - mgSelStrings prev; - if (m_fall_through && values.size()<10) - prev=values; + mgSelItems prev; + if (m_fall_through && items.size()<10) + prev=items; while (1) { if (m_level < 1) return false; - if (m_level<order.size()) order[m_level]->set ("",EMPTY); + if (m_level<order.size()) order[m_level]->set (zeroitem); m_level--; - prevvalue=order.getKeyValue(m_level); - if (m_level<order.size()) order[m_level]->set ("",EMPTY); + prevvalue=order.getKeyItem(m_level).value(); + if (m_level<order.size()) order[m_level]->set (zeroitem); clearCache(); if (!m_fall_through) break; - if (count () > 1 && !(prev==values)) + if (count () > 1 && !(prev==items)) break; } setPosition(prevvalue); @@ -841,7 +839,7 @@ mgSelection::leave_all () { m_level=0; for (unsigned int i=0;i<ordersize();i++) - order[i]->set ("",EMPTY); + order[i]->set (zeroitem); clearCache(); } @@ -849,67 +847,59 @@ void mgSelection::selectfrom(mgOrder& oldorder,mgContentItem* o) { leave_all(); - string selval; - string selid; + mgSelItem selitem; assert(m_level==0); for (unsigned int idx = 0; idx < ordersize(); idx++) { - selval = EMPTY; - selid = EMPTY; + selitem = zeroitem; mgKeyTypes new_kt = getKeyType(idx); for (unsigned int i=0;i<oldorder.size();i++) { mgKeyTypes old_kt = oldorder.getKeyType(i); if (old_kt==new_kt) - { - selval = oldorder.getKeyValue(i); - selid = oldorder.getKeyId(i); - } + selitem = oldorder.getKeyItem(i); else if (old_kt>new_kt && iskeyGenre(old_kt) && iskeyGenre(new_kt)) { - selid = id(new_kt,value(new_kt,oldorder.getKeyId(i))); - selval= value(new_kt,selid); + string selid=id(new_kt,value(new_kt,oldorder.getKeyItem(i).id())); + selitem=mgSelItem (value(new_kt,selid),selid); } - if (selid!=EMPTY) break; - } - if (selid==EMPTY && o && o->getId()>=0) - { - selval = o->getKeyValue(new_kt); - selid = o->getKeyId(new_kt); + if (selitem.valid()) break; } - if (selid==EMPTY) + if (!selitem.valid() && o && o->getTrackid()>=0) + selitem = o->getKeyItem(new_kt); + if (!selitem.valid()) break; if (m_level<ordersize()-1) { - order[m_level++]->set (selval, selid); + order[m_level++]->set (selitem); } else { - setPosition(selval); + setPosition(selitem.value()); return; } } if (m_level>0) { m_level--; - selval = order.getKeyValue(m_level); - order[m_level]->set("",EMPTY); - setPosition(selval); - order[m_level+1]->set("",EMPTY); + selitem = order.getKeyItem(m_level); + order[m_level]->set(zeroitem); + setPosition(selitem.value()); + order[m_level+1]->set(zeroitem); } assert(m_level<ordersize()); } string -mgSelection::value(mgKeyTypes kt, string id) const +mgSelection::value(mgKeyTypes kt, string idstr) const { if (loadvalues (kt)) { map<string,string>& valmap = map_values[kt]; map<string,string>::iterator it; - it = valmap.find(id); + it = valmap.find(idstr); if (it!=valmap.end()) { string r = it->second; @@ -918,17 +908,17 @@ mgSelection::value(mgKeyTypes kt, string id) const } map_ids[kt].clear(); loadvalues(kt); - it = valmap.find(id); + it = valmap.find(idstr); if (it!=valmap.end()) - return valmap[id]; + return valmap[idstr]; } - return id; + return idstr; } string -mgSelection::value(mgKey* k, string id) const +mgSelection::value(mgKey* k, string idstr) const { - return value(k->Type(),id); + return value(k->Type(),idstr); } string @@ -996,7 +986,7 @@ mgSelection::inCollection(const string Name) const if (order.getKeyType(1) != keyCollectionItem) mgError("inCollection: key[1] is not keyCollectionItem"); if (!Name.empty()) - result &= (order.getKeyValue(0) == Name); + result &= (order.getKeyItem(0).value() == Name); return result; } @@ -1011,12 +1001,12 @@ void mgSelection::DumpState(mgValmap& nv) const if (i<m_level) { char *n; asprintf(&n,"order.Keys.%u.Position",i); - nv.put(n,getKeyValue(i)); + nv.put(n,getKeyItem(i).value()); free(n); } } nv.put("TrackId",m_trackid); - nv.put("Position",values[m_position]); + nv.put("Position",items[m_position].value()); if (m_level>=order.size()-1) nv.put("TrackPosition",getTrackPosition()); } @@ -1027,7 +1017,7 @@ mgSelection::UsedKeyValues() map <mgKeyTypes, string> result; for (unsigned int idx = 0 ; idx < level() ; idx++) { - result[order.getKeyType(idx)] = order.getKeyValue(idx); + result[order.getKeyType(idx)] = order.getKeyItem(idx).value(); } if (level() < order.size()-1) { diff --git a/mg_selection.h b/mg_selection.h index af897e0..f9fa455 100644 --- a/mg_selection.h +++ b/mg_selection.h @@ -25,7 +25,6 @@ using namespace std; typedef vector<string> strvector; - /*! * \brief the only interface to the database. * Some member functions are declared const although they can modify the inner state of mgSelection. @@ -35,18 +34,24 @@ typedef vector<string> strvector; */ class mgSelection { - private: - class mgSelStrings + class mgSelItems { - friend class mgSelection; - private: - strvector strings; - mgSelection* m_sel; - void setOwner(mgSelection* sel); public: - string& operator[](unsigned int idx); - bool operator==(const mgSelStrings&x) const; + mgSelItems() { m_sel=0; } + void setOwner(mgSelection* sel); + mgSelItem& operator[](unsigned int idx); + string& id(unsigned int); + unsigned int count(unsigned int); + bool operator==(const mgSelItems&x) const; size_t size() const; + unsigned int valindex (const string v) const; + unsigned int idindex (const string i) const; + void clear(); + void push_back(mgSelItem& item) { m_items.push_back(item); } + private: + unsigned int index (const string s,bool val,bool second_try=false) const; + vector<mgSelItem> m_items; + mgSelection* m_sel; }; public: //! \brief defines an order to be used @@ -99,20 +104,19 @@ class mgSelection //! \brief the normal destructor ~mgSelection (); -/*! \brief represents all values for the current level. The result - * is cached in values, subsequent accesses to values only incur a - * small overhead for building the SQL WHERE command. The values will +/*! \brief represents all items for the current level. The result + * is cached, subsequent accesses to values only incur a + * small overhead for building the SQL WHERE command. The items will * be reloaded when the SQL command changes */ - mutable mgSelStrings values; + mutable mgSelItems items; /*! \brief returns the name of a key */ mgKeyTypes getKeyType (const unsigned int level) const; //! \brief return the current value of this key - string getKeyValue (const unsigned int level) const; - unsigned int getKeyIndex(const unsigned int level) const; + mgSelItem& getKeyItem (const unsigned int level) const; /*! \brief returns the current item from the value() list */ @@ -177,7 +181,7 @@ class mgSelection */ bool enter (const string value) { - return enter (valindex (value)); + return enter (items.valindex (value)); } /*! \brief like enter but if we are at the leaf level simply select @@ -185,12 +189,12 @@ class mgSelection */ bool select (const string value) { - return select (valindex(value)); + return select (items.valindex(value)); } - bool selectid (const string id) + bool selectid (const string i) { - return select(idindex(id)); + return select(items.idindex(i)); } void selectfrom(mgOrder& oldorder,mgContentItem* o); @@ -317,7 +321,7 @@ class mgSelection */ void setPosition (const string value) { - setPosition (valindex (value)); + setPosition (items.valindex (value)); } /*! \brief go to a position in the track list @@ -408,8 +412,8 @@ class mgSelection { return (m_current_values=="" && m_current_tracks==""); } - string value(mgKeyTypes kt, string id) const; - string value(mgKey* k, string id) const; + string value(mgKeyTypes kt, string idstr) const; + string value(mgKey* k, string idstr) const; string value(mgKey* k) const; string id(mgKeyTypes kt, string val) const; string id(mgKey* k, string val) const; @@ -426,8 +430,6 @@ class mgSelection mutable string m_current_tracks; //! \brief be careful when accessing this, see mgSelection::tracks() mutable vector < mgContentItem > m_tracks; - mutable strvector m_ids; - mutable vector < unsigned int > m_counts; //! \brief initializes maps for id/value mapping in both direction bool loadvalues (mgKeyTypes kt) const; bool m_fall_through; @@ -451,8 +453,6 @@ class mgSelection * entries and the wrong tracks might be played. */ string sql_values (); - unsigned int valindex (const string val,const bool second_try=false) const; - unsigned int idindex (const string val,const bool second_try=false) const; string ListFilename (); string m_Directory; void loadgenres (); @@ -223,45 +223,13 @@ mgSync::GetFileInfo(const char *filename) channels = ap->channels(); //tracks.channels if (m_db.HasFolderFields()) { - char *path = strdup(filename); - char *folder1=""; - char *folder2=""; - char *folder3=""; - char *folder4=""; - char *p=path; - char *slash; - slash=strchr(p,'/'); - if (slash) - { - folder1=p; - *slash=0; - p=slash+1; - slash=strchr(p,'/'); - if (slash) - { - folder2=p; - *slash=0; - p=slash+1; - slash=strchr(p,'/'); - if (slash) - { - folder3=p; - *slash=0; - p=slash+1; - slash=strchr(p,'/'); - if (slash) - { - folder4=p; - *slash=0; - } - } - } - } - sql_Cstring(folder1,c_folder1); - sql_Cstring(folder2,c_folder2); - sql_Cstring(folder3,c_folder3); - sql_Cstring(folder4,c_folder4); - free(path); + char *folders[4]; + char *fbuf=SeparateFolders(filename,folders,4); + sql_Cstring(folders[0],c_folder1); + sql_Cstring(folders[1],c_folder2); + sql_Cstring(folders[2],c_folder3); + sql_Cstring(folders[3],c_folder4); + free(fbuf); } return true; } @@ -296,8 +264,10 @@ mgSync::SyncFile(const char *filename) void mgSync::Sync(char * const * path_argv, bool delete_missing) { + extern void showimportcount(unsigned int,bool final=false); if (!m_db.Connected()) return; + unsigned int count=0; m_db.CreateFolderFields(); chdir(the_setup.ToplevelDir); @@ -320,14 +290,12 @@ mgSync::Sync(char * const * path_argv, bool delete_missing) SyncFile(ftsent->fts_path); count++; if (count%1000==0) - { - extern void showimportcount(unsigned int); showimportcount(count); - } } } fts_close(fts); } + showimportcount(count,true); } void @@ -126,3 +126,24 @@ std::string trim(std::string const& source, char const* delims ) { result.erase(); return result; } + + +char * +SeparateFolders(const char *filename, char * folders[],unsigned int fcount) +{ + for (unsigned int i=0;i<fcount;i++) + folders[i]=""; + char *fbuf=strdup(filename); + char *slash=fbuf-1; + for (unsigned int i=0;i<fcount;i++) + { + char *p=slash+1; + slash=strchr(p,'/'); + if (!slash) + break; + folders[i]=p; + *slash=0; + } + return fbuf; +} + @@ -84,4 +84,6 @@ class mgLog std::string trim(std::string const& source, char const* delims = " \t\r\n"); +char *SeparateFolders(const char *filename, char * folders[],unsigned int fcount); + #endif /* _MUGGLE_TOOLS_H */ diff --git a/mg_valmap.c b/mg_valmap.c index f5d8e02..2361b00 100644 --- a/mg_valmap.c +++ b/mg_valmap.c @@ -37,7 +37,7 @@ void mgValmap::Write(FILE *f) { } void mgValmap::put(const char* name, const string value) { - if (value.empty() || value==EMPTY) return; + if (value.empty()) return; (*this)[string(name)] = value; } @@ -47,7 +47,6 @@ mgMuggle::MainMenuEntry (void) mgMuggle::mgMuggle (void) { - main = NULL; // defaults for database arguments the_setup.DbHost = 0; the_setup.DbSocket = 0; @@ -65,12 +64,10 @@ mgMuggle::mgMuggle (void) #endif } -#if VDRVERSNUM >= 0321 void mgMuggle::Stop (void) { - if (main) main->SaveState(); free(the_setup.DbHost); free(the_setup.DbName); free(the_setup.DbUser); @@ -78,7 +75,6 @@ mgMuggle::Stop (void) free(the_setup.ToplevelDir); } -#endif const char * mgMuggle::CommandLineHelp (void) @@ -248,8 +244,7 @@ cOsdObject * mgMuggle::MainMenuAction (void) { // Perform the action when selected from the main VDR menu. - main = new mgMainMenu (); - return main; + return new mgMainMenu (); } @@ -69,6 +69,5 @@ class mgMuggle:public cPlugin virtual bool SetupParse (const char *Name, const char *Value); - mgMainMenu *main; }; #endif @@ -45,7 +45,7 @@ void showmessage(const char *msg,int duration) { } -void showimportcount(unsigned int count) +void showimportcount(unsigned int count,bool final=false) { } diff --git a/vdr_actions.c b/vdr_actions.c index 1c12689..6f58da7 100644 --- a/vdr_actions.c +++ b/vdr_actions.c @@ -74,7 +74,7 @@ class mgEntry : public mgOsdItem public: void Notify(); bool Enabled(mgActions on) { return IsEntry(on);} - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); eOSState Process(eKeys key); void Execute(); eOSState Back(); @@ -243,15 +243,15 @@ class mgCommand : public mgOsdItem class mgActOrder : public mgOsdItem { public: - const char* MenuName(const unsigned int idx,const string value); + const char* MenuName(const unsigned int idx,const mgSelItem& item); virtual eOSState Process(eKeys key); void Execute(); }; const char* -mgActOrder::MenuName(const unsigned int idx,const string value) +mgActOrder::MenuName(const unsigned int idx,const mgSelItem& item) { - return strdup(value.c_str()); + return strdup(item.value().c_str()); } eOSState @@ -328,28 +328,28 @@ mgEntry::Notify() const char * -mgEntry::MenuName(const unsigned int idx,const string value) +mgEntry::MenuName(const unsigned int idx,const mgSelItem& item) { char *result; char ct[20]; ct[0]=0; - unsigned int selcount = selection()->valcount(value); + unsigned int selcount = item.count(); if (selection()->level()<selection()->ordersize()-1 || selcount>1) sprintf(ct," [%u]",selcount); // when changing this, also change mgDoCollEntry::getTarget() if (selection()->isCollectionlist()) { - if (value == osd()->default_collection) - asprintf(&result,"-> %s%s",value.c_str(),ct); + if (item.value() == osd()->default_collection) + asprintf(&result,"-> %s%s",item.value().c_str(),ct); else - asprintf(&result," %s%s",value.c_str(),ct); + asprintf(&result," %s%s",item.value().c_str(),ct); } else if (selection()->inCollection()) - asprintf(&result,"%4d %s%s",idx,value.c_str(),ct); + asprintf(&result,"%4d %s%s",idx,item.value().c_str(),ct); else if (selection()->isLanguagelist()) - asprintf(&result,"%s%s",dgettext("iso_639",value.c_str()),ct); + asprintf(&result,"%s%s",dgettext("iso_639",item.value().c_str()),ct); else - asprintf(&result,"%s%s",value.c_str(),ct); + asprintf(&result,"%s%s",item.value().c_str(),ct); return result; } @@ -541,7 +541,7 @@ class mgChooseOrder : public mgCommand virtual eOSState Process(eKeys key); void Execute (); const char *ButtonName() { return tr("Order"); } - const char *MenuName(const unsigned int idx,const string value) + const char *MenuName(const unsigned int idx,const mgSelItem& item) { return strdup(tr("Select an order")); } }; @@ -688,7 +688,7 @@ class mgCmdSync : public mgOsdItem }; -static char *sync_args[] = +char *sync_args[] = { ".", 0 @@ -698,7 +698,7 @@ eOSState mgCmdSync::ProcessKey(eKeys key) { if (key==kOk) - if (Interface->Confirm(tr("Synchronize database with track flles?"))) + if (Interface->Confirm(tr("Synchronize database with track files?"))) { Execute(); return osContinue; @@ -726,10 +726,10 @@ class mgSetDefaultCollection:public mgCommand { return tr ("Default"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; -const char * mgSetDefaultCollection::MenuName(const unsigned int idx,const string value) +const char * mgSetDefaultCollection::MenuName(const unsigned int idx,const mgSelItem& item) { char *b; asprintf (&b, tr("Set default to collection '%s'"), @@ -788,13 +788,13 @@ class mgAddAllToCollection:public mgCommand { { return tr ("Add"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); protected: void ExecuteMove(); }; const char * -mgAddAllToCollection::MenuName (const unsigned int idx,const string value) +mgAddAllToCollection::MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr("Add all to a collection")); } @@ -833,11 +833,11 @@ class mgAddAllToDefaultCollection:public mgCommand { { return tr ("Add"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; const char * -mgAddAllToDefaultCollection::MenuName (const unsigned int idx,const string value) +mgAddAllToDefaultCollection::MenuName (const unsigned int idx,const mgSelItem& item) { char *b; asprintf (&b, tr ("Add all to '%s'"), @@ -883,7 +883,7 @@ class mgAddThisToCollection:public mgAddAllToCollection bool Enabled(mgActions on); void Execute (); const char *ButtonName (); - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; @@ -910,7 +910,7 @@ mgAddThisToCollection::Enabled(mgActions on) } const char * -mgAddThisToCollection::MenuName (const unsigned int idx,const string value) +mgAddThisToCollection::MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr("Add to a collection")); } @@ -922,7 +922,7 @@ class mgAddThisToDefaultCollection:public mgAddAllToDefaultCollection bool Enabled(mgActions on); void Execute (); const char *ButtonName (); - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; @@ -952,7 +952,7 @@ mgAddThisToDefaultCollection::Enabled(mgActions on) } const char * -mgAddThisToDefaultCollection::MenuName (const unsigned int idx,const string value) +mgAddThisToDefaultCollection::MenuName (const unsigned int idx,const mgSelItem& item) { char *b; asprintf (&b, tr ("Add to '%s'"), osd ()->default_collection.c_str ()); @@ -968,7 +968,7 @@ class mgRemoveAllFromCollection:public mgCommand { return tr ("Remove"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; void @@ -983,7 +983,7 @@ mgRemoveAllFromCollection::Execute () } const char * -mgRemoveAllFromCollection::MenuName (const unsigned int idx,const string value) +mgRemoveAllFromCollection::MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr("Remove all from a collection")); } @@ -997,11 +997,11 @@ class mgClearCollection : public mgCommand { return tr ("Clear"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; const char * -mgClearCollection::MenuName (const unsigned int idx,const string value) +mgClearCollection::MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr("Clear the collection")); } @@ -1032,7 +1032,7 @@ class mgRemoveThisFromCollection:public mgRemoveAllFromCollection { return tr ("Remove"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; @@ -1048,7 +1048,7 @@ mgRemoveThisFromCollection::Execute () const char * -mgRemoveThisFromCollection::MenuName (const unsigned int idx,const string value) +mgRemoveThisFromCollection::MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr("Remove from a collection")); } @@ -1110,7 +1110,7 @@ class mgCreateCollection : public mgCreate mgCreateCollection(); bool Enabled(mgActions on); void Execute (); - const char *MenuName (const unsigned int idx=0,const string value=""); + const char *MenuName (const unsigned int idx=0,const mgSelItem& item=zeroitem); }; mgCreateCollection::mgCreateCollection() : mgCreate(MenuName()) @@ -1118,7 +1118,7 @@ mgCreateCollection::mgCreateCollection() : mgCreate(MenuName()) } const char* -mgCreateCollection::MenuName(const unsigned int idx,const string value) +mgCreateCollection::MenuName(const unsigned int idx,const mgSelItem& item) { return strdup(tr ("Create collection")); } @@ -1162,7 +1162,7 @@ class mgDeleteCollection:public mgCommand { return tr ("Delete"); } - const char *MenuName (const unsigned int idx,const string value); + const char *MenuName (const unsigned int idx,const mgSelItem& item); }; bool @@ -1178,7 +1178,7 @@ mgDeleteCollection::Enabled(mgActions on) return result; } -const char* mgDeleteCollection::MenuName(const unsigned int idx,const string value) +const char* mgDeleteCollection::MenuName(const unsigned int idx,const mgSelItem& item) { return strdup(tr("Delete the collection")); } @@ -1210,7 +1210,7 @@ class mgExportTracklist:public mgCommand { return tr ("Export"); } - const char *MenuName (const unsigned int idx,const string value) + const char *MenuName (const unsigned int idx,const mgSelItem& item) { return strdup(tr ("Export track list")); } diff --git a/vdr_actions.h b/vdr_actions.h index 29713f1..72f9caf 100644 --- a/vdr_actions.h +++ b/vdr_actions.h @@ -18,6 +18,8 @@ #include <osd.h> #include <plugin.h> +#include "mg_order.h" + using namespace std; class mgSelection; @@ -107,7 +109,7 @@ class mgAction * to execute this. The returned C string must be freeable at any time. * \param value a string that can be used for building the menu name. */ - virtual const char *MenuName (const unsigned int idx=0,const string value="") + virtual const char *MenuName (const unsigned int idx=0,const mgSelItem& item=zeroitem) { return strdup(ButtonName()); } diff --git a/vdr_decoder.c b/vdr_decoder.c index 5ac9706..0d7bbf1 100644 --- a/vdr_decoder.c +++ b/vdr_decoder.c @@ -203,9 +203,15 @@ bool mgDecoder::tryLock (void) if (!m_locked && !m_playing) { - lock (); + m_locked++; + + m_locklock.Unlock (); // don't hold the "locklock" when locking + // "lock", may cause a deadlock + m_lock.Lock (); + m_urgentLock = false; res = true; } - m_locklock.Unlock (); + else + m_locklock.Unlock (); return res; } @@ -144,8 +144,7 @@ mgMainMenu::CollectionEntered(string name) { if (!UsingCollection) return false; if (selection()->level()==0) return false; - string collection = trim(selection ()->getKeyValue(0)); - return (collection == name); + return trim(selection ()->getKeyItem(0).value()) == name; } @@ -496,11 +495,11 @@ mgMainMenu::AddOrderActions(mgMenu* m) void mgMenu::AddSelectionItems (mgSelection *sel,mgActions act) { - for (unsigned int i = 0; i < sel->values.size (); i++) + for (unsigned int i = 0; i < sel->items.size (); i++) { mgAction *a = GenerateAction(act, actEntry); if (!a) continue; - const char *name = a->MenuName(i+1,sel->values[i]); + const char *name = a->MenuName(i+1,sel->items[i]); // add incremental filter here #if 0 // example: @@ -869,12 +868,21 @@ showmessage(const char * msg,int duration) } void -showimportcount(unsigned int count) +showimportcount(unsigned int count,bool final=false) { char b[100]; - sprintf(b,tr("Imported %d tracks..."),count); - assert(strlen(b)<100); - showmessage(b,1); + if (final) + { + sprintf(b,tr("Import done:Imported %d tracks"),count); + assert(strlen(b)<100); + showmessage(b,1); + } + else + { + sprintf(b,tr("Imported %d tracks..."),count); + assert(strlen(b)<100); + showmessage(b); + } } void diff --git a/vdr_player.c b/vdr_player.c index 3b3035f..01e7337 100644 --- a/vdr_player.c +++ b/vdr_player.c @@ -682,10 +682,11 @@ mgPCMPlayer::Action (void) break; } } + eState curr_m_state=m_state; // avoid helgrind warning Unlock (); - if ((m_rframe || m_state == msWait) && m_pframe) + if ((m_rframe || curr_m_state == msWait) && m_pframe) { // Wait for output to become ready DevicePoll (poll, 500); @@ -826,18 +827,18 @@ mgPCMPlayer::Play (void) { MGLOG ("mgPCMPlayer::Play"); - Lock (); if (m_playmode != pmPlay && m_current) { + Lock (); if (m_playmode == pmStopped) { m_state = msStart; } // DevicePlay(); // TODO? Commented out in original code, too SetPlayMode (pmPlay); + Unlock (); } - Unlock (); } |