#define _GNU_SOURCE#include <stdio.h>#include <string.h>#include <libgen.h>#include <sys/stat.h>#include <errno.h>#include <stdio.h>#include "library.h"#include "audio.h"#include "lastfm.h"#include "helper.h"#include <dbi/dbi.h>#include <semaphore.h>#include "database.h"/*INSERT INTO Album (name,dir,artist) SELECT 'So Farrrr',467,88 from Album WHERE NOT EXISTS ( SELECT * from Album WHERE name='So Farrrr' AND artist='88' ) limit 1*/void *vmalloc(const char *marker,size_t size){// printf("Malloc:%s: %lub - %lukb\n",marker,size,size/1024); return malloc(size);}char qbuffer[1024];/* Library global mutex */extern sem_t mutex;extern dbi_conn DB_conn;int LIBRARY_get_stat(char *buffer){ dbi_result result; int rv; long long album_count=0,artist_count=0,track_count=0; result = dbi_conn_query(DB_conn,"SELECT COUNT(id) FROM Artist"); rv = dbi_result_first_row(result); artist_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); result = dbi_conn_query(DB_conn,"SELECT COUNT(id) FROM Album"); rv = dbi_result_first_row(result); album_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); result = dbi_conn_query(DB_conn,"SELECT COUNT(id) FROM Tags"); rv = dbi_result_first_row(result); track_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); sprintf(buffer,"%lli Tracks\n%lli Artists\n%lli Albums", track_count,artist_count,album_count); return 0;}int LIBRARY_get_url_from_tagid(long long tag_id,char *buffer){ dbi_result result; int rv; result = dbi_conn_queryf(DB_conn,"SELECT \ CONCAT(Directories.name,'/',filename) \ FROM Tags JOIN Directories ON Tags.dir = Directories.id \ WHERE Tags.id=%lli",tag_id); rv = dbi_result_first_row(result); strcpy(buffer,dbi_result_get_string_idx(result,1)); dbi_result_free(result); return 0;}/* Returns a NULL terminated array of path strings */long long LIBRARY_get_paths(char ***paths){ dbi_result result=NULL; char **buffer=NULL; long long size; const char *error=NULL; /* MUTEX */ sem_wait(&mutex); result = dbi_conn_query(DB_conn,"SELECT path FROM LibraryPath"); if(result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_get_path:%s\n",error); sem_post(&mutex); return 0; } size = dbi_result_get_numrows(result); buffer = malloc( sizeof(char *) * (size + 1) ); buffer[size] = NULL; int i=0; while(dbi_result_next_row(result)){ buffer[i++]=dbi_result_get_string_copy_idx(result,1); } dbi_result_free(result); sem_post(&mutex); *paths = buffer; return size;}int LIBRARY_get_artist_name(long long album_id, char **empty){ char *buffer=NULL; dbi_result result=NULL; /* MUTEX */ sem_wait(&mutex); result = dbi_conn_queryf(DB_conn,"SELECT Artist.name \ FROM Artist \ JOIN Album_Artist ON Artist.id = Album_Artist.artist_id \ JOIN Album ON Album.id = Album_Artist.album_id \ WHERE Album.id=%llu",album_id); if(dbi_result_first_row(result)){ buffer = DB_strdup(result,1); } dbi_result_free(result); sem_post(&mutex); *empty = buffer; return 0;}int LIBRARY_free_artist_metadata(LIBRARY_artist_metadata *l){ int i,j; if(l == NULL)return 1; for(i=0;i<l->album_count;i++){ for(j=0;j<l->album[i]->track_count;j++){ free(l->album[i]->tracks[j]); } free(l->album[i]->tracks); free(l->album[i]); } free(l->album); free(l); return 0;}int LIBRARY_free_album_metadata_array(LIBRARY_album_metadata **l, long long size){ unsigned int i,j; if(l == NULL)return 1; for(i=0;i<size;i++){ if(l[i]->tracks){ for(j=0;j<l[i]->track_count;j++){ free(l[i]->tracks[j]); } free(l[i]->tracks); } free(l[i]); } free(l); return 0;}int LIBRARY_free_artist_metadata_array(LIBRARY_artist_metadata **l,long long size){ int i,j,k; if(l == NULL)return 1; for(i=0;i<size;i++){ for(j=0;j<l[i]->album_count;j++){ for(k=0;k<l[i]->album[j]->track_count;k++){ free(l[i]->album[j]->tracks[k]); } free(l[i]->album[j]->tracks); free(l[i]->album[j]); } free(l[i]->album); free(l[i]); } free(l); return 0;}int LIBRARY_free_album_metadata(LIBRARY_album_metadata *l){ unsigned int j; if(l== NULL)return 1; for(j=0;j<l->track_count;j++){ free(l->tracks[j]); } free(l->tracks); free(l); return 0;}int LIBRARY_free_track_metadata(LIBRARY_track_metadata *lib){ if(lib)free(lib); return 0;}void LIBRARY_print_artist_metadata(LIBRARY_artist_metadata **lib,long long size){ int i,j,k; printf("LIBRARY_print_artist_metadata: Size = %lli\n",size); for(i=0;i<size;i++){ printf("[%4lli] %s\n",lib[i]->id,lib[i]->name); for(j=0;j<lib[i]->album_count;j++){ printf(" +--[%4lli] %s\n",lib[i]->album[j]->id, lib[i]->album[j]->name); for(k=0;k<lib[i]->album[j]->track_count;k++){ printf(" |--[%5lli] %s\n", lib[i]->album[j]->tracks[k]->id, lib[i]->album[j]->tracks[k]->name); } } }}int LIBRARY_get_track(LIBRARY_track_metadata **lib, long long tag_id){ dbi_result result; printf("LIBRARY_get_track: %llu\n",tag_id); result = dbi_conn_queryf(DB_conn, "SELECT year,track,length,title,Artist.id,Artist.name,Album.id,Album.name \ FROM Tags \ JOIN Artist ON Artist.id = Tags.artist \ JOIN Album ON Album.id = Tags.album \ WHERE Tags.id=%llu",tag_id); if(dbi_result_next_row(result)){ *lib = malloc(sizeof(LIBRARY_track_metadata)); (*lib)->year = dbi_result_get_short_idx(result,1); (*lib)->track = dbi_result_get_short_idx(result,2); (*lib)->length = dbi_result_get_short_idx(result,3); strcpy((*lib)->name,dbi_result_get_string_idx(result,4)); (*lib)->artist_id = dbi_result_get_ulonglong_idx(result,5); DB_strcpy((*lib)->artist_name,result,6); (*lib)->album_id = dbi_result_get_ulonglong_idx(result,7); DB_strcpy((*lib)->album_name,result,8); (*lib)->id = tag_id; dbi_result_free(result); }else{ return 1; } return 0;}long long LIBRARY_get_va_album(LIBRARY_album_metadata **lib, long long album_id){ dbi_result result; long long size; int i; LIBRARY_track_metadata *tptr; LIBRARY_album_metadata *album; /* MUTEX */ sem_wait(&mutex); printf("LIBRARY_get_va_album: %llu\n",album_id); result = dbi_conn_queryf(DB_conn, "SELECT Album.name,!ISNULL(data) \ FROM Album \ JOIN Album_Artist ON Album_Artist.album_id = Album.id \ JOIN Artist ON Artist.id = Album_Artist.artist_id \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ WHERE Album.id=%llu \ AND Album.VA=1",album_id); size = dbi_result_get_numrows(result); if(dbi_result_next_row(result)){ album = malloc(sizeof(LIBRARY_album_metadata)); DB_strcpy(album->name,result,1); album->has_art = dbi_result_get_short_idx(result,2); album->id = album_id; album->artist_id = 0; album->length = 0; album->va = 1; dbi_result_free(result); }else { sem_post(&mutex); return 0; } result = dbi_conn_queryf(DB_conn, "SELECT Tags.id,year,length,track,title,Artist.name,Artist.id \ FROM Tags \ JOIN Artist ON Artist.id = Tags.artist \ WHERE album=%llu \ ORDER BY track",album_id); album->track_count = dbi_result_get_numrows(result); album->tracks = malloc(album->track_count * sizeof(LIBRARY_track_metadata*)); i=0; while (dbi_result_next_row(result)) { album->tracks[i] = malloc(sizeof(LIBRARY_track_metadata)); tptr = album->tracks[i]; tptr->id = dbi_result_get_ulonglong_idx(result,1); tptr->year = dbi_result_get_int_idx(result,2); tptr->length = dbi_result_get_int_idx(result,3); tptr->track= dbi_result_get_short_idx(result,4); strcpy(tptr->name,dbi_result_get_string_idx(result,5)); DB_strcpy(tptr->artist_name,result,6); tptr->artist_id = dbi_result_get_ulonglong_idx(result,7); tptr->album_id = album_id; album->length += tptr->length; i++; } dbi_result_free(result); *lib = album; sem_post(&mutex); return album->track_count;}long long LIBRARY_get_latest_albums(LIBRARY_album_metadata ***lib){ dbi_result result=NULL,sub_result=NULL; const char *error=NULL; long long size=0; int i,j; LIBRARY_album_metadata **albums; LIBRARY_track_metadata *tptr; /* MUTEX */ sem_wait(&mutex); result = dbi_conn_query(DB_conn, "SELECT Album.id,Album.VA,!ISNULL(data),Album.name,Artist.id,Artist.name \ FROM Tags \ JOIN Album ON Album.id = Tags.album \ JOIN Artist ON Artist.id = Tags.artist \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ GROUP BY album ORDER BY Album.mtime DESC LIMIT 5"); if(result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_get_latest_albums:%s\n",error); sem_post(&mutex); return 0; } size = dbi_result_get_numrows(result); albums = malloc(sizeof(LIBRARY_artist_metadata*)*size); i=0; while(dbi_result_next_row(result)){ albums[i]=malloc(sizeof(LIBRARY_album_metadata)); albums[i]->id = dbi_result_get_longlong_idx(result,1); albums[i]->va = dbi_result_get_short_idx(result,2); albums[i]->has_art = dbi_result_get_short_idx(result,3); DB_strcpy(albums[i]->name,result,4); albums[i]->length =0; sub_result = NULL; if(!albums[i]->va){ albums[i]->artist_id = dbi_result_get_longlong_idx(result,5); DB_strcpy(albums[i]->artist_name,result,6); sub_result = dbi_conn_queryf(DB_conn, "SELECT id,year,length,track,title \ FROM Tags \ WHERE album=%llu AND artist=%llu \ ORDER BY track", albums[i]->id,albums[i]->artist_id); }else { albums[i]->artist_id=0; sub_result = dbi_conn_queryf(DB_conn, "SELECT id,year,length,track,title,artist \ FROM Tags \ WHERE album=%llu \ ORDER BY track", albums[i]->id); } if(sub_result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_get_latest_albums:%s\n",error); dbi_result_free(result); sem_post(&mutex); return 0; } albums[i]->track_count = dbi_result_get_numrows(sub_result); albums[i]->tracks = malloc(albums[i]->track_count * sizeof(LIBRARY_track_metadata*)); j=0; while (dbi_result_next_row(sub_result)) { albums[i]->tracks[j] = malloc(sizeof(LIBRARY_track_metadata)); tptr = albums[i]->tracks[j]; tptr->id = dbi_result_get_ulonglong_idx(sub_result,1); tptr->year = dbi_result_get_int_idx(sub_result,2); tptr->length = dbi_result_get_int_idx(sub_result,3); tptr->track= dbi_result_get_short_idx(sub_result,4); strcpy(tptr->name,dbi_result_get_string_idx(sub_result,5)); tptr->album_id = albums[i]->id; if(albums[i]->va){ tptr->artist_id = dbi_result_get_longlong_idx(sub_result,6); }else{ tptr->artist_id =0; } albums[i]->length += tptr->length; j++; } dbi_result_free(sub_result); i++; } dbi_result_free(result); sem_post(&mutex); *lib = albums; return size;}long long LIBRARY_get_album(LIBRARY_album_metadata **lib, long long artist_id, long long album_id){ dbi_result result; long long size; int i; LIBRARY_track_metadata *tptr; LIBRARY_album_metadata *album; /* MUTEX */ sem_wait(&mutex); printf("LIBRARY_get_album: %llu:%llu\n",artist_id,album_id); result = dbi_conn_queryf(DB_conn, "SELECT Artist.name,Album.name,!ISNULL(data) \ FROM Album \ JOIN Album_Artist ON Album_Artist.album_id = Album.id \ JOIN Artist ON Artist.id = Album_Artist.artist_id \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ WHERE Album.id=%llu AND Artist.id=%llu \ AND Album.VA=0",album_id,artist_id); size = dbi_result_get_numrows(result); if(dbi_result_next_row(result)){ album = malloc(sizeof(LIBRARY_album_metadata)); album->artist_id = artist_id; DB_strcpy(album->artist_name,result,1); DB_strcpy(album->name,result,2); album->has_art = dbi_result_get_short_idx(result,3); album->id = album_id; album->va = 0; album->length = 0; dbi_result_free(result); }else { sem_post(&mutex); return 0; } result = dbi_conn_queryf(DB_conn, "SELECT id,year,length,track,title \ FROM Tags \ WHERE album=%llu AND artist=%llu \ ORDER BY track",album_id,artist_id); album->track_count = dbi_result_get_numrows(result); album->tracks = malloc(album->track_count * sizeof(LIBRARY_track_metadata*)); i=0; while (dbi_result_next_row(result)) { album->tracks[i] = malloc(sizeof(LIBRARY_track_metadata)); tptr = album->tracks[i]; tptr->id = dbi_result_get_ulonglong_idx(result,1); tptr->year = dbi_result_get_int_idx(result,2); tptr->length = dbi_result_get_int_idx(result,3); tptr->track= dbi_result_get_short_idx(result,4); strcpy(tptr->name,dbi_result_get_string_idx(result,5)); tptr->album_id = 0; tptr->artist_id =0; album->length += tptr->length; i++; } dbi_result_free(result); *lib = album; sem_post(&mutex); return album->track_count;}long long LIBRARY_get_va_albums(LIBRARY_album_metadata ***lib, long long artist_id){ dbi_result result,sub_result; int i,j; long long size; LIBRARY_album_metadata **album; LIBRARY_track_metadata *tptr; /* MUTEX */ sem_wait(&mutex); result = dbi_conn_queryf(DB_conn, "SELECT Album.id,Album.name,!ISNULL(data) \ FROM Album \ JOIN Album_Artist ON Album_Artist.album_id = Album.id \ JOIN Artist ON Artist.id = Album_Artist.artist_id \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ WHERE Artist.id=%llu \ AND Album.VA=1 \ ORDER BY Album.name",artist_id); if(result == NULL){ sem_post(&mutex); return 0; } size = dbi_result_get_numrows(result); if(size ==0 ) { dbi_result_free(result); sem_post(&mutex); return 0; } printf("album_count = %lli\n",size); album = malloc(size*sizeof(LIBRARY_album_metadata*)); i=0;j=0; while (dbi_result_next_row(result)) { album[i] = malloc(sizeof(LIBRARY_album_metadata)); album[i]->id = dbi_result_get_ulonglong_idx(result,1); DB_strcpy(album[i]->name,result,2); album[i]->has_art = dbi_result_get_short_idx(result,3); album[i]->artist_id =0; album[i]->length =0; album[i]->va = 1;// printf("alib[i]->name = %s\n",album[i]->name); sub_result = dbi_conn_queryf(DB_conn, "SELECT id,year,length,track,title \ FROM Tags \ WHERE album=%llu \ ORDER BY track",album[i]->id,artist_id); album[i]->track_count = dbi_result_get_numrows(sub_result); album[i]->tracks = malloc(album[i]->track_count *sizeof(LIBRARY_track_metadata)); j=0; while (dbi_result_next_row(sub_result)) { album[i]->tracks[j] = malloc(sizeof(LIBRARY_track_metadata)); tptr = album[i]->tracks[j]; tptr->id = dbi_result_get_ulonglong_idx(sub_result,1); tptr->year = dbi_result_get_int_idx(sub_result,2); tptr->length = dbi_result_get_int_idx(sub_result,3); tptr->track= dbi_result_get_short_idx(sub_result,4); strcpy(tptr->name,dbi_result_get_string_idx(sub_result,5)); tptr->album_id = album[i]->id; tptr->artist_id = artist_id; album[i]->length += tptr->length; j++; } dbi_result_free(sub_result); i++; } dbi_result_free(result); sem_post(&mutex); *lib = album; return size;}long long LIBRARY_get_artist(LIBRARY_artist_metadata **lib, long long artist_id){ dbi_result result,sub_result; long long size; int i,j; LIBRARY_album_metadata **alib; LIBRARY_track_metadata *tptr; LIBRARY_artist_metadata *artist; /* MUTEX */ sem_wait(&mutex); printf("LIBRARY_get_artist: %llu\n",artist_id); result = dbi_conn_queryf(DB_conn, "SELECT Artist.id,Artist.name,!ISNULL(data) \ FROM Artist \ JOIN Album_Artist ON Artist.id = Album_Artist.artist_id \ JOIN Album ON Album_Artist.album_id = Album.id \ LEFT JOIN ArtistArt ON Artist.id = ArtistArt.artist_id \ WHERE Album.VA=0 AND Artist.id=%llu GROUP BY Artist.name", artist_id); if(dbi_result_next_row(result)){ artist = malloc(sizeof(LIBRARY_artist_metadata)); artist->id = dbi_result_get_ulonglong_idx(result,1); DB_strcpy(artist->name,result,2); artist->has_art = dbi_result_get_short_idx(result,3); }else{ sem_post(&mutex); return 0; } dbi_result_free(result); result = dbi_conn_queryf(DB_conn, "SELECT Album.id,Album.name,!ISNULL(data) \ FROM Album \ JOIN Album_Artist ON Album_Artist.album_id = Album.id \ JOIN Artist ON Artist.id = Album_Artist.artist_id \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ WHERE Artist.id=%llu \ AND Album.VA=0 \ ORDER BY Album.name",artist_id); size = dbi_result_get_numrows(result); artist->album_count = size; printf("album_count = %lli\n",size); artist->album = malloc(size*sizeof(LIBRARY_album_metadata*)); alib = artist->album; i=0;j=0; while (dbi_result_next_row(result)) { alib[i] = malloc(sizeof(LIBRARY_album_metadata)); alib[i]->id = dbi_result_get_ulonglong_idx(result,1); DB_strcpy(alib[i]->name,result,2); alib[i]->has_art = dbi_result_get_short_idx(result,3); alib[i]->artist_id = artist_id; alib[i]->va = 0;// printf("alib[i]->name = %s\n",alib[i]->name); sub_result = dbi_conn_queryf(DB_conn, "SELECT id,year,length,track,title \ FROM Tags \ WHERE album=%llu AND artist=%llu \ ORDER BY track",alib[i]->id,artist_id); alib[i]->track_count = dbi_result_get_numrows(sub_result); alib[i]->length =0; alib[i]->tracks = malloc(alib[i]->track_count *sizeof(LIBRARY_track_metadata)); j=0; while (dbi_result_next_row(sub_result)) { alib[i]->tracks[j] = malloc(sizeof(LIBRARY_track_metadata)); tptr = alib[i]->tracks[j]; tptr->id = dbi_result_get_ulonglong_idx(sub_result,1); tptr->year = dbi_result_get_int_idx(sub_result,2); tptr->length = dbi_result_get_int_idx(sub_result,3); tptr->track= dbi_result_get_short_idx(sub_result,4); strcpy(tptr->name,dbi_result_get_string_idx(sub_result,5)); tptr->artist_id = 0; tptr->album_id = 0; alib[i]->length += tptr->length; j++; } dbi_result_free(sub_result); i++; } dbi_result_free(result); *lib = artist; sem_post(&mutex); return size;}long long LIBRARY_get_all_va_albums(LIBRARY_album_metadata ***lib){ dbi_result result,sub_result; long long size; size_t length; unsigned int i,j; LIBRARY_track_metadata *track_ptr; /* MUTEX */ sem_wait(&mutex); result = dbi_conn_query(DB_conn,"SELECT name,id FROM Album \ WHERE VA=1 ORDER BY name"); size = dbi_result_get_numrows(result); printf("LIBRARY_get_all_va_albums: va_album_count = %llu\n",size); /* Allocate this massive buffer */ *lib = malloc(size*sizeof(LIBRARY_album_metadata*)); LIBRARY_album_metadata **va_lib = *lib; i=0; while (dbi_result_next_row(result)) { va_lib[i] = malloc(sizeof(LIBRARY_album_metadata)); DB_strcpy(va_lib[i]->name,result,1); va_lib[i]->id = dbi_result_get_ulonglong_idx(result,2); va_lib[i]->va = 1; sub_result = dbi_conn_queryf(DB_conn,"SELECT \ Tags.id,Tags.title,Tags.length,Tags.track,Artist.id,Artist.name \ FROM Tags JOIN Artist ON Tags.artist = Artist.id \ WHERE album=%llu \ ORDER BY track",va_lib[i]->id); va_lib[i]->length = 0; va_lib[i]->track_count = dbi_result_get_numrows(sub_result); va_lib[i]->tracks = malloc(va_lib[i]->track_count* sizeof(LIBRARY_track_metadata*)); for(j=0;j<va_lib[i]->track_count;j++){ dbi_result_next_row(sub_result); va_lib[i]->tracks[j] = malloc(sizeof(LIBRARY_track_metadata)); track_ptr = va_lib[i]->tracks[j]; track_ptr->id = dbi_result_get_ulonglong_idx(sub_result,1); track_ptr->index = j; track_ptr->track = dbi_result_get_short_idx(sub_result,4); length = DB_strcpy(track_ptr->name,sub_result,6); strcat(track_ptr->name," - "); DB_strcpy(track_ptr->name+length+3,sub_result,2); track_ptr->length = dbi_result_get_short_idx(sub_result,3); va_lib[i]->length += track_ptr->length; track_ptr->artist_id = dbi_result_get_ulonglong_idx(sub_result,5); track_ptr->album_id = va_lib[i]->id; } dbi_result_free(sub_result); i++; } dbi_result_free(result); sem_post(&mutex); return size;}/* Do not return artists that only appear in Various Artist albums*/long long LIBRARY_get_all_artists(LIBRARY_artist_metadata ***lib){ long long size; int i,j,k; int album_count,track_count; unsigned long long album_id,artist_id,track_id; LIBRARY_album_metadata *album_ptr; LIBRARY_track_metadata *track_ptr; /* MUTEX */ sem_wait(&mutex); dbi_result result,sub_result,temp_result; result = dbi_conn_query(DB_conn, "SELECT Artist.name,Artist.id,!ISNULL(data) FROM \ Artist \ JOIN Album_Artist ON Artist.id = Album_Artist.artist_id \ JOIN Album ON Album_Artist.album_id = Album.id \ LEFT JOIN ArtistArt ON Artist.id = ArtistArt.artist_id \ WHERE Album.VA!=1 GROUP BY Artist.name"); size = dbi_result_get_numrows(result); printf("LIBRARY_get_all_artists: artist_count = %llu\n",size); /* Allocate this massive buffer */ *lib = vmalloc("173",size*sizeof(LIBRARY_artist_metadata*)); LIBRARY_artist_metadata **artists_library = *lib; /* Copy out the data */ i=0; while (dbi_result_next_row(result)) { artists_library[i] = malloc(sizeof(LIBRARY_artist_metadata)); DB_strcpy(artists_library[i]->name,result,1); artist_id = dbi_result_get_ulonglong_idx(result,2); artists_library[i]->has_art = dbi_result_get_longlong_idx(result,3);// artists_library[i]->visible = 1; sub_result = dbi_conn_queryf(DB_conn,"SELECT Album.id,name,!ISNULL(data) \ FROM Album_Artist \ JOIN Album ON Album.id = Album_Artist.album_id \ JOIN Tags ON Tags.album = Album_Artist.album_id \ LEFT JOIN AlbumArt ON AlbumArt.album_id = Album.id \ WHERE artist_id=%llu AND VA!=1 GROUP BY name",artist_id); album_count = dbi_result_get_numrows(sub_result); artists_library[i]->index = i; artists_library[i]->id = artist_id; artists_library[i]->album_count = album_count; artists_library[i]->va_album_count = 0; artists_library[i]->va_album = NULL; //printf("[%20llu]%s\t has %u albums\n",artist_id,artists_library[i]->name,album_count); artists_library[i]->album = malloc(album_count* sizeof(LIBRARY_album_metadata*)); for(j=0;j<album_count;j++){ dbi_result_next_row(sub_result); artists_library[i]->album[j] = vmalloc("201",sizeof(LIBRARY_album_metadata)); album_ptr = artists_library[i]->album[j]; album_id = dbi_result_get_ulonglong_idx(sub_result,1); DB_strcpy(album_ptr->name,sub_result,2); album_ptr->has_art = dbi_result_get_longlong_idx(sub_result,3); album_ptr->length = 0; album_ptr->va = 0; temp_result = dbi_conn_queryf(DB_conn,"SELECT \ id,title,length,track FROM Tags \ WHERE album=%llu AND artist=%llu \ ORDER BY track",album_id,artist_id); track_count = dbi_result_get_numrows(temp_result); album_ptr->index = j; album_ptr->id = album_id; album_ptr->artist_id = artist_id; album_ptr->track_count = track_count; album_ptr->tracks = vmalloc("215",track_count * sizeof(LIBRARY_track_metadata*)); for(k=0;k<track_count;k++){ dbi_result_next_row(temp_result); album_ptr->tracks[k] = vmalloc("220",sizeof(LIBRARY_track_metadata)); track_ptr = album_ptr->tracks[k]; track_id = dbi_result_get_ulonglong_idx(temp_result,1); strcpy(track_ptr->name, dbi_result_get_string_idx(temp_result,2)); track_ptr->length = dbi_result_get_short_idx(temp_result,3); track_ptr->track = dbi_result_get_short_idx(temp_result,4); album_ptr->length += track_ptr->length; track_ptr->index = k; track_ptr->id = track_id; track_ptr->artist_id = 0; track_ptr->album_id = 0; } dbi_result_free(temp_result); } dbi_result_free(sub_result); i++; } dbi_result_free(result); sem_post(&mutex); return size;}long long LIBRARY_get_all_tracks(AUDIO_metadata ***lib){ long long size=0; unsigned int i=0; int rv=0; const char *title=NULL; int album_id,artist_id,dir_id; dbi_result result; dbi_result temp_result; result = dbi_conn_queryf(DB_conn,"SELECT title,artist,album,dir FROM Tags"); /* Get the size of the library */ size = dbi_result_get_numrows(result); printf("LIBRARY_get_all_tracks: Size = %llu\n",size); /* Allocate this massive buffer */ *lib = malloc(size*sizeof(AUDIO_metadata*)); AUDIO_metadata **library = *lib; /* Copy out the data */ while (dbi_result_next_row(result)) { library[i] = malloc(sizeof(AUDIO_metadata)); title = dbi_result_get_string_idx(result,1); artist_id = dbi_result_get_int_idx(result,2); album_id = dbi_result_get_int_idx(result,3); dir_id = dbi_result_get_int_idx(result,4); /* Look up the Artist name */ temp_result = dbi_conn_queryf(DB_conn, "SELECT name FROM Artist WHERE id=%llu",artist_id); rv =dbi_result_first_row(temp_result); if(rv){ DB_strcpy(library[i]->artist,temp_result,1); }else{ strcpy(library[i]->artist,"artist"); } dbi_result_free(temp_result); /* Look up the Album name */ temp_result = dbi_conn_queryf(DB_conn, "SELECT name FROM Album WHERE id=%llu AND dir=%llu", album_id,dir_id); rv = dbi_result_first_row(temp_result); if(rv){ DB_strcpy(library[i]->album,temp_result,1); }else{ strcpy(library[i]->album,"album"); } dbi_result_free(temp_result); strcpy(library[i]->title,title); i++; //printf("i=%i\n",i); if(i==size)break; } dbi_result_free(result); return size;}int LIBRARY_factor_VA(){ dbi_result result,sub_result,temp_result,t2_result; char *album_buffer; long long artist_id,album_id,album_dup_id; unsigned int artist_count,distinct_count; int i; /* MUTEX */ sem_wait(&mutex); /* Stag1-A: Find all duplicate Album Names */ result = dbi_conn_query(DB_conn,"SELECT id,name FROM Album GROUP BY \ name HAVING (COUNT(name)>1)"); while(dbi_result_next_row(result)){ album_id = dbi_result_get_ulonglong_idx(result,1); album_buffer = DB_quote_strdup(result,2); /* Stage1-B: Find all the artists who belong to this album */ sub_result = dbi_conn_queryf(DB_conn, "SELECT DISTINCT artist_id FROM Album_Artist JOIN \ Album ON Album_Artist.album_id = Album.id \ WHERE Album.name=%s", album_buffer); distinct_count = dbi_result_get_numrows(sub_result); dbi_result_free(sub_result); /* Stage1-C: Is this album a 'single artist' album? * Perhaps duplicated because it appeared in separate folders? */ if(distinct_count == 1){ va_duplicate: // distinct_count > 1 /* Update Tags */ sub_result = dbi_conn_queryf(DB_conn, "UPDATE Tags SET album=%llu WHERE album IN \ (SELECT id FROM Album WHERE name=%s AND id!=%llu)", album_id,album_buffer,album_id); dbi_result_free(sub_result); /* Update Album_Artist */ sub_result = dbi_conn_queryf(DB_conn, "UPDATE Album_Artist SET album_id=%llu \ WHERE album_id IN \ (SELECT id FROM Album WHERE name=%s AND id!=%llu)", album_id,album_buffer,album_id); dbi_result_free(sub_result); /* Now delete from Album */ sub_result = dbi_conn_queryf(DB_conn, "DELETE FROM Album WHERE name=%s AND id!=%llu", album_buffer,album_id); dbi_result_free(sub_result); printf("LIBRARY_factor_VA: Single Duplicate: id=%llu:%s\n", album_id,album_buffer); }else { /* This album could either be; * -1- Multiple "Best of" albums or * -2- Various Artist albums split over multiple directories or * -3- Multiple Various Artist albums with the same name, * eg. "Summer Hits" (UK), and "Summer Hits" (USA) */ /* Stage1-D: Find the Various Artists (case 2 and 3) * FIXME: Limitation: assume no two VA Albums with the same name */ sub_result = dbi_conn_queryf(DB_conn,"SELECT id \ FROM Album WHERE name=%s",album_buffer); distinct_count = dbi_result_get_numrows(sub_result); /* Each albun must have more than one distinct artist * should probably check dir too */ i=0; while(dbi_result_next_row(sub_result)){ album_dup_id = dbi_result_get_ulonglong_idx(result,1); temp_result = dbi_conn_queryf(DB_conn, "SELECT DISTINCT artist_id \ FROM Album_Artist WHERE album_id=%llu", album_id); if(dbi_result_get_numrows(temp_result)>1)i++; dbi_result_free(temp_result); } dbi_result_free(sub_result); /* Did all the duplicate albums have more than one * distinct artist ? */ if(i==distinct_count){ printf("LIBRARY_factor_VA: VA_Duplicate = %s\n", album_buffer); /* delete the sucker */ goto va_duplicate; }else{ // Some of the albums we guessed as VA Albums had a single artist printf("LIBRARY_factor_VA: Wrong Guess = %s\n", album_buffer); } } // if distinct_count == 1 free(album_buffer); } // top while loop dbi_result_free(result); /* Stage2-A: Mark all VA Albums */ result = dbi_conn_query(DB_conn,"UPDATE Album SET VA=1 \ WHERE id IN(SELECT album_id FROM Album_Artist GROUP BY Album_id \ HAVING COUNT(DISTINCT artist_id)>1)"); dbi_result_free(result); /* Remove the VA flag from the exception */ //result = dbi_conn_query(DB_conn,"UPDATE Album SET VA=0 WHERE name=''"); result = dbi_conn_query(DB_conn,"UPDATE Album SET VA=0 WHERE name='' OR name='Unknown'"); dbi_result_free(result); /* Stage3-A: Find all Artists that have more than 1 Non-VA album with the same name */ // TODO: Should we just allow this? result = dbi_conn_query(DB_conn,"SELECT Artist.id,COUNT(Album.name) AS n \ FROM Artist \ JOIN Album_Artist ON Artist.id = Album_Artist.artist_id \ JOIN Album ON Album.id = Album_Artist.album_id \ WHERE VA=0 \ GROUP BY Artist.name \ HAVING COUNT(DISTINCT(Album.name))<n"); artist_count = dbi_result_get_numrows(result); while(dbi_result_next_row(result)){ artist_id = dbi_result_get_ulonglong_idx(result,1); /* Stage3-B: Find the names of the duplicated albums */ sub_result = dbi_conn_queryf(DB_conn, "SELECT Album.id,Album.name \ FROM Artist \ JOIN Album_Artist ON Artist.id = Album_Artist.artist_id \ JOIN Album ON Album.id = Album_Artist.album_id \ WHERE Artist.id=%llu AND VA=0 \ GROUP BY Album.name HAVING COUNT(Album.name)>1",artist_id); while(dbi_result_next_row(sub_result)){ album_id = dbi_result_get_ulonglong_idx(sub_result,1); album_buffer = DB_quote_strdup(sub_result,2); /* Stage3-C: Get the IDs for all the dupes */ temp_result = dbi_conn_queryf(DB_conn, "SELECT Album.id \ FROM Album \ JOIN Album_Artist ON Album.id = Album_Artist.album_id \ JOIN Artist ON Artist.id = Album_Artist.artist_id \ WHERE Artist.id=%llu AND Album.name=%s AND Album.id!=%llu", artist_id,album_buffer,album_id); //FIXME: Setup ON UPDATE/DELETE CASCADE table constraints while(dbi_result_next_row(temp_result)){ album_dup_id = dbi_result_get_ulonglong_idx(temp_result,1); /* Update Tags */ t2_result = dbi_conn_queryf(DB_conn,"UPDATE Tags \ SET album=%llu WHERE album=%llu",album_id,album_dup_id); dbi_result_free(t2_result); /* Delete from Album */ t2_result = dbi_conn_queryf(DB_conn,"DELETE FROM Album \ WHERE id=%llu",album_dup_id); dbi_result_free(t2_result); /* Delete from Album_Artist relation table */ t2_result = dbi_conn_queryf(DB_conn,"DELETE FROM Album_Artist \ WHERE album_id=%llu",album_dup_id); dbi_result_free(t2_result); printf("LIBRARY_factor_VA: Single Duplicate: id=%llu:%s\n", album_id,album_buffer); } dbi_result_free(temp_result); free(album_buffer); } dbi_result_free(sub_result); } dbi_result_free(result); sem_post(&mutex); return 0;}int LIBRARY_get_image_blob(long long artist_id, long long album_id, unsigned char **data,size_t *length){ dbi_result result=NULL; /* MUTEX */ sem_wait(&mutex); if(album_id){ printf("LIBRARY_get_image_blob: album_id=%llu\n",album_id); result = dbi_conn_queryf(DB_conn,"SELECT data FROM AlbumArt \ WHERE album_id=%llu",album_id); }else if (artist_id){ printf("LIBRARY_get_image_blob: artist_id=%llu\n",artist_id); result = dbi_conn_queryf(DB_conn,"SELECT data FROM ArtistArt \ WHERE artist_id=%llu",artist_id); } if(result == NULL){ sem_post(&mutex); return 1; } if( !dbi_result_next_row(result) ){ dbi_result_free(result); sem_post(&mutex); return 1; } *data = (unsigned char *) dbi_result_get_binary_copy_idx(result,1); *length = dbi_result_get_field_length_idx(result,1); dbi_result_free(result); sem_post(&mutex); return 0;}int LIBRARY_add_artist_info(long long artist_id, LASTFM_ARTIST_INFO *a){ char *quote=NULL; dbi_result result,sub_result; const char *error; long long smallsum; long long sartist_id; int rv; int i; if(a== NULL)return 1; if(artist_id == 0) return 1; /* MUTEX */ sem_wait(&mutex); if(a->image_size!= 0){ rv = dbi_conn_quote_binary_copy(DB_conn,a->image, a->image_size,(unsigned char **)"e); smallsum = HELPER_hash(a->image,a->image_size); if(rv == 0){ if(quote)free(quote); dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_add_artist_info:%s\n",error); sem_post(&mutex); return 1; } result = dbi_conn_queryf(DB_conn,"INSERT INTO ArtistArt \ (artist_id,data,smallsum) VALUES(%llu,%s,%llu)",artist_id,quote,smallsum); free(quote); if(result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_add_artist_info:%s\n",error); sem_post(&mutex); return 1; } dbi_result_free(result); } if(a->similar){ for(i=0;a->similar[i];i++){ rv = dbi_conn_quote_string_copy(DB_conn, a->similar[i],"e); /* Look up the artist in our artist table */ result = dbi_conn_queryf(DB_conn,"SELECT id FROM Artist \ WHERE name=%s",quote); free(quote); if( dbi_result_first_row(result) == 1){ sartist_id = dbi_result_get_ulonglong_idx(result,1); /* Add the relationship to the SimilarArtist table */ sub_result = dbi_conn_queryf(DB_conn,"INSERT \ IGNORE INTO SimilarArtist (artist_id,sartist_id) \ VALUES(%llu,%llu)",artist_id,sartist_id); if(sub_result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr, "LIBRARY_add_artist_info:%s\n",error); dbi_result_free(result); sem_post(&mutex); return 1; } dbi_result_free(sub_result); } dbi_result_free(result); } } if(a->summary){ rv = dbi_conn_quote_string_copy(DB_conn,a->summary,"e); result = dbi_conn_queryf(DB_conn,"UPDATE Artist \ SET summary=%s WHERE id=%llu",quote,artist_id); free(quote); if(result == NULL){ dbi_conn_error(DB_conn,&error); fprintf(stderr,"LIBRARY_add_artist_info:%s\n",error); sem_post(&mutex); return 1; } dbi_result_free(result); } sem_post(&mutex); return 0;}int LIBRARY_add_image_blob(long long artist_id,long long album_id, unsigned char *data,size_t length){ unsigned char *quote; int rv; dbi_result result=NULL; long long smallsum; const char *err; printf("LIBRARY_add_image_blob:%llu:%llu:%pi:%lu\n",artist_id,album_id,data,length); /* MUTEX */ sem_wait(&mutex); rv = dbi_conn_quote_binary_copy(DB_conn,(unsigned char *)data,length,"e); if(rv == 0){ // something happened sem_post(&mutex); return 1; } smallsum = HELPER_hash(data,length); if(album_id){ result = dbi_conn_queryf(DB_conn,"INSERT INTO AlbumArt \ (album_id,smallsum,data) VALUES(%llu,%llu,%s)",album_id,smallsum,quote); }else if(artist_id){ result = dbi_conn_queryf(DB_conn,"INSERT INTO ArtistArt \ (artist_id,smallsum,data) VALUES(%llu,%llu,%s)",artist_id,smallsum,quote); }else { printf("LIBRARY_add_image_blob: Invalid Input\n"); free(quote); sem_post(&mutex); return 1; } if(result == NULL){ dbi_conn_error(DB_conn,&err); printf("ERROR: LIBRARY_add_image_blob: %s\n",err); } free(quote); dbi_result_free(result); sem_post(&mutex); return 0;}int LIBRARY_add_image_filename(long long artist_id,long long album_id, char *filename){ dbi_result result; char *quote; int rv; /* MUTEX */ sem_wait(&mutex); rv = dbi_conn_quote_string_copy(DB_conn,filename,"e); if(rv == 0){ // something happened sem_post(&mutex); return 1; } /* Album Art is sent with both artist and album */ if(album_id){ result = dbi_conn_queryf(DB_conn,"INSERT INTO AlbumArt \ (album_id,filename) VALUES(%llu,%s)",album_id,quote); }else if (artist_id){ result = dbi_conn_queryf(DB_conn,"INSERT INTO ArtistArt \ (artist_id,filename) VALUES(%llu,%s)",artist_id,quote); }else { printf("LIBRARY_add_image_filename: Invalid Input\n"); free(quote); sem_post(&mutex); return 1; } free(quote); dbi_result_free(result); sem_post(&mutex); return 0;}void LIBRARY_delete_file(AUDIO_SESSION *s, char *fullpath){ char *base=NULL; char *dir=NULL; dbi_result result=NULL; long long artist_id,album_id,dir_id,tag_id; long long file_count,song_count,album_count; /* MUTEX */ sem_wait(&mutex); /* Check if file exists */ if( dbi_conn_quote_string_copy(DB_conn,basename(fullpath),&base) && dbi_conn_quote_string_copy(DB_conn,dirname(fullpath),&dir) ){ result = dbi_conn_queryf(DB_conn,"SELECT \ Tags.artist,Tags.album,Directories.id,Tags.id \ FROM Tags \ JOIN Directories ON Directories.id = Tags.dir \ WHERE Tags.filename=%s AND Directories.name=%s", base,dir); free(base); free(dir); }else goto skip; /* If it doesnt exist in our db forget about it */ if(result == NULL) goto skip; if(!dbi_result_first_row(result)) goto skip; /* Read Tag row then delete Tag row */ artist_id = dbi_result_get_longlong_idx(result,1); album_id = dbi_result_get_longlong_idx(result,2); dir_id = dbi_result_get_longlong_idx(result,3); tag_id = dbi_result_get_longlong_idx(result,4); dbi_result_free(result); /* Delete the Tag */ result = dbi_conn_queryf(DB_conn,"DELETE FROM Tags WHERE id=%llu",tag_id); dbi_result_free(result); /* If this album doesnt have anymore songs, delete the album */ result = dbi_conn_queryf(DB_conn,"SELECT Count(Tags.id) FROM Tags \ WHERE album=%llu AND artist=%llu AND id!=%llu", album_id,artist_id,tag_id); if( result == NULL || !dbi_result_first_row(result) ) goto skip; song_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); if(song_count == 0){ result = dbi_conn_queryf(DB_conn,"DELETE FROM Album \ WHERE id=%llu",album_id); dbi_result_free(result); } /* If this artist doesnt have anymore albums, delete the artist too */ result = dbi_conn_queryf(DB_conn, "SELECT COUNT(Album.id) FROM Album \ JOIN Album_Artist ON Album_Artist.album_id = Album.id \ WHERE artist_id=%llu AND album_id!=%llu", artist_id,album_id); if( result == NULL || !dbi_result_first_row(result) ) goto skip; album_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); if(album_count == 0){ result = dbi_conn_queryf(DB_conn,"DELETE FROM Artist \ WHERE id=%llu",artist_id); dbi_result_free(result); } /* Leave ArtistArt and AlbumArt for a defragment routine or something */ /* Delete Directory if it doesnt have anymore files */ result = dbi_conn_queryf(DB_conn, "SELECT COUNT(id) FROM Tags WHERE dir=%llu",dir_id); if( result == NULL || !dbi_result_first_row(result) ) goto skip; file_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); if(file_count == 0){ result = dbi_conn_queryf(DB_conn,"DELETE FROM Directories \ WHERE id=%llu",dir_id); dbi_result_free(result); } skip: sem_post(&mutex); return;}void _LIBRARY_delete_artist(long long old_id){ dbi_result result=NULL; result = dbi_conn_queryf(DB_conn,"DELETE \ FROM Artist WHERE id=%llu",old_id); dbi_result_free(result); result = dbi_conn_queryf(DB_conn,"DELETE \ FROM Album_Artist WHERE artist_id=%llu",old_id); dbi_result_free(result); result = dbi_conn_queryf(DB_conn,"DELETE \ FROM SimilarArtist WHERE artist_id=%llu",old_id); dbi_result_free(result); result = dbi_conn_queryf(DB_conn,"DELETE \ FROM ArtistArt WHERE artist_id=%llu",old_id); dbi_result_free(result);}void _LIBRARY_rename_artist(long long tag_id, long long album_id, long long old_id, const char *old, const char *new){ long long new_id; long long tag_count=0; char *quote_new= NULL; dbi_result result=NULL; int added_artist=0; printf("LIBRARY_rename_artist:'%s' -> '%s'",old,new); /* Compute id for new artist name */ new_id = HELPER_hash(new,0); /* Check if that id already exists */ result = dbi_conn_queryf(DB_conn,"SELECT id \ FROM Artist \ WHERE id=%llu",new_id); /* If its a new artist - add to Artist table */ if(!dbi_result_first_row(result)){ dbi_result_free(result); dbi_conn_quote_string_copy(DB_conn,new,"e_new); result = dbi_conn_queryf(DB_conn,"INSERT INTO Artist \ (id,name) VALUES(%llu,%s)",new_id,quote_new); free(quote_new); dbi_result_free(result); }else dbi_result_free(result); /* Update Tag */ result = dbi_conn_queryf(DB_conn,"UPDATE Tags \ SET artist=%llu WHERE id=%llu",new_id,tag_id); dbi_result_free(result); /* Update relations if necessary in Album_Artist table */ result = dbi_conn_queryf(DB_conn,"SELECT artist_id,album_id \ FROM Album_Artist \ WHERE artist_id=%llu AND album_id=%llu", new_id,album_id); if(!dbi_result_first_row(result)){ dbi_result_free(result); result = dbi_conn_queryf(DB_conn,"INSERT INTO Album_Artist \ (artist_id,album_id) VALUES(%llu,%llu)", new_id,album_id); dbi_result_free(result); }else dbi_result_free(result); /* Is the Album_Artist relationship still needed for the old artist */ result = dbi_conn_queryf(DB_conn,"SELECT COUNT(id) \ FROM Tags \ WHERE artist=%llu AND album=%llu",old_id,album_id); dbi_result_first_row(result); tag_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); if(tag_count == 0){ result = dbi_conn_queryf(DB_conn,"DELETE \ FROM Album_Artist \ WHERE album_id=%llu AND artist_id=%llu", album_id,old_id); dbi_result_free(result); } /* Check if there are any tags now that belong to the old artist * - Delete old artist entry if necessary */ result = dbi_conn_queryf(DB_conn,"SELECT COUNT(id) \ FROM Tags \ WHERE artist=%llu",old_id); dbi_result_first_row(result); tag_count = dbi_result_get_longlong_idx(result,1); dbi_result_free(result); if(tag_count == 0) { _LIBRARY_delete_artist(old_id); }}void _LIBRARY_rename_album(long long tag_id,char *path, long long old_id,char *old,char *new){ /* compute album id */ /* check if it already exists */}void LIBRARY_update_db(AUDIO_SESSION *s,char *fullpath){ char *quote_filename,*quote_dir; char *quote_title; char *old_artist,*old_album; char *new_dir; long long old_artist_id,old_album_id; long long new_artist_id,new_album_id; long long tag_id; struct stat path_stat; time_t tag_mtime; dbi_result result; AUDIO_metadata *mdata; int rv; rv = s->AUDIO_is_audio(s,fullpath); if(rv)return; /* MUTEX */ sem_wait(&mutex); new_dir = strdup(dirname(fullpath)); rv = dbi_conn_quote_string_copy(DB_conn,new_dir,"e_dir); rv = dbi_conn_quote_string_copy(DB_conn,basename(fullpath),"e_filename); stat(fullpath,&path_stat); /* Check if file exists */ result = dbi_conn_queryf(DB_conn, "SELECT Tags.id,Tags.mtime \ FROM Tags JOIN Directories ON Tags.dir = Directories.id \ WHERE filename=%s AND Directories.name=%s", quote_filename,quote_dir); free(quote_filename); free(quote_dir); //rv = dbi_result_get_numrows(result); if( result == NULL ) goto skip; if( !dbi_result_first_row(result) ){ dbi_result_free(result); sem_post(&mutex); quote_filename = strdup(basename(fullpath)); quote_dir = strdup(dirname(fullpath)); LIBRARY_add_file(s,quote_dir,quote_filename); free(quote_filename); free(quote_dir); return; } tag_id = dbi_result_get_longlong_idx(result,1); tag_mtime = dbi_result_get_longlong_idx(result,2); dbi_result_free(result); /* Compare db's mtime of file and current mtime */ if(path_stat.st_mtime <= tag_mtime) goto skip; /* Update the db */ mdata = malloc(sizeof(AUDIO_metadata)); rv = AUDIO_get_metadata_taglib(fullpath,mdata); /* The file exists in the DB, but its newer than the version we have * Need to see which tags have changed and make/propagate changes * accordingly.*/ /* Update tag title blind */ dbi_conn_quote_string_copy(DB_conn,mdata->title,"e_title); result = dbi_conn_queryf(DB_conn,"UPDATE Tags \ SET title=%s \ WHERE id=%llu",quote_title); dbi_result_free(result); /* Check other fields, before updating */ result = dbi_conn_queryf(DB_conn,"SELECT Artist.id,Artist.name,Album.id,Album.name \ FROM Artist \ JOIN Tags ON Tags.artist = Artist.id \ JOIN Album ON Tags.album = Album.id \ WHERE Tags.id=%llu",tag_id); dbi_result_first_row(result); old_artist_id = dbi_result_get_ulonglong_idx(result,1); old_artist = dbi_result_get_string_copy_idx(result,2); old_album_id = dbi_result_get_string_copy_idx(result,3); old_album = dbi_result_get_string_copy_idx(result,4); dbi_result_free(result); /* Compare existing artist name with current one */ if(strcmp(mdata->artist,old_artist) == 0) goto skip_artist; _LIBRARY_rename_artist(tag_id,old_album_id,old_artist_id, old_artist,mdata->artist); skip_artist: /* Compare existing album name with current one */ if(strcmp(mdata->album,old_album) == 0) goto skip_album; _LIBRARY_rename_album(tag_id,new_dir,old_album_id,old_album,mdata->album); skip_album: free(quote_title); free(old_artist); free(old_album); free(new_dir); free(mdata); skip: sem_post(&mutex); return;}void LIBRARY_add_file(AUDIO_SESSION *s, char *base_path, char *d_name){ dbi_result result; AUDIO_metadata mdata; int rv; unsigned long long rows=0; const char *errormsg; char *quote_artist,*quote_album,*quote_title,*quote_dir,*quote_filename; long long artist_id=0,album_id=0,dir_id=0; struct stat path_stat; snprintf(mdata.path,LONG_FIELD,"%s/%s",base_path,d_name); rv = s->AUDIO_is_audio(s,mdata.path); if(rv)return; /* if its an ogg file, ask taglib for the tags */// if(strcasestr(mdata.path,".ogg")){ rv = AUDIO_get_metadata_taglib(mdata.path,&mdata);// }else{// rv = s->AUDIO_get_metadata(s,mdata.path,&mdata);// } if(rv)return; if(mdata.artist[0]==0 && mdata.title[0]==0){ rv = HELPER_guess_metadata(mdata.path,&mdata); } /* MUTEX */ sem_wait(&mutex); /* Insert the Artist data first */ quote_artist=NULL; rv = dbi_conn_quote_string_copy(DB_conn,mdata.artist,"e_artist); if(rv){ artist_id = HELPER_hash((const unsigned char *)mdata.artist,0); result = dbi_conn_queryf(DB_conn, "INSERT IGNORE INTO Artist (id,name) VALUES(%llu,%s)" ,artist_id,quote_artist); /* TODO: check for DBI_ROW_ERROR */ dbi_result_free(result); } /* Insert directory information */ quote_dir=NULL; rv = dbi_conn_quote_string_copy(DB_conn,base_path,"e_dir); if(rv){ dir_id = HELPER_hash((const unsigned char *)base_path,0); result = dbi_conn_queryf(DB_conn, "INSERT IGNORE INTO Directories (id,name) \ VALUES(%llu,%s) ", dir_id,quote_dir); /* TODO: check for DBI_ROW_ERROR */ dbi_result_free(result); } /* Insert the Album data */ quote_album=NULL; album_id=0; if(mdata.album[0]==0 || mdata.album[0]==' '){ result = dbi_conn_query(DB_conn, "SELECT id FROM Album WHERE name=''"); if(dbi_result_next_row(result)) { album_id = dbi_result_get_ulonglong(result,"id"); dbi_result_free(result); goto skip_album; }else { dbi_result_free(result); goto first_blank_album; } } first_blank_album: rv = dbi_conn_quote_string_copy(DB_conn,mdata.album,"e_album); if(rv){ char *hash_string = NULL; int string_size=0; string_size = asprintf(&hash_string,"%s%s",mdata.album,base_path); if(hash_string == NULL){ printf("asprint failed\n"); exit(0); } album_id = HELPER_hash((const unsigned char *)hash_string,0); free(hash_string); stat(base_path,&path_stat); result = dbi_conn_queryf(DB_conn, "INSERT IGNORE INTO Album (id,name,dir,mtime) \ VALUES(%llu,%s,%llu,%lu)", album_id,quote_album,dir_id,path_stat.st_mtime); rows = dbi_result_get_numrows_affected(result); /* TODO: check for DBI_ROW_ERROR */ dbi_result_free(result); } skip_album: quote_filename=NULL; rv = dbi_conn_quote_string_copy(DB_conn,d_name,"e_filename); /* Insert the Album Artist relation */ result = dbi_conn_queryf(DB_conn,"INSERT IGNORE INTO Album_Artist \ (album_id,artist_id) VALUES(%llu,%llu)",album_id,artist_id); dbi_result_free(result); /* Insert the tag data */ quote_title=NULL; stat(mdata.path,&path_stat); rv = dbi_conn_quote_string_copy(DB_conn,mdata.title,"e_title); if(rv){ result = dbi_conn_queryf(DB_conn,"INSERT IGNORE INTO Tags \ (filename,dir,album,artist,title,year,track,length,mtime) \ VALUES(%s,%llu,%llu,%llu,%s,%u,%u,%u,%lu)", quote_filename,dir_id,album_id,artist_id,quote_title, mdata.year,mdata.track,mdata.length,path_stat.st_mtime); if(result == NULL){ dbi_conn_error(DB_conn,&errormsg); printf("ERROR: LIBRARY_add_file: Tags: %s\n",errormsg); } dbi_result_free(result); } if(quote_artist)free(quote_artist); if(quote_album)free(quote_album); if(quote_title)free(quote_title); if(quote_filename)free(quote_filename); if(quote_dir)free(quote_dir); sem_post(&mutex);}void LIBRARY_scanfs(AUDIO_SESSION *s,char *base_dir){ struct stat path_stat; char *quote=NULL; const char *error=NULL; dbi_result result=NULL; stat(base_dir,&path_stat); dbi_conn_quote_string_copy(DB_conn,base_dir,"e); if(quote == NULL)return; result = dbi_conn_queryf(DB_conn,"INSERT INTO LibraryPath \ (path,mtime) VALUES(%s,%lu)",quote,path_stat.st_mtime); dbi_conn_error(DB_conn,&error); printf("LIBRARY_scanfs:%s\n",error); dbi_result_free(result); _LIBRARY_scanfs(s,base_dir,NULL,0);}void _LIBRARY_scanfs(AUDIO_SESSION *s,char *base_dir, char *buffer, int last){ DIR *dptr; struct dirent *ent; int start=0; int length = 0; if(buffer == NULL){ buffer = malloc(sizeof(char) * 1024); strcpy(buffer,base_dir); // sprintf(buffer,"%s",base_dir); start =1; last = strlen(base_dir); printf("Start\n"); } length = strlen(buffer); printf("IN l=%i c=%i: %s\n",last, length,buffer); dptr = opendir(buffer); if(!dptr){ buffer[last]='\0'; return; } while( (ent = readdir(dptr)) ){ if(ent->d_type == DT_DIR){ if(strncmp(ent->d_name,".",2)!=0 && strncmp(ent->d_name,"..",3)!=0){ strcat(buffer,"/"); strcat(buffer,ent->d_name); _LIBRARY_scanfs(s,base_dir,buffer, length); } }else if(ent->d_type == DT_REG){ printf("FILE: %s\n",ent->d_name); LIBRARY_add_file(s,buffer,ent->d_name); } } printf("OUT l=%i c=%i: %s\n",last, length,buffer); if(start){ free(buffer); printf("Done\n"); }else { buffer[last]='\0'; } closedir(dptr);}