diff options
author | wr61 <wr61@e10066b5-e1e2-0310-b819-94efdf66514b> | 2005-02-28 01:30:25 +0000 |
---|---|---|
committer | wr61 <wr61@e10066b5-e1e2-0310-b819-94efdf66514b> | 2005-02-28 01:30:25 +0000 |
commit | 9e6139533024afca59ef5873d333f0af93ccbc17 (patch) | |
tree | 3629b26c8ab1415ac11d7324384ad805e7be281e | |
parent | c3d04581101a47717cda7b9d810646100a2934bd (diff) | |
download | vdr-plugin-muggle-9e6139533024afca59ef5873d333f0af93ccbc17.tar.gz vdr-plugin-muggle-9e6139533024afca59ef5873d333f0af93ccbc17.tar.bz2 |
mgSelection::Sync, not yet very well tested
git-svn-id: https://vdr-muggle.svn.sourceforge.net/svnroot/vdr-muggle/branches/0.1.3-wr@518 e10066b5-e1e2-0310-b819-94efdf66514b
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | mg_actions.c | 15 | ||||
-rw-r--r-- | mg_actions.h | 2 | ||||
-rw-r--r-- | mg_database.c | 130 | ||||
-rw-r--r-- | mg_database.h | 83 | ||||
-rw-r--r-- | mg_mysql.c | 61 | ||||
-rw-r--r-- | mg_mysql.h | 6 | ||||
-rw-r--r-- | mg_order.c | 10 | ||||
-rw-r--r-- | mg_order.h | 1 | ||||
-rw-r--r-- | mg_selection.c | 234 | ||||
-rw-r--r-- | mg_selection.h | 17 | ||||
-rw-r--r-- | mg_setup.c | 2 | ||||
-rw-r--r-- | muggle.c | 1 | ||||
-rwxr-xr-x | mugglei.c | 741 | ||||
-rw-r--r-- | vdr_menu.c | 3 |
15 files changed, 366 insertions, 942 deletions
@@ -96,7 +96,7 @@ libvdr-$(PLUGIN).so: $(OBJS) $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@ @cp $@ $(LIBDIR)/$@.$(VDRVERSION) -mugglei: mg_tools.o mugglei.o +mugglei: mg_tools.o mugglei.o mg_order.o mg_selection.o mg_mysql.o mg_valmap.o mg_content.o mg_setup.o i18n.o $(CXX) $(CXXFLAGS) $^ $(MILIBS) -o $@ install: diff --git a/mg_actions.c b/mg_actions.c index 9adeb9a..2934ee4 100644 --- a/mg_actions.c +++ b/mg_actions.c @@ -677,6 +677,18 @@ mgToggleSelection::Execute () osd()->newposition = selection ()->gotoPosition (); } +class mgSync : public mgCommand +{ + public: + void Execute(); + const char *ButtonName() { return tr("Synchronize"); } +}; + +void +mgSync::Execute() +{ + selection()->Sync("."); +} //! \brief sets the default collection selection class mgSetDefaultCollection:public mgCommand @@ -1216,6 +1228,7 @@ mgAction::Type() if (t == typeid(mgCreateOrder)) return actCreateOrder; if (t == typeid(mgDeleteOrder)) return actDeleteOrder; if (t == typeid(mgEditOrder)) return actEditOrder; + if (t == typeid(mgSync)) return actSync; if (t == typeid(mgExternal0)) return actExternal0; if (t == typeid(mgExternal1)) return actExternal1; if (t == typeid(mgExternal2)) return actExternal2; @@ -1277,7 +1290,7 @@ actGenerate(const mgActions action) case actSetButton: result = new mgSetButton;break; case actShowList: result = new mgShowList;break; case actShowCommands: result = new mgShowCommands;break; - case actUnused5: break; + case actSync: result = new mgSync;break; case actSetDefaultCollection: result = new mgSetDefaultCollection;break; case actOrder: result = new mgActOrder;break; case actUnused6: break; diff --git a/mg_actions.h b/mg_actions.h index e60fcdf..ac12586 100644 --- a/mg_actions.h +++ b/mg_actions.h @@ -50,7 +50,7 @@ enum mgActions { actShowCommands, actCreateOrder, actDeleteOrder, - actUnused5, //!< order by Genre1/Artist/Album/Title + actSync, actAddAllToDefaultCollection, actAddThisToDefaultCollection, actSetDefaultCollection, diff --git a/mg_database.c b/mg_database.c deleted file mode 100644 index dff7b0f..0000000 --- a/mg_database.c +++ /dev/null @@ -1,130 +0,0 @@ -/*! \file mg_database.c - * \brief A capsule around MySql database access - * - * \version $Revision: 1.2 $ - * \date $Date$ - * \author Ralf Klueber, Lars von Wedel, Andreas Kellner - * \author file owner: $Author$ - */ - -#include "mg_database.h" -#include "mg_tools.h" - -#include <stdarg.h> - -static const int MAX_QUERY_BUFLEN = 2048; - -static char *db_cmds[] = { - "use GiantDisc;" - "DROP DATABASE IF EXISTS GiantDisc; CREATE DATABASE GiantDisc;", - "grant all privileges on GiantDisc.* to vdr@localhost;", - "drop table if exists album; CREATE TABLE album ( artist varchar(255) default NULL, title varchar(255) default NULL, cddbid varchar(20) NOT NULL default '', coverimg varchar(255) default NULL, covertxt mediumtext, modified date default NULL, genre varchar(10) default NULL, PRIMARY KEY (cddbid), KEY artist (artist(10)), KEY title (title(10)), KEY genre (genre), KEY modified (modified)) TYPE=MyISAM;", - "drop table if exists genre; CREATE TABLE genre (id varchar(10) NOT NULL default '', id3genre smallint(6) default NULL, genre varchar(255) default NULL, freq int(11) default NULL, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists language; CREATE TABLE language (id varchar(4) NOT NULL default '', language varchar(40) default NULL, freq int(11) default NULL, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists musictype; CREATE TABLE musictype (musictype varchar(40) default NULL, id tinyint(3) unsigned NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists player;CREATE TABLE player ( ipaddr varchar(255) NOT NULL default '', uichannel varchar(255) NOT NULL default '', logtarget int(11) default NULL, cdripper varchar(255) default NULL, mp3encoder varchar(255) default NULL, cdromdev varchar(255) default NULL, cdrwdev varchar(255) default NULL, id int(11) NOT NULL default '0', PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists playerstate;CREATE TABLE playerstate ( playerid int(11) NOT NULL default '0', playertype int(11) NOT NULL default '0', snddevice varchar(255) default NULL, playerapp varchar(255) default NULL, playerparams varchar(255) default NULL, ptlogger varchar(255) default NULL, currtracknb int(11) default NULL, state varchar(4) default NULL, shufflepar varchar(255) default NULL, shufflestat varchar(255) default NULL, pauseframe int(11) default NULL, framesplayed int(11) default NULL, framestotal int(11) default NULL, anchortime bigint(20) default NULL, PRIMARY KEY (playerid,playertype)) TYPE=HEAP;", - "drop table if exists playlist;CREATE TABLE playlist ( title varchar(255) default NULL, author varchar(255) default NULL, note varchar(255) default NULL, created timestamp(8) NOT NULL, id int(10) unsigned NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists playlistitem;CREATE TABLE playlistitem ( playlist int(11) NOT NULL default '0', tracknumber mediumint(9) NOT NULL default '0', trackid int(11) default NULL, PRIMARY KEY (playlist,tracknumber)) TYPE=MyISAM;", - "drop table if exists playlog;CREATE TABLE playlog ( trackid int(11) default NULL, played date default NULL, id tinyint(3) unsigned NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists recordingitem;CREATE TABLE recordingitem ( trackid int(11) default NULL, recdate date default NULL, rectime time default NULL, reclength int(11) default NULL, enddate date default NULL, endtime time default NULL, repeat varchar(10) default NULL, initcmd varchar(255) default NULL, parameters varchar(255) default NULL, atqjob int(11) default NULL, id int(11) NOT NULL default '0', PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists source; CREATE TABLE source ( source varchar(40) default NULL, id tinyint(3) unsigned NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;", - "drop table if exists tracklistitem;CREATE TABLE tracklistitem ( playerid int(11) NOT NULL default '0', listtype smallint(6) NOT NULL default '0', tracknb int(11) NOT NULL default '0', trackid int(11) NOT NULL default '0', PRIMARY KEY (playerid,listtype,tracknb)) TYPE=MyISAM;", - "drop table if exists tracks;CREATE TABLE tracks ( artist varchar(255) default NULL, title varchar(255) default NULL, genre1 varchar(10) default NULL, genre2 varchar(10) default NULL, year smallint(5) unsigned default NULL, lang varchar(4) default NULL, type tinyint(3) unsigned default NULL, rating tinyint(3) unsigned default NULL, length smallint(5) unsigned default NULL, source tinyint(3) unsigned default NULL, sourceid varchar(20) default NULL, tracknb tinyint(3) unsigned default NULL, mp3file varchar(255) default NULL, condition tinyint(3) unsigned default NULL, voladjust smallint(6) default '0', lengthfrm mediumint(9) default '0', startfrm mediumint(9) default '0', bpm smallint(6) default '0', lyrics mediumtext, bitrate varchar(10) default NULL, created date default NULL, modified date default NULL, backup tinyint(3) unsigned default NULL, samplerate int(7) unsigned default NULL, channels tinyint(3) unsigned default NULL, id int(11) NOT NULL auto_increment, PRIMARY KEY (id), KEY title (title(10)), KEY mp3file (mp3file(10)), KEY genre1 (genre1), KEY genre2 (genre2), KEY year (year), KEY lang (lang), KEY type (type), KEY rating (rating), KEY sourceid (sourceid), KEY artist (artist(10))) TYPE=MyISAM;" -}; - - -mgDB::mgDB() -{ -} - -mgDB::mgDB(std::string host, std::string name, - std::string user, std::string pass, - int port) -{ -} - -mgDB::~mgDB() -{ -} - -MYSQL_RES * -mgDB::exec_sql(std::string query) -{ - if (query.empty()) - return 0; - mgDebug( 3, "exec_sql(%X,%s)", &m_dbase, query.c_str() ); - if (mysql_query (&m_dbase, (query + ';').c_str ())) - { - mgError("SQL Error in %s: %s",query.c_str(),mysql_error (&m_dbase)); - std::cout << "ERROR in " << query << ":" << mysql_error(&m_dbase) << std::endl; - return 0; - } - return mysql_store_result(&m_dbase); -} - -void mgDB::initialize() -{ - // create database - exec_sql( std::string(db_cmds[1]) ); - exec_sql( std::string(db_cmds[0]) ); - exec_sql( std::string(db_cmds[2]) ); - - // create tables - int len = sizeof( db_cmds ) / sizeof( char* ); - for( int i=3; i < len; i ++ ) - { - exec_sql( std::string( db_cmds[i] ) ); - } -} - -MYSQL mgDB::getDBHandle() -{ - - return m_dbase; -} - -std::string mgDB::escape_string( MYSQL *db, std::string s ) -{ - char *escbuf = (char *) malloc( 2*s.size() + 1 ); - - mysql_real_escape_string( db, escbuf, s.c_str(), s.size() ); - - std::string r = std::string( escbuf ); - free( escbuf ); - - return r; -} - -MYSQL_RES* mgDB::read_query( const char *fmt, ...) -{ - char querybuf[MAX_QUERY_BUFLEN]; - va_list ap; - va_start( ap, fmt ); - vsnprintf( querybuf, MAX_QUERY_BUFLEN-1, fmt, ap ); - - if( mysql_query( &m_dbase, querybuf) ) - { - mgError( "SQL error in MUGGLE:\n%s\n", querybuf ); - } - - MYSQL_RES *result = mysql_store_result( &m_dbase ); - - va_end(ap); - return result; -} - -void mgDB::write_query( const char *fmt, ... ) -{ - char querybuf[MAX_QUERY_BUFLEN]; - va_list ap; - va_start( ap, fmt ); - vsnprintf( querybuf, MAX_QUERY_BUFLEN-1, fmt, ap ); - - if( mysql_query( &m_dbase, querybuf ) ) - { - mgError( "SQL error in MUGGLE:\n%s\n", querybuf ); - } - - va_end(ap); -} diff --git a/mg_database.h b/mg_database.h deleted file mode 100644 index de159aa..0000000 --- a/mg_database.h +++ /dev/null @@ -1,83 +0,0 @@ -/*! - * \file mg_database.h - * \brief A capsule around MySql database access - * - * \version $Revision: 1.2 $ - * \date $Date$ - * \author Ralf Klueber, Lars von Wedel, Andreas Kellner - * \author Responsible author: $Author$ - */ - -#ifndef __MG_DATABASE_H -#define __MG_DATABASE_H - -#include <string> -#include <mysql/mysql.h> - -/*! - * \brief an abstract database class - * - */ -class mgDB -{ - public: - - /*! \brief default constructor - */ - mgDB( ); - - /*! \brief constructor - * - * \param host - * \param name - * \param user - * \param pass - * \param port - */ - mgDB( std::string host, std::string name, - std::string user="", std::string pass="", - int port = 0 ); - - // add constructor for sockets - - /*! \brief destructor */ - ~mgDB(); - - /*! - * \brief obtain database handle - */ - MYSQL getDBHandle(); - - MYSQL_RES *exec_sql (std::string query); - - /*! - * \brief database initialization - */ - void initialize(); - - /*! - * \brief helper function to execute read queries - * - * \todo Could be a member of mgDatabase? - */ - MYSQL_RES* read_query( const char *fmt, ... ); - - /*! - * \brief helper function to execute write queries - * - * \todo Could be a member of mgDatabase? - */ - void write_query( const char *fmt, ... ); - - /*! - * \brief escape arguments to be contained in a query - * - * \todo use m_dbase member of this class - */ - static std::string escape_string( MYSQL *db, std::string s ); - - private: - MYSQL m_dbase; -}; - -#endif @@ -178,6 +178,7 @@ char *db_cmds[] = mgmySql::mgmySql() { m_db = 0; + m_hasfolderfields=false; Connect(); } @@ -244,16 +245,38 @@ void mgmySql::Create() string mgmySql::sql_string( const string s ) { - if (!this) - return "'" + s + "'"; - - char *buf = (char *) malloc( 2*s.size() + 1 ); - mysql_real_escape_string( m_db, buf, s.c_str(), s.size() ); - string result = "'" + string( buf ) + "'"; - free( buf ); + char *b = sql_Cstring(s); + string result = string( b); + free( b); return result; } +char* +mgmySql::sql_Cstring( const string s ) +{ + return sql_Cstring(s.c_str()); +} + +char* +mgmySql::sql_Cstring( const char *s) +{ + char *buf; + int buflen; + if (!this) + buflen=strlen(s)+2; + else + buflen=2*strlen(s)+3; + buf = (char *) malloc( buflen); + buf[0]='\''; + if (!this) + strcpy(buf+1,s); + else + mysql_real_escape_string( m_db, buf+1, s, strlen(s) ); + *(strchr(buf,0)+1)=0; + *(strchr(buf,0))='\''; + return buf; +} + void mgmySql::Connect () { @@ -312,4 +335,28 @@ mgmySql::Connect () return; } +void +mgmySql::CreateFolderFields() +{ + if (!Connected()) + return; + if (HasFolderFields()) + return; + mysql_query(m_db,"DESCRIBE tracks folder1"); + MYSQL_RES *rows = mysql_store_result(m_db); + if (rows) + { + m_hasfolderfields = mysql_num_rows(rows)>0; + mysql_free_result(rows); + if (!m_hasfolderfields) + { + m_hasfolderfields = !mysql_query(m_db, + "alter table tracks add column folder1 varchar(255)," + "add column folder2 varchar(255)," + "add column folder3 varchar(255)," + "add column folder4 varchar(255)"); + + } + } +} @@ -41,6 +41,9 @@ class mgmySql */ string sql_string( string s ); + char* sql_Cstring( const string s ); + char* sql_Cstring( const char *s ); + string get_col0( const string query); /*! \brief executes a query and returns the integer value from @@ -53,12 +56,15 @@ class mgmySql long thread_id() { return mysql_thread_id(m_db);} long affected_rows() { return mysql_affected_rows(m_db);} bool Connected() const { return m_db;} + bool HasFolderFields() const { return m_hasfolderfields;} void Connect(); //! \brief create database and tables void Create(); + void CreateFolderFields(); private: MYSQL *m_db; + bool m_hasfolderfields; }; #endif @@ -228,6 +228,14 @@ class mgKeyGenre3 : public mgKeyGenres unsigned int genrelevel() const { return 3; } }; +class mgKeyid3Genre : public mgKeyNormal { + public: + mgKeyid3Genre() : mgKeyNormal(keyid3Genre,"tracks","genre1") {}; + string map_idfield() const { return "id"; } + string map_valuefield() const { return "id3genre"; } + string map_valuetable() const { return "genre"; } +}; + string mgKeyGenres::GenreClauses(mgmySql &db,bool orderby) const { @@ -994,6 +1002,7 @@ ktGenerate(const mgKeyTypes kt) case keyAlbum: result = new mgKeyAlbum;break; case keyCreated: result = new mgKeyDate(kt,"tracks","created");break; case keyModified: result = new mgKeyDate(kt,"tracks","modified");break; + case keyid3Genre: result = new mgKeyid3Genre;break; case keyCollection: result = new mgKeyCollection;break; case keyCollectionItem: result = new mgKeyCollectionItem;break; case keyLanguage: result = new mgKeyLanguage;break; @@ -1024,6 +1033,7 @@ ktName(const mgKeyTypes kt) case keyAlbum: result = "Album";break; case keyCreated: result = "Created";break; case keyModified: result = "Modified";break; + case keyid3Genre: result = "id3Genre";break; case keyCollection: result = "Collection";break; case keyCollectionItem: result = "Collection item";break; case keyLanguage: result = "Language";break; @@ -40,6 +40,7 @@ enum mgKeyTypes { keyFolder4, keyCreated, keyModified, + keyid3Genre, keyCollection, keyCollectionItem, }; diff --git a/mg_selection.c b/mg_selection.c index 05904f3..f01063a 100644 --- a/mg_selection.c +++ b/mg_selection.c @@ -9,11 +9,21 @@ * */ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> #include <stdio.h> +#include <fts.h> + #include "mg_selection.h" #include "vdr_setup.h" #include "mg_tools.h" +#include <mpegfile.h> +#include <flacfile.h> +#include <id3v2tag.h> +#include <fileref.h> + //! \brief adds string n to string s, using a comma to separate them static string comma (string & s, string n); @@ -1115,3 +1125,227 @@ mgSelection::choices(mgOrder *o,unsigned int level, unsigned int *current) } return result; } + +char * +mgSelection::sql_Cstring(TagLib::String s) +{ + return m_db.sql_Cstring(s.toCString()); +} + +char * +mgSelection::lower(char *s) +{ + char *p=s; + while (*p) + { + int i=(int)(*p); + (*p)=(char)tolower(i); + p++; + } + return s; +} + +TagLib::String +mgSelection::getlanguage(const char *filename) +{ + TagLib::String result = ""; + TagLib::ID3v2::Tag * id3v2tag=0; + char *extension = strrchr(filename,'.'); + if (!extension) + return result; + extension++; + lower(extension); + if (!strcmp(extension,"flac")) + { + TagLib::FLAC::File f(filename); + id3v2tag = f.ID3v2Tag(); + if (id3v2tag) + { + TagLib::ID3v2::FrameList l = id3v2tag->frameListMap()["TLAN"]; + if (!l.isEmpty()) + result = l.front()->toString(); + } + } + else if (!strcmp(extension,"mp3")) + { + TagLib::MPEG::File f(filename); + id3v2tag = f.ID3v2Tag(); + if (id3v2tag) + { + TagLib::ID3v2::FrameList l = id3v2tag->frameListMap()["TLAN"]; + if (!l.isEmpty()) + result = l.front()->toString(); + } + } + return result; +} + +char * +mgSelection::getAlbum(const char *c_album,const char *c_artist,const char *c_title) +{ + char * result; + char *b; + asprintf(&b,"SELECT cddbid FROM album" + " WHERE title=%s AND artist=%s",c_title,c_artist); + result=m_db.sql_Cstring(m_db.get_col0(b)); + free(b); + if (!strcmp(result,"'NULL'")) + { + asprintf(&result,"'%ld-%9s",random(),c_artist+1); + char *p=strchr(result,0)-1; + if (*p!='\'') + *p='\''; + asprintf(&b,"INSERT INTO album SET artist=%s,title=%s,cddbid=%s", + c_artist,c_album,result); + m_db.exec_sql(b); + free(b); + } + return result; +} + +void +mgSelection::AddTrack(const char *filename) +{ +// mgDebug(1,"%s:AddTrack(%s)",get_current_dir_name(),filename); + + TagLib::FileRef f( filename) ; + if (f.isNull()) + return; + TagLib::Tag *tag = f.tag(); + if (!f.tag()) + return; + char *c_album; + if (tag->album()=="") + c_album=strdup("'Unassigned'"); + else + c_album=sql_Cstring(tag->album()); + char *c_artist=sql_Cstring(tag->artist()); + char *c_title=sql_Cstring(tag->title()); + char *c_cddbid=getAlbum(c_album,c_artist,c_title); + char *c_mp3file=sql_Cstring(filename); + char *c_genre1=sql_Cstring(id(keyGenres,tag->genre().to8Bit())); + char *c_lang=sql_Cstring(getlanguage(filename)); + char *folderstring=(char*)malloc(strlen(c_mp3file)*3); + unsigned int trackno=tag->track(); + unsigned int year=tag->year(); + TagLib::AudioProperties *ap = f.audioProperties(); + int len = ap->length(); // tracks.length + int bitrate = ap->bitrate(); // tracks.bitrate + int sample = ap->sampleRate(); //tracks.samplerate + int channels = ap->channels(); //tracks.channels + folderstring[0]=0; + 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; + } + } + } + } + char *c_folder1=sql_Cstring(folder1); + char *c_folder2=sql_Cstring(folder2); + char *c_folder3=sql_Cstring(folder3); + char *c_folder4=sql_Cstring(folder4); + free(path); + sprintf(folderstring,"folder1=%s,folder2=%s,folder3=%s,folder4=%s", + c_folder1,c_folder2,c_folder3,c_folder4); + free(c_folder1); + free(c_folder2); + free(c_folder3); + free(c_folder4); + } + char sql[2000]; + sprintf(sql,"INSERT INTO tracks SET artist=%s,title=%s,year=%d,sourceid=%s," + "tracknb=%d,mp3file=%s,length=%d,bitrate=%d,samplerate=%d," + "channels=%d,genre1=%s,genre2='',lang=%s,%s", + c_artist,c_title,year,c_cddbid, + trackno,c_mp3file,len,bitrate,sample, + channels,c_genre1,c_lang,folderstring); + free(c_album); + free(c_artist); + free(c_title); + free(c_cddbid); + free(c_mp3file); + free(c_genre1); + free(c_lang); + free(folderstring); + m_db.exec_sql(sql); +} + +void +mgSelection::SyncFile(const char *filename) +{ + if (!strncmp(filename,"./",2)) + filename += 2; + if (strlen(filename)>255) + { + mgWarning("Length of file exceeds database field capacity: %s", filename); + + return; + } + string escapedmp3file = m_db.sql_string(filename); + string s = m_db.get_col0("SELECT id from tracks WHERE mp3file="+escapedmp3file); + if (s!="NULL") + { + } + else + { + AddTrack(filename); + } +} + +void +mgSelection::Sync(const char * path, bool assorted,bool delete_missing) +{ + if (!m_db.Connected()) + { + mgError("Cannot connect to data base"); + } + // init random number generator + struct timeval tv; + struct timezone tz; + gettimeofday( &tv, &tz ); + srandom( tv.tv_usec ); + + m_db.CreateFolderFields(); + chdir(the_setup.ToplevelDir); + FTS *fts; + FTSENT *ftsent; + const char * paths[2]; + paths[0]=path; + paths[1]=0; + fts = fts_open( const_cast<char *const *>(paths), FTS_LOGICAL, 0); + while ( (ftsent = fts_read(fts)) != NULL) + { + SyncFile(ftsent->fts_path); + } + fts_close(fts); +} diff --git a/mg_selection.h b/mg_selection.h index 422040d..4a8f298 100644 --- a/mg_selection.h +++ b/mg_selection.h @@ -24,6 +24,8 @@ using namespace std; #include "mg_order.h" #include "mg_content.h" +#include <tag.h> + typedef vector<string> strvector; @@ -305,13 +307,12 @@ class mgSelection /*! import/export tags like * \par path can be a file or a directory. If directory, - * sync all files within but by default non recursive - * \par recursive recurse into all directories beneath path + * sync all files within * \par assorted see mugglei -h * \par delete_missing if the file does not exist, delete the * data base entry. If the file is unreadable, do not delete. */ - void Sync(string path, bool recursive=false,bool assorted=false,bool delete_missing=false); + void Sync(const char * path, bool assorted=false,bool delete_missing=false); /*! \brief go to a position in the current level. If we are at the * most detailled level this also sets the track position since @@ -467,6 +468,16 @@ class mgSelection void loadgenres (); void InitFrom(const mgSelection* s); + char *sql_Cstring(TagLib::String s); + char *lower(char *s); + TagLib::String getlanguage(const char *filename); + char * getAlbum(const char *c_album,const char *c_artist,const char *c_title); + void AddTrack(const char *filename); + void SyncFile(const char *filename); + + + + }; @@ -31,4 +31,6 @@ mgSetup::mgSetup () LimiterLevel = DEFAULT_LIMITER_LEVEL; Only48kHz = 0; ToplevelDir = "/mnt/music/"; + DbHost = "localhost"; + DbName = "GiantDisc"; } @@ -15,7 +15,6 @@ #include "vdr_menu.h" #include "vdr_setup.h" #include "mg_tools.h" -#include "mg_selection.h" #include "i18n.h" #include <getopt.h> @@ -30,9 +30,13 @@ #include <id3v2tag.h> #include <fileref.h> -#include "mg_tools.h" +#include "vdr_setup.h" +#include "mg_selection.h" -MYSQL *db; + +using namespace std; + +int SysLogLevel = 1; static char *server_args[] = { @@ -49,687 +53,27 @@ static char *server_groups[] = (char *)NULL }; -char *db_cmds[] = -{ - "DROP DATABASE IF EXISTS GiantDisc; CREATE DATABASE GiantDisc;", - "grant all privileges on GiantDisc.* to vdr@localhost;", - "use GiantDisc;", - "drop table if exists album; CREATE TABLE album ( " - "artist varchar(255) default NULL, " - "title varchar(255) default NULL, " - "cddbid varchar(20) NOT NULL default '', " - "coverimg varchar(255) default NULL, " - "covertxt mediumtext, " - "modified date default NULL, " - "genre varchar(10) default NULL, " - "PRIMARY KEY (cddbid), " - "KEY artist (artist(10)), " - "KEY title (title(10)), " - "KEY genre (genre), " - "KEY modified (modified)) " - "TYPE=MyISAM;", - "drop table if exists genre; CREATE TABLE genre (" - "id varchar(10) NOT NULL default '', " - "id3genre smallint(6) default NULL, " - "genre varchar(255) default NULL, " - "freq int(11) default NULL, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists language; CREATE TABLE language (" - "id varchar(4) NOT NULL default '', " - "language varchar(40) default NULL, " - "freq int(11) default NULL, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists musictype; CREATE TABLE musictype (" - "musictype varchar(40) default NULL, " - "id tinyint(3) unsigned NOT NULL auto_increment, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists player;CREATE TABLE player ( " - "ipaddr varchar(255) NOT NULL default '', " - "uichannel varchar(255) NOT NULL default '', " - "logtarget int(11) default NULL, " - "cdripper varchar(255) default NULL, " - "mp3encoder varchar(255) default NULL, " - "cdromdev varchar(255) default NULL, " - "cdrwdev varchar(255) default NULL, " - "id int(11) NOT NULL default '0', " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists playerstate;CREATE TABLE playerstate ( " - "playerid int(11) NOT NULL default '0', " - "playertype int(11) NOT NULL default '0', " - "snddevice varchar(255) default NULL, " - "playerapp varchar(255) default NULL, " - "playerparams varchar(255) default NULL, " - "ptlogger varchar(255) default NULL, " - "currtracknb int(11) default NULL, " - "state varchar(4) default NULL, " - "shufflepar varchar(255) default NULL, " - "shufflestat varchar(255) default NULL, " - "pauseframe int(11) default NULL, " - "framesplayed int(11) default NULL, " - "framestotal int(11) default NULL, " - "anchortime bigint(20) default NULL, " - "PRIMARY KEY (playerid,playertype)) " - "TYPE=HEAP;", - "drop table if exists playlist;CREATE TABLE playlist ( " - "title varchar(255) default NULL, " - "author varchar(255) default NULL, " - "note varchar(255) default NULL, " - "created timestamp(8) NOT NULL, " - "id int(10) unsigned NOT NULL auto_increment, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists playlistitem;CREATE TABLE playlistitem ( " - "playlist int(11) NOT NULL default '0', " - "tracknumber mediumint(9) NOT NULL default '0', " - "trackid int(11) default NULL, " - "PRIMARY KEY (playlist,tracknumber)) " - "TYPE=MyISAM;", - "drop table if exists playlog;CREATE TABLE playlog ( " - "trackid int(11) default NULL, " - "played date default NULL, " - "id tinyint(3) unsigned NOT NULL auto_increment, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists recordingitem;CREATE TABLE recordingitem ( " - "trackid int(11) default NULL, " - "recdate date default NULL, " - "rectime time default NULL, " - "reclength int(11) default NULL, " - "enddate date default NULL, " - "endtime time default NULL, " - "repeat varchar(10) default NULL, " - "initcmd varchar(255) default NULL, " - "parameters varchar(255) default NULL, " - "atqjob int(11) default NULL, " - "id int(11) NOT NULL default '0', " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists source; CREATE TABLE source ( " - "source varchar(40) default NULL, " - "id tinyint(3) unsigned NOT NULL auto_increment, " - "PRIMARY KEY (id)) " - "TYPE=MyISAM;", - "drop table if exists tracklistitem;CREATE TABLE tracklistitem ( " - "playerid int(11) NOT NULL default '0', " - "listtype smallint(6) NOT NULL default '0', " - "tracknb int(11) NOT NULL default '0', " - "trackid int(11) NOT NULL default '0', " - "PRIMARY KEY (playerid,listtype,tracknb)) " - "TYPE=MyISAM;", - "drop table if exists tracks;CREATE TABLE tracks ( " - "artist varchar(255) default NULL, " - "title varchar(255) default NULL, " - "genre1 varchar(10) default NULL, " - "genre2 varchar(10) default NULL, " - "year smallint(5) unsigned default NULL, " - "lang varchar(4) default NULL, " - "type tinyint(3) unsigned default NULL, " - "rating tinyint(3) unsigned default NULL, " - "length smallint(5) unsigned default NULL, " - "source tinyint(3) unsigned default NULL, " - "sourceid varchar(20) default NULL, " - "tracknb tinyint(3) unsigned default NULL, " - "mp3file varchar(255) default NULL, " - "condition tinyint(3) unsigned default NULL, " - "voladjust smallint(6) default '0', " - "lengthfrm mediumint(9) default '0', " - "startfrm mediumint(9) default '0', " - "bpm smallint(6) default '0', " - "lyrics mediumtext, " - "bitrate varchar(10) default NULL, " - "created date default NULL, " - "modified date default NULL, " - "backup tinyint(3) unsigned default NULL, " - "samplerate int(7) unsigned default NULL, " - "channels tinyint(3) unsigned default NULL, " - "id int(11) NOT NULL auto_increment, " - "folder1 varchar(255), " - "folder2 varchar(255), " - "folder3 varchar(255), " - "folder4 varchar(255), " - "PRIMARY KEY (id), " - "KEY title (title(10)), " - "KEY mp3file (mp3file(10)), " - "KEY genre1 (genre1), " - "KEY genre2 (genre2), " - "KEY year (year), " - "KEY lang (lang), " - "KEY type (type), " - "KEY rating (rating), " - "KEY sourceid (sourceid), " - "KEY artist (artist(10))) " - "TYPE=MyISAM;" -}; - -bool folderfields; - -std::string host, user, pass, dbname, sck; +string host, user, pass, dbname, sck; bool import_assorted, delete_mode, create_mode; -#define MAX_QUERY_BUFLEN 2048 -static char querybuf[MAX_QUERY_BUFLEN]; - void showmessage(const char *msg) { } -void -init_folderfields() -{ - folderfields=false; - mysql_query(db,"DESCRIBE tracks folder1"); - MYSQL_RES *rows = mysql_store_result(db); - if (rows) - { - folderfields = mysql_num_rows(rows)>0; - mysql_free_result(rows); - if (!folderfields) - { - folderfields = !mysql_query(db, - "alter table tracks add column folder1 varchar(255)," - "add column folder2 varchar(255)," - "add column folder3 varchar(255)," - "add column folder4 varchar(255)"); - - } - } -} - -MYSQL_RES* mgSqlReadQuery(MYSQL *db, const char *fmt, ...) -{ - va_list ap; - va_start( ap, fmt ); - vsnprintf( querybuf, MAX_QUERY_BUFLEN-1, fmt, ap ); - - if( mysql_query(db, querybuf) ) - { - mgError( "SQL error in MUGGLE:\n%s: %s\n", querybuf,mysql_error(db) ); - } - - MYSQL_RES *result = mysql_store_result(db); - - va_end(ap); - return result; -} - -void mgSqlWriteQuery(MYSQL *db, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vsnprintf(querybuf, MAX_QUERY_BUFLEN-1, fmt, ap); - - if( mysql_query(db, querybuf) ) - { - mgError( "SQL error in MUGGLE:\n%s %s\n", querybuf,mysql_error(db) ); - } - - va_end(ap); -} - -int init_database() -{ - db = mysql_init(0); // NULL? - - if( db == NULL ) - { - std::cout << "mysql_init failed." << std::endl; - return -1; - } - - // check for use of sockets - if( sck != "" ) - { - if( mysql_real_connect( db, NULL, user.c_str(), pass.c_str(), dbname.c_str(), - 0, sck.c_str(), 0 ) == NULL ) - - { - std::cout << "mysql_real_connect using sockets failed." << std::endl; - return -2; - } - } - else - { - if( mysql_real_connect( db, host.c_str(), user.c_str(), pass.c_str(), dbname.c_str(), - 0, NULL, 0 ) == NULL ) - { - std::cout << "mysql_real_connect via TCP failed." << std::endl; - return -2; - } - } - - return 0; -} - -MYSQL_RES * -exec_sql( std::string query ) -{ - if( query.empty() ) - return 0; - mgDebug( 3, "exec_sql(%X,%s)", db, query.c_str() ); - if (mysql_query (db, (query + ';').c_str ())) - { - mgError("SQL Error in %s: %s",query.c_str(),mysql_error (db)); - std::cout << "ERROR in " << query << ":" << mysql_error(db) << std::endl; - return 0; - } - return mysql_store_result(db); -} - -int create_database() -{ - // create database and tables - int len = sizeof( db_cmds ) / sizeof( char* ); - for( int i=0; i < len; i ++ ) - { - exec_sql( std::string( db_cmds[i] ) ); - } - return 0; -} - -time_t get_fs_modification_time( std::string filename ) -{ - struct stat *buf = (struct stat*) malloc( sizeof( struct stat ) ); - time_t mod = 0; - - // yes: obtain modification date for file and db entry - if( !stat( filename.c_str(), buf ) ) - { - mod = buf->st_mtime; - free( buf ); - } - - return mod; -} - -time_t get_db_modification_time( long uid ) -{ - time_t mt = 0; - - MYSQL_RES *result = mgSqlReadQuery( db, "SELECT UNIX_TIMESTAMP(modification_time) " - "FROM tracks WHERE id=\"%d\"", uid ); - if( mysql_num_rows(result) ) - { - MYSQL_ROW row = mysql_fetch_row( result ); - - std::string mod_time = row[0]; - mt = (time_t) atol( mod_time.c_str() ); - } - - return mt; -} - -TagLib::String escape_string( MYSQL *db, TagLib::String s ) +const char *I18nTranslate(const char *s,const char *Plugin) { - char *buf = strdup( s.toCString() ); - char *escbuf = (char *) malloc( 2*strlen( buf ) + 1 ); - - mysql_real_escape_string( db, escbuf, s.toCString(), s.size() ); - TagLib::String r = TagLib::String( escbuf ); - - free( escbuf ); - free( buf); - - return r; -} - -long find_file_in_database( MYSQL *db, std::string filename ) -{ - long uid = -1; - - TagLib::String file = TagLib::String( filename.c_str() ); - file = escape_string( db, file ); - - MYSQL_RES *result = mgSqlReadQuery( db, "SELECT id FROM tracks WHERE mp3file=\"%s\"", file.toCString() ); - if( mysql_num_rows(result) ) - { - MYSQL_ROW row = mysql_fetch_row( result ); - uid = atol( row[0] ); - } - - // obtain ID and return - return uid; -} - -TagLib::String find_genre_id( TagLib::String genre ) -{ - TagLib::String id = ""; - - if( genre.size() ) - { - MYSQL_RES *result = mgSqlReadQuery( db, "SELECT id FROM genre WHERE " - "genre=\"%s\"", genre.toCString() ); - - if( mysql_num_rows(result) ) - { - MYSQL_ROW row = mysql_fetch_row( result ); - - id = row[0]; - } - } - - return id; -} - -// read tags from the mp3 file and store them into the corresponding database entry -void update_db( long uid, std::string filename ) -{ - TagLib::String title, album, artist, genre, cddbid, language; - uint trackno, year; - - // ID3_Tag filetag( filename.c_str() ); - TagLib::FileRef f( filename.c_str() ); - - if( !f.isNull() && f.tag() ) - { - // std::cout << "Evaluating " << filename << std::endl; - TagLib::Tag *tag = f.tag(); - - // obtain tag information - title = tag->title(); - album = tag->album(); - year = tag->year(); - artist = tag->artist(); - trackno = tag->track(); - genre = tag->genre(); - language = ""; - TagLib::ID3v2::Tag * id3v2tag=0; - if (filename.substr(filename.size()-5)==".flac") - { - TagLib::FLAC::File f(filename.c_str()); - id3v2tag = f.ID3v2Tag(); - if (id3v2tag) - { - TagLib::ID3v2::FrameList l = id3v2tag->frameListMap()["TLAN"]; - if (!l.isEmpty()) - language = l.front()->toString(); - } - } - else if (filename.substr(filename.size()-4)==".mp3") - { - TagLib::MPEG::File f(filename.c_str()); - id3v2tag = f.ID3v2Tag(); - if (id3v2tag) - { - TagLib::ID3v2::FrameList l = id3v2tag->frameListMap()["TLAN"]; - if (!l.isEmpty()) - language = l.front()->toString(); - } - } - - TagLib::String gid = find_genre_id( genre ); - - TagLib::AudioProperties *ap = f.audioProperties(); - int len = ap->length(); // tracks.length - int bitrate = ap->bitrate(); // tracks.bitrate - int sample = ap->sampleRate(); //tracks.samplerate - int channels = ap->channels(); //tracks.channels - - title = escape_string( db, title ); - album = escape_string( db, album ); - artist = escape_string( db, artist ); - - // TODO: CD identifier (if it exists), playcounter, popularimeter (rating?), volume adjustment, lyrics, cover - - // finally update the database - - // obtain associated album or create - if( album == "" ) - { // no album found, create default album for artist - MYSQL_RES *result = mgSqlReadQuery( db, "SELECT cddbid FROM album WHERE title=\"Unassigned\" AND artist=\"%s\"", artist.toCString() ); - MYSQL_ROW row = mysql_fetch_row( result ); - - // Default album does not yet exist (num rows == 0) - int nrows = mysql_num_rows(result); - if( nrows == 0 ) - { - // create new album entry "Unassigned" for this artist - long id = random(); - char *buf; - asprintf( &buf, "%ld-%s", id, tag->artist().toCString() ); - cddbid = TagLib::String( buf ).substr( 0, 20 ); - cddbid = escape_string( db, cddbid ); - free( buf ); - - mgSqlWriteQuery( db, - "INSERT INTO album (artist, title, cddbid) " - "VALUES (\"%s\", \"Unassigned\", \"%s\")", - artist.toCString(), cddbid.toCString() ); - } - else - { // use first album found as source id for the track - cddbid = escape_string(db,row[0]); - } - } - else - { // album tag found, associate or create - MYSQL_RES *result; - if( import_assorted ) - { // lookup an existing album by title only (artist should be "Various Artists" - result = mgSqlReadQuery( db, "SELECT cddbid FROM album WHERE title=\"%s\" AND artist=\"Various Artists\"", - album.toCString(), artist.toCString() ); - } - else - { - result = mgSqlReadQuery( db, "SELECT cddbid FROM album WHERE title=\"%s\" AND artist=\"%s\"", - album.toCString(), artist.toCString() ); - } - MYSQL_ROW row = mysql_fetch_row( result ); - - // num rows == 0 ? - int nrows = mysql_num_rows(result); - if( nrows == 0 ) - { - // create new album entry - long id = random(); - char *buf; - asprintf( &buf, "%ld-%s", id, tag->album().toCString() ); - cddbid = TagLib::String( buf ).substr( 0, 20 ); - cddbid = escape_string( db, cddbid ); - free( buf ); - - if( import_assorted ) - { // in this case, the album author is "Various Artists" - mgSqlWriteQuery( db, - "INSERT INTO album (artist,title,cddbid) " - "VALUES (\"Various Artists\", \"%s\", \"%s\")", - album.toCString(), cddbid.toCString() ); - } - else - { - mgSqlWriteQuery( db, - "INSERT INTO album (artist,title,cddbid) " - "VALUES (\"%s\", \"%s\", \"%s\")", - artist.toCString(), album.toCString(), cddbid.toCString() ); - } - } - else - { // use first album found as source id for the track - cddbid = escape_string(db,row[0]); - } - } - - // update tracks table - if( uid > 0 ) - { // the entry is known to exist already, hence update it - - mgSqlWriteQuery( db, "UPDATE tracks SET artist=\"%s\", title=\"%s\", year=\"%d\"," - "sourceid=\"%s\", mp3file=\"%s\", length=%d, bitrate=\"%d\"," - "samplerate=%d, channels=%d, genre1=\"%s\", lang=\"%s\" WHERE id=%d", - artist.toCString(), title.toCString(), year, - cddbid.toCString(), filename.c_str(), len, bitrate, - sample, channels, gid.toCString(), language.toCString(), uid ); - } - else - { // the entry does not exist, create it - if (folderfields) - { - char *path = strdup(filename.c_str()); - 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; - } - } - } - } - TagLib::String f1 = escape_string( db, folder1 ); - TagLib::String f2 = escape_string( db, folder2 ); - TagLib::String f3 = escape_string( db, folder3 ); - TagLib::String f4 = escape_string( db, folder4 ); - mgSqlWriteQuery( db, - "INSERT INTO tracks " - "(artist, title, year,sourceid,tracknb,mp3file,length,bitrate,samplerate,channels,genre1,genre2,lang,folder1,folder2,folder3,folder4) VALUES" - "(\"%s\", \"%s\", %d, \"%s\", %d, \"%s\", %d, \"%d\", %d, %d, \"%s\",\"\",\"%s\"," - "\"%s\",\"%s\",\"%s\",\"%s\")", - artist.toCString(), title.toCString(), year, cddbid.toCString(), - trackno, filename.c_str(), len, bitrate, sample, channels, gid.toCString(), - language.toCString(),f1.toCString(),f2.toCString(),f3.toCString(),f4.toCString()); - free(path); - } - else - mgSqlWriteQuery( db, - "INSERT INTO tracks " - "(artist, title, year,sourceid,tracknb,mp3file,length,bitrate,samplerate,channels,genre1,genre2,lang) VALUES" - "(\"%s\", \"%s\", %d, \"%s\", %d, \"%s\", %d, \"%d\", %d, %d, \"%s\",\"\",\"%s\")", - artist.toCString(), title.toCString(), year, cddbid.toCString(), - trackno, filename.c_str(), len, bitrate, sample, channels, gid.toCString(), - language.toCString()); - -#ifdef VERBOSE - std::cout << "-- TAG --" << std::endl; - std::cout << "title - '" << tag->title() << "'" << std::endl; - std::cout << "artist - '" << tag->artist() << "'" << std::endl; - std::cout << "album - '" << tag->album() << "'" << std::endl; - std::cout << "year - '" << tag->year() << "'" << std::endl; - std::cout << "comment - '" << tag->comment() << "'" << std::endl; - std::cout << "track - '" << tag->track() << "'" << std::endl; - std::cout << "genre - '" << tag->genre() << "'" << std::endl; - std::cout << "language- '" << language << "'" << std::endl; -#endif - } - } -} - -void update_tags( long uid ) -{ - MYSQL_RES *result; - MYSQL_ROW row; - - if( uid >= 0 ) - { - result = mgSqlReadQuery( db, "SELECT artist,title,year,tracknb,mp3file,genre1,id FROM tracks where id=%d", uid ); - } - else - { - result = mgSqlReadQuery( db, "SELECT artist,title,year,tracknb,mp3file,genre1,id FROM tracks" ); - } - - // loop all results - char* cwd = getcwd( NULL, 0 ); - std::string wdir = std::string( cwd ); - free( cwd ); - - struct stat *buf = (struct stat*) malloc( sizeof( struct stat ) ); - while(( row = mysql_fetch_row(result) ) != NULL ) - { - - std::string file = wdir + "/" + std::string( row[4] ); - - if( !stat( file.c_str(), buf ) ) - { - // set tags? - /* - std::string artist = row[0]; - std::string title = row[1]; - int year = atoi( row[2] ); - int track = atoi( row[3] ); - std::string genre = row[5]; - */ - } - else - { - if( delete_mode ) - { -#ifdef VERBOSE - std::cout << "Deleting entry " << row[6] << " from database because the file no longer exists." << std::endl; -#endif - mgSqlWriteQuery( db, "DELETE FROM tracks where id=%s", row[6] ); - } - } - } - free( buf ); -} - -void evaluate_file( std::string filename ) -{ - // is filename stored in database? - long uid = find_file_in_database( db, filename ); - if( uid >= 0 ) - { - // currently only update database, do not consider writing changes from the db back to tags - /* - // determine modification times in database and on filesystem - time_t db_time = get_db_modification_time( uid ); - time_t fs_time = get_fs_modification_time( filename ); - - if( db_time > fs_time ) - { - // db is newer: update id3 tags from db - update_tags( uid, filename ); - } - else - { - // file is newer: update db from id3 tags - update_db( uid, filename ); - } - */ - - update_db( uid, filename ); - } - else - { - // not in db yet: import file - update_db( -1, filename ); - } + return s; } int main( int argc, char *argv[] ) { + mgSetDebugLevel(1); if( mysql_server_init(sizeof(server_args) / sizeof(char *), server_args, server_groups) ) { exit(1); } - std::string filename; + char *filename; if( argc < 2 ) { // we need at least a filename! @@ -743,8 +87,8 @@ int main( int argc, char *argv[] ) std::cout << " -n <database> - specify database name (default is 'GiantDisc')" << std::endl; std::cout << " -u <username> - specify user of mySql database (default is empty)" << std::endl; std::cout << " -p <password> - specify password of user (default is empty password)" << std::endl; - std::cout << " -f <filename> - name of music file to import or update" << std::endl; - std::cout << " -a - import track as if it was on an assorted album" << std::endl; + std::cout << " -t <topleveldir> - name of music top level directory" << std::endl; + std::cout << " -f <filename> - name of music file or directory to import or update relative to topleveldir" << std::endl; std::cout << " -z - scan all database entries and delete entries for files not found" << std::endl; std::cout << " -c - create a new database entry deleting existing entries" << std::endl; @@ -752,11 +96,6 @@ int main( int argc, char *argv[] ) } // option defaults - host = "localhost"; - dbname = "GiantDisc"; - user = ""; - pass = ""; - sck = ""; import_assorted = false; delete_mode = false; create_mode = false; @@ -765,7 +104,7 @@ int main( int argc, char *argv[] ) // parse command line options while( 1 ) { - int c = getopt(argc, argv, "h:u:p:n:af:s:z"); + int c = getopt(argc, argv, "h:s:n:u:p:t:f:z"); if (c == -1) break; @@ -778,32 +117,32 @@ int main( int argc, char *argv[] ) } break; case 'h': { - host = optarg; + the_setup.DbHost = optarg; } break; case 'n': { - dbname = optarg; + the_setup.DbName = optarg; } break; case 'u': { - user = optarg; + the_setup.DbUser = optarg; } break; case 'p': { - pass = optarg; + the_setup.DbPass = optarg; } break; - case 'a': + case 's': { - import_assorted = true; + the_setup.DbSocket = optarg; + } break; + case 't': + { + the_setup.ToplevelDir = optarg; } break; case 'f': { filename = optarg; } break; - case 's': - { - sck = optarg; - } break; case 'z': { delete_mode = true; @@ -815,36 +154,8 @@ int main( int argc, char *argv[] ) } } - if( filename.length() > 255 ) - { - std::cerr << "Warning: length of file exceeds database field capacity: " << filename << std::endl; - } - - // init random number generator - struct timeval tv; - struct timezone tz; - gettimeofday( &tv, &tz ); - srandom( tv.tv_usec ); - - if( 0 == init_database() ) - { - init_folderfields(); - if( delete_mode ) - { - update_tags( -1 ); - } - else if( create_mode ) - { - create_database(); - } - if( filename.size() ) - { - evaluate_file( filename ); - } - } - - mysql_server_end(); - + mgSelection sel; + sel.Sync(filename,false); return 0; } @@ -600,6 +600,9 @@ mgSubmenu::BuildOsd () AddAction(actClearCollection,on); AddAction(actChooseOrder,on); AddAction(actExportTracklist,on); +#if 0 + AddAction(actSync,on); +#endif cCommand *command; if (osd()->external_commands) { |