All pastes #1754125 Raw Edit

C

public c v1 · immutable
#1754125 ·published 2010-01-17 00:15 UTC
rendered paste body
#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 **)&quote);		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],&quote);			/* 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,&quote);		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,&quote);	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,&quote);	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,&quote_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,&quote_dir);	rv = dbi_conn_quote_string_copy(DB_conn,basename(fullpath),&quote_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,&quote_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,&quote_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,&quote_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,&quote_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,&quote_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,&quote_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,&quote);	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);}