summaryrefslogtreecommitdiff
path: root/mg_order.c
diff options
context:
space:
mode:
Diffstat (limited to 'mg_order.c')
-rw-r--r--mg_order.c284
1 files changed, 224 insertions, 60 deletions
diff --git a/mg_order.c b/mg_order.c
index 525469c..4c44f28 100644
--- a/mg_order.c
+++ b/mg_order.c
@@ -4,7 +4,10 @@
#include <stdio.h>
#include <assert.h>
-mgSelItem zeroitem;
+static map <mgKeyTypes, map<string,string> > map_values;
+static map <mgKeyTypes, map<string,string> > map_ids;
+
+mgKeyMaps KeyMaps;
bool iskeyGenre(mgKeyTypes kt)
{
@@ -100,50 +103,6 @@ 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:
@@ -153,15 +112,15 @@ class mgKeyNormal : public mgKey {
string value() const;
string id() const;
bool valid() const;
- void set(mgSelItem& item);
- mgSelItem& get();
+ void set(mgListItem& item);
+ mgListItem& 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;
- mgSelItem m_item;
+ mgListItem m_item;
string m_field;
private:
mgKeyTypes m_kt;
@@ -253,10 +212,10 @@ class mgKeyGenres : public mgKeyNormal {
mgKeyGenres() : mgKeyNormal(keyGenres,"tracks","genre1") {};
mgKeyGenres(mgKeyTypes kt) : mgKeyNormal(kt,"tracks","genre1") {};
mgParts Parts(mgmySql &db,bool orderby=false) const;
+ protected:
string map_idfield() const { return "id"; }
string map_valuefield() const { return "genre"; }
- string map_valuetable() const { return "genre"; }
- protected:
+ string map_table() const { return "genre"; }
virtual unsigned int genrelevel() const { return 4; }
private:
string GenreClauses(mgmySql &db,bool orderby) const;
@@ -344,18 +303,20 @@ class mgKeyLanguage : public mgKeyNormal {
public:
mgKeyLanguage() : mgKeyNormal(keyLanguage,"tracks","lang") {};
mgParts Parts(mgmySql &db,bool orderby=false) const;
+ protected:
string map_idfield() const { return "id"; }
string map_valuefield() const { return "language"; }
- string map_valuetable() const { return "language"; }
+ string map_table() const { return "language"; }
};
class mgKeyCollection: public mgKeyNormal {
public:
mgKeyCollection() : mgKeyNormal(keyCollection,"playlist","id") {};
mgParts Parts(mgmySql &db,bool orderby=false) const;
+ protected:
string map_idfield() const { return "id"; }
string map_valuefield() const { return "title"; }
- string map_valuetable() const { return "playlist"; }
+ string map_table() const { return "playlist"; }
};
class mgKeyCollectionItem : public mgKeyNormal {
public:
@@ -404,12 +365,12 @@ mgKeyNormal::mgKeyNormal(const mgKeyTypes kt, string table, string field)
}
void
-mgKeyNormal::set(mgSelItem& item)
+mgKeyNormal::set(mgListItem& item)
{
m_item=item;
}
-mgSelItem&
+mgListItem&
mgKeyNormal::get()
{
return m_item;
@@ -802,7 +763,7 @@ mgOrder::getKeyType(unsigned int idx) const
return Keys[idx]->Type();
}
-mgSelItem&
+mgListItem&
mgOrder::getKeyItem(unsigned int idx) const
{
assert(idx<Keys.size());
@@ -931,6 +892,43 @@ next:
return result;
}
+string
+mgOrder::GetContent(mgmySql &db,unsigned int level,vector < mgContentItem > &content) const
+{
+ mgParts p = Parts(db,level);
+ p.fields.clear();
+ p.fields.push_back("tracks.id");
+ p.fields.push_back("tracks.title");
+ p.fields.push_back("tracks.mp3file");
+ p.fields.push_back("tracks.artist");
+ p.fields.push_back("album.title");
+ p.fields.push_back("tracks.genre1");
+ p.fields.push_back("tracks.genre2");
+ p.fields.push_back("tracks.bitrate");
+ p.fields.push_back("tracks.year");
+ p.fields.push_back("tracks.rating");
+ 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 = level; i<size(); i++)
+ p += Key(i)->Parts(db,true);
+ string result = p.sql_select(false);
+ content.clear ();
+ MYSQL_RES *rows = db.exec_sql (result);
+ if (rows)
+ {
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row (rows)) != 0)
+ content.push_back (mgContentItem (row));
+ mysql_free_result (rows);
+ }
+ return result;
+}
+
+
//! \brief right now thread locking should not be needed here
mgReferences::mgReferences()
{
@@ -1078,13 +1076,179 @@ ktValue(const char * name)
return mgKeyTypes(0);
}
+static vector<int> keycounts;
+
+unsigned int
+mgOrder::keycount(mgKeyTypes kt) const
+{
+ if (keycounts.size()==0)
+ {
+ for (unsigned int ki=int(mgKeyTypesLow);ki<=int(mgKeyTypesHigh);ki++)
+ {
+ keycounts.push_back(-1);
+ }
+ }
+ int& count = keycounts[int(kt-mgKeyTypesLow)];
+ if (count==-1)
+ {
+ mgKey* k = ktGenerate(kt);
+ struct mgmySql db;
+ if (k->Enabled(db))
+ count = db.exec_count(k->Parts(db,true).sql_count());
+ else
+ count = 0;
+ delete k;
+ }
+ return count;
+}
+
+
+bool
+mgOrder::UsedBefore(const mgKeyTypes kt,unsigned int level) const
+{
+ if (level>=size())
+ level = size() -1;
+ for (unsigned int lx = 0; lx < level; lx++)
+ if (getKeyType(lx)==kt)
+ return true;
+ return false;
+}
-vector<const char*>
-ktNames()
+vector <const char *>
+mgOrder::Choices(unsigned int level, unsigned int *current) const
{
- static vector<const char*> result;
- for (unsigned int i = int(mgKeyTypesLow); i <= int(mgKeyTypesHigh); i++)
- result.push_back(ktName(mgKeyTypes(i)));
+ vector<const char*> result;
+ if (level>size())
+ {
+ *current = 0;
+ return result;
+ }
+ for (unsigned int ki=int(mgKeyTypesLow);ki<=int(mgKeyTypesHigh);ki++)
+ {
+ mgKeyTypes kt = mgKeyTypes(ki);
+ if (kt==getKeyType(level))
+ {
+ *current = result.size();
+ result.push_back(ktName(kt));
+ continue;
+ }
+ if (UsedBefore(kt,level))
+ continue;
+ if (kt==keyDecade && UsedBefore(keyYear,level))
+ continue;
+ if (kt==keyGenre1)
+ {
+ if (UsedBefore(keyGenre2,level)) continue;
+ if (UsedBefore(keyGenre3,level)) continue;
+ if (UsedBefore(keyGenres,level)) continue;
+ }
+ if (kt==keyGenre2)
+ {
+ if (UsedBefore(keyGenre3,level)) continue;
+ if (UsedBefore(keyGenres,level)) continue;
+ }
+ if (kt==keyGenre3)
+ {
+ if (UsedBefore(keyGenres,level)) continue;
+ }
+ if (kt==keyFolder1)
+ {
+ if (UsedBefore(keyFolder2,level)) continue;
+ if (UsedBefore(keyFolder3,level)) continue;
+ if (UsedBefore(keyFolder4,level)) continue;
+ }
+ if (kt==keyFolder2)
+ {
+ if (UsedBefore(keyFolder3,level)) continue;
+ if (UsedBefore(keyFolder4,level)) continue;
+ }
+ if (kt==keyFolder3)
+ {
+ if (UsedBefore(keyFolder4,level)) continue;
+ }
+ if (kt==keyCollection || kt==keyCollectionItem)
+ result.push_back(ktName(kt));
+ else if (keycount(kt)>1)
+ result.push_back(ktName(kt));
+ }
return result;
}
+bool
+mgKey::LoadMap() const
+{
+ map<string,string>& idmap = map_ids[Type()];
+ if (map_idfield().empty())
+ {
+ return false;
+ }
+ mgmySql db;
+ map<string,string>& valmap = map_values[Type()];
+ char *b;
+ asprintf(&b,"select %s,%s from %s;",map_idfield().c_str(),map_valuefield().c_str(),map_table().c_str());
+ MYSQL_RES *rows = db.exec_sql (string(b));
+ free(b);
+ if (rows)
+ {
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row (rows)) != 0)
+ {
+ if (row[0] && row[1])
+ {
+ valmap[row[0]] = row[1];
+ idmap[row[1]] = row[0];
+ }
+ }
+ mysql_free_result (rows);
+ }
+ return true;
+}
+
+bool
+mgKeyMaps::loadvalues (mgKeyTypes kt) const
+{
+ if (map_ids.count(kt)>0)
+ return true;
+ mgKey* k = ktGenerate(kt);
+ bool result = k->LoadMap();
+ delete k;
+ return result;
+}
+
+string
+mgKeyMaps::value(mgKeyTypes kt, string idstr) const
+{
+ if (loadvalues (kt))
+ {
+ map<string,string>& valmap = map_values[kt];
+ map<string,string>::iterator it;
+ it = valmap.find(idstr);
+ if (it!=valmap.end())
+ {
+ string r = it->second;
+ if (!r.empty())
+ return r;
+ }
+ map_ids[kt].clear();
+ loadvalues(kt);
+ it = valmap.find(idstr);
+ if (it!=valmap.end())
+ return valmap[idstr];
+ }
+ return idstr;
+}
+
+string
+mgKeyMaps::id(mgKeyTypes kt, string valstr) const
+{
+ if (loadvalues (kt))
+ {
+ map<string,string>& idmap = map_ids[kt];
+ string v = idmap[valstr];
+ if (kt==keyGenre1) v=v.substr(0,1);
+ if (kt==keyGenre2) v=v.substr(0,2);
+ if (kt==keyGenre3) v=v.substr(0,3);
+ return v;
+ }
+ return valstr;
+}