summaryrefslogtreecommitdiff
path: root/mugglei.c
diff options
context:
space:
mode:
Diffstat (limited to 'mugglei.c')
-rwxr-xr-xmugglei.c690
1 files changed, 350 insertions, 340 deletions
diff --git a/mugglei.c b/mugglei.c
index 66fb766..3db2f04 100755
--- a/mugglei.c
+++ b/mugglei.c
@@ -1,340 +1,350 @@
-
-#include <string>
-using namespace std;
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <mysql/mysql.h>
-
-#include <taglib/tag.h>
-#include <taglib/fileref.h>
-
-#include "mg_tools.h"
-
-MYSQL *db;
-
-string host, user, pass, dbname;
-bool import_assorted;
-
-int init_database()
-{
- db = mysql_init(NULL);
- if( db == NULL )
- {
- return -1;
- }
-
- if( mysql_real_connect( db, host.c_str(), user.c_str(), pass.c_str(), dbname.c_str(),
- 0, NULL, 0 ) == NULL )
- {
- return -2;
- }
-
- return 0;
-}
-
-time_t get_fs_modification_time( string filename )
-{
- struct stat *buf = (struct stat*) malloc( sizeof( struct stat ) );
-
- // yes: obtain modification date for file and db entry
- int statres = stat( filename.c_str(), buf );
-
- time_t mod = buf->st_mtime;
- free( buf );
-
- return mod;
-}
-
-time_t get_db_modification_time( long uid )
-{
- time_t mt;
-
- MYSQL_RES *result = mgSqlReadQuery( db, "SELECT modification_time FROM tracks WHERE id=\"%d\"", uid );
- MYSQL_ROW row = mysql_fetch_row( result );
-
- string mod_time = row[0];
- mt = (time_t) atol( mod_time.c_str() );
-
- return mt;
-}
-
-TagLib::String escape_string( MYSQL *db, TagLib::String s )
-{
- char *buf = strdup( s.toCString() );
- char *escbuf = (char *) malloc( 2*strlen( buf ) + 1 );
-
- int len = mysql_real_escape_string( db, escbuf, buf, strlen( buf ) );
-
- return TagLib::String( escbuf );
-}
-
-long find_file_in_database( MYSQL *db, string filename )
-{
- 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() );
- MYSQL_ROW row = mysql_fetch_row( result );
-
- // obtain ID and return
- return atol( row[0] );
-}
-
-// read tags from the mp3 file and store them into the corresponding database entry
-void update_db( long uid, string filename )
-{
- TagLib::String title, album, artist, genre, cddbid;
- uint trackno, year;
-
- // ID3_Tag filetag( filename.c_str() );
- TagLib::FileRef f( filename.c_str() );
-
- if( !f.isNull() && f.tag() )
- {
- // cout << "Evaluating " << filename << 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();
-
- 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, "%d-%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 = 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, "%d-%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 = 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=\"%s\", sourceid=\"%s\", mp3file=\"%s\""
- "WHERE id=%d", artist.toCString(), title.toCString(), year, cddbid.toCString(), filename.c_str(), uid );
- }
- else
- { // the entry does not exist, create it
- // int t = title.find( "'" );
- // int a = artist.find( "'" );
- mgSqlWriteQuery( db,
- "INSERT INTO tracks (artist,title,genre1,genre2,year,sourceid,tracknb,mp3file)"
- " VALUES (\"%s\", \"%s\", \"\", \"\", %d, \"%s\", %d, \"%s\")",
- artist.toCString(), title.toCString(), year, cddbid.toCString(), trackno, filename.c_str() );
- /*
- cout << "-- TAG --" << endl;
- cout << "title - \"" << tag->title() << "\"" << endl;
- cout << "artist - \"" << tag->artist() << "\"" << endl;
- cout << "album - \"" << tag->album() << "\"" << endl;
- cout << "year - \"" << tag->year() << "\"" << endl;
- cout << "comment - \"" << tag->comment() << "\"" << endl;
- cout << "track - \"" << tag->track() << "\"" << endl;
- cout << "genre - \"" << tag->genre() << "\"" << endl;
- */
- }
- }
-}
-
-void update_tags( long uid, string filename )
-{
-
-}
-
-void evaluate_file( MYSQL *db, string filename )
-{
- if( 0 == init_database() )
- {
- // 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
- /*
- // 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 );
- }
- }
-}
-
-int main( int argc, char *argv[] )
-{
- int option_index;
- string filename;
-
- if( argc < 2 )
- { // we need at least a filename!
- cout << "mugglei -- import helper for Muggle VDR plugin" << endl;
- cout << "(C) Lars von Wedel" << endl;
- cout << "This is free software; see the source for copying conditions." << endl;
- cout << "" << endl;
- cout << "Options:" << endl;
- cout << " -h <hostname> - specify host of mySql database server (default is 'localhost')" << endl;
- cout << " -n <database> - specify database name (default is 'GiantDisc')" << endl;
- cout << " -u <username> - specify user of mySql database (default is empty)" << endl;
- cout << " -p <password> - specify password of user (default is empty password)" << endl;
- cout << " -f <filename> - name of music file to import" << endl;
- cout << " -a - import track as if it was on an assorted album" << endl;
-
- exit( 1 );
- }
-
- // option defaults
- host = "localhost";
- dbname = "GiantDisc";
- user = "";
- pass = "";
- import_assorted = false;
-
- // parse command line options
- while( 1 )
- {
- int c = getopt(argc, argv, "h:u:p:n:af:");
-
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- { // long option
-
- } break;
- case 'h':
- {
- host = optarg;
- } break;
- case 'u':
- {
- user = optarg;
- } break;
- case 'p':
- {
- pass = optarg;
- } break;
- case 'd':
- {
- dbname = optarg;
- } break;
- case 'a':
- {
- import_assorted = true;
- } break;
- case 'f':
- {
- filename = optarg;
- } break;
- }
- }
-
- // init random number generator
- struct timeval tv;
- struct timezone tz;
- gettimeofday( &tv, &tz );
- srandom( tv.tv_usec );
-
- int res = init_database();
-
- if( !res )
- {
- update_db( 0, filename );
- }
- else
- {
- cout << "Database initialization failed. Exiting.\n" << endl;
- }
-
- return res;
-}
-
+
+#include <string>
+using namespace std;
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <mysql/mysql.h>
+
+#include <taglib/tag.h>
+#include <taglib/fileref.h>
+
+#include "mg_tools.h"
+
+MYSQL *db;
+
+string host, user, pass, dbname;
+bool import_assorted;
+
+int init_database()
+{
+ db = mysql_init(NULL);
+ if( db == NULL )
+ {
+ return -1;
+ }
+
+ if( mysql_real_connect( db, host.c_str(), user.c_str(), pass.c_str(), dbname.c_str(),
+ 0, NULL, 0 ) == NULL )
+ {
+ return -2;
+ }
+
+ return 0;
+}
+
+time_t get_fs_modification_time( string filename )
+{
+ struct stat *buf = (struct stat*) malloc( sizeof( struct stat ) );
+
+ // yes: obtain modification date for file and db entry
+ int statres = stat( filename.c_str(), buf );
+
+ time_t mod = buf->st_mtime;
+ free( buf );
+
+ return mod;
+}
+
+time_t get_db_modification_time( long uid )
+{
+ time_t mt;
+
+ MYSQL_RES *result = mgSqlReadQuery( db, "SELECT modification_time FROM tracks WHERE id=\"%d\"", uid );
+ MYSQL_ROW row = mysql_fetch_row( result );
+
+ string mod_time = row[0];
+ mt = (time_t) atol( mod_time.c_str() );
+
+ return mt;
+}
+
+TagLib::String escape_string( MYSQL *db, TagLib::String s )
+{
+ char *buf = strdup( s.toCString() );
+ char *escbuf = (char *) malloc( 2*strlen( buf ) + 1 );
+
+ int len = mysql_real_escape_string( db, escbuf, buf, strlen( buf ) );
+
+ return TagLib::String( escbuf );
+}
+
+long find_file_in_database( MYSQL *db, string filename )
+{
+ 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() );
+ MYSQL_ROW row = mysql_fetch_row( result );
+
+ // obtain ID and return
+ return atol( row[0] );
+}
+
+// read tags from the mp3 file and store them into the corresponding database entry
+void update_db( long uid, string filename )
+{
+ TagLib::String title, album, artist, genre, cddbid;
+ uint trackno, year;
+
+ // ID3_Tag filetag( filename.c_str() );
+ TagLib::FileRef f( filename.c_str() );
+
+ if( !f.isNull() && f.tag() )
+ {
+ // cout << "Evaluating " << filename << 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();
+
+ 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, "%d-%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 = 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, "%d-%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 = 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=\"%s\","
+ "sourceid=\"%s\", mp3file=\"%s\", length=%d, bitrate=\"%d\","
+ "samplerate=%d, channels=%d WHERE id=%d",
+ artist.toCString(), title.toCString(), year,
+ cddbid.toCString(), filename.c_str(), len, bitrate,
+ sample, channels, uid );
+ }
+ else
+ { // the entry does not exist, create it
+ mgSqlWriteQuery( db,"INSERT INTO tracks (artist,title,genre1,genre2,year,"
+ "sourceid,tracknb,mp3file,length,bitrate,samplerate,channels)"
+ " VALUES (\"%s\", \"%s\", \"\", \"\", %d, \"%s\", %d, \"%s\", %d, \"%d\", %d, %d)",
+ artist.toCString(), title.toCString(), year, cddbid.toCString(),
+ trackno, filename.c_str(), len, bitrate, sample, channels );
+ /*
+ cout << "-- TAG --" << endl;
+ cout << "title - \"" << tag->title() << "\"" << endl;
+ cout << "artist - \"" << tag->artist() << "\"" << endl;
+ cout << "album - \"" << tag->album() << "\"" << endl;
+ cout << "year - \"" << tag->year() << "\"" << endl;
+ cout << "comment - \"" << tag->comment() << "\"" << endl;
+ cout << "track - \"" << tag->track() << "\"" << endl;
+ cout << "genre - \"" << tag->genre() << "\"" << endl;
+ */
+ }
+ }
+}
+
+void update_tags( long uid, string filename )
+{
+
+}
+
+void evaluate_file( MYSQL *db, string filename )
+{
+ if( 0 == init_database() )
+ {
+ // 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
+ /*
+ // 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 );
+ }
+ }
+}
+
+int main( int argc, char *argv[] )
+{
+ int option_index;
+ string filename;
+
+ if( argc < 2 )
+ { // we need at least a filename!
+ cout << "mugglei -- import helper for Muggle VDR plugin" << endl;
+ cout << "(C) Lars von Wedel" << endl;
+ cout << "This is free software; see the source for copying conditions." << endl;
+ cout << "" << endl;
+ cout << "Options:" << endl;
+ cout << " -h <hostname> - specify host of mySql database server (default is 'localhost')" << endl;
+ cout << " -n <database> - specify database name (default is 'GiantDisc')" << endl;
+ cout << " -u <username> - specify user of mySql database (default is empty)" << endl;
+ cout << " -p <password> - specify password of user (default is empty password)" << endl;
+ cout << " -f <filename> - name of music file to import" << endl;
+ cout << " -a - import track as if it was on an assorted album" << endl;
+
+ exit( 1 );
+ }
+
+ // option defaults
+ host = "localhost";
+ dbname = "GiantDisc";
+ user = "";
+ pass = "";
+ import_assorted = false;
+
+ // parse command line options
+ while( 1 )
+ {
+ int c = getopt(argc, argv, "h:u:p:n:af:");
+
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ { // long option
+
+ } break;
+ case 'h':
+ {
+ host = optarg;
+ } break;
+ case 'u':
+ {
+ user = optarg;
+ } break;
+ case 'p':
+ {
+ pass = optarg;
+ } break;
+ case 'd':
+ {
+ dbname = optarg;
+ } break;
+ case 'a':
+ {
+ import_assorted = true;
+ } break;
+ case 'f':
+ {
+ filename = optarg;
+ } break;
+ }
+ }
+
+ // init random number generator
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday( &tv, &tz );
+ srandom( tv.tv_usec );
+
+ int res = init_database();
+
+ if( !res )
+ {
+ update_db( 0, filename );
+ }
+ else
+ {
+ cout << "Database initialization failed. Exiting.\n" << endl;
+ }
+
+ return res;
+}
+