2025-11-23 18:31:34 +09:00
# include "mauplay.h"
# include <sqlite3.h>
# include <stb_ds.h>
static sqlite3 * db ;
2025-11-23 21:12:09 +09:00
numkv_t * db_musics = NULL ;
numkv_t * db_albums = NULL ;
numkv_t * db_artists = NULL ;
numkv_t * db_genres = NULL ;
2025-11-23 18:31:34 +09:00
int db_exec ( const char * s ) {
sqlite3_stmt * stmt ;
int st = 0 ;
if ( sqlite3_prepare_v2 ( db , s , - 1 , & stmt , NULL ) ! = SQLITE_OK ) {
return 1 ;
}
if ( sqlite3_step ( stmt ) ! = SQLITE_DONE ) {
st = 1 ;
}
if ( sqlite3_finalize ( stmt ) ! = SQLITE_OK ) {
st = 1 ;
}
return st ;
}
int db_init ( void ) {
2025-11-25 11:16:05 +09:00
char * conf = MDEDirectoryConfigPath ( ) ;
char * dir = malloc ( strlen ( conf ) + 8 + 1 ) ;
char * path ;
int st = 0 ;
strcpy ( dir , conf ) ;
strcat ( dir , " /mauplay " ) ;
free ( conf ) ;
2025-11-23 18:31:34 +09:00
MDEDirectoryCreate ( dir , 0755 ) ;
path = malloc ( strlen ( dir ) + 1 + strlen ( " mauplay.db " ) + 1 ) ;
strcpy ( path , dir ) ;
strcat ( path , " /mauplay.db " ) ;
free ( dir ) ;
if ( sqlite3_open ( path , & db ) ! = SQLITE_OK ) {
free ( path ) ;
return 1 ;
}
free ( path ) ;
2025-11-25 04:27:27 +09:00
if ( ( st = db_exec ( " CREATE TABLE IF NOT EXISTS cache (path TEXT PRIMARY KEY, title TEXT, artist TEXT, album TEXT, genre TEXT, length INTEGER, track INTEGER, mtime INTEGER) " ) ) ! = 0 ) {
2025-11-23 18:31:34 +09:00
sqlite3_close ( db ) ;
return st ;
}
return st ;
}
static int db_bind ( sqlite3_stmt * stmt , const char * path ) {
2025-11-24 19:49:20 +09:00
MDESound sound = MDESoundOpen ( path ) ;
2025-11-23 18:31:34 +09:00
char * p ;
const char * s_title ;
const char * s_artist ;
const char * s_album ;
const char * s_genre ;
int s_length ;
2025-11-25 04:27:27 +09:00
int s_track = 0 ;
2025-11-29 22:25:52 +09:00
char * str ;
2025-11-23 18:31:34 +09:00
struct stat s ;
2025-11-24 19:49:20 +09:00
if ( sound = = NULL ) return 1 ;
2025-11-23 18:31:34 +09:00
2025-11-24 19:49:20 +09:00
s_title = sound - > context - > title ;
s_artist = sound - > context - > artist ;
s_album = sound - > context - > album ;
s_genre = sound - > context - > genre ;
2025-11-25 04:27:27 +09:00
s_track = sound - > context - > track ;
2025-11-24 19:49:20 +09:00
s_length = sound - > context - > frames / sound - > context - > sample_rate ;
2025-11-23 18:31:34 +09:00
2025-11-29 22:25:52 +09:00
# ifdef _WIN32
if ( s_title = = NULL ) s_title = ( str = strrchr ( path , ' \\ ' ) ) ! = NULL ? ( str + 1 ) : path ;
# else
if ( s_title = = NULL ) s_title = ( str = strrchr ( path , ' / ' ) ) ! = NULL ? ( str + 1 ) : path ;
# endif
2025-11-23 18:31:34 +09:00
if ( s_artist = = NULL ) s_artist = " <unknown> " ;
if ( s_album = = NULL ) s_album = " <unknown> " ;
if ( s_genre = = NULL ) s_genre = " <unknown> " ;
p = MDEFileAbsolutePath ( path ) ;
stat ( p , & s ) ;
sqlite3_bind_text ( stmt , 1 , p , - 1 , SQLITE_TRANSIENT ) ;
sqlite3_bind_text ( stmt , 2 , s_title , - 1 , SQLITE_TRANSIENT ) ;
sqlite3_bind_text ( stmt , 3 , s_artist , - 1 , SQLITE_TRANSIENT ) ;
sqlite3_bind_text ( stmt , 4 , s_album , - 1 , SQLITE_TRANSIENT ) ;
sqlite3_bind_text ( stmt , 5 , s_genre , - 1 , SQLITE_TRANSIENT ) ;
sqlite3_bind_int ( stmt , 6 , s_length ) ;
2025-11-25 04:27:27 +09:00
sqlite3_bind_int64 ( stmt , 7 , s_track ) ;
sqlite3_bind_int64 ( stmt , 8 , s . st_mtime ) ;
2025-11-23 18:31:34 +09:00
2025-11-24 19:49:20 +09:00
MDESoundClose ( sound ) ;
2025-11-23 18:31:34 +09:00
free ( p ) ;
return 0 ;
}
void db_add ( const char * path ) {
sqlite3_stmt * stmt ;
2025-11-25 04:27:27 +09:00
if ( sqlite3_prepare_v2 ( db , " INSERT OR REPLACE INTO cache VALUES(?,?,?,?,?,?,?,?) " , - 1 , & stmt , NULL ) ! = SQLITE_OK ) {
2025-11-23 18:31:34 +09:00
return ;
}
if ( db_bind ( stmt , path ) = = 0 ) {
sqlite3_step ( stmt ) ;
}
sqlite3_finalize ( stmt ) ;
}
void db_scan ( void ) {
sqlite3_stmt * stmt ;
2025-11-23 21:12:09 +09:00
int total = 0 ;
int i ;
for ( i = 0 ; i < shlen ( db_musics ) ; i + + ) {
free ( db_musics [ i ] . title ) ;
free ( db_musics [ i ] . album ) ;
free ( db_musics [ i ] . artist ) ;
free ( db_musics [ i ] . genre ) ;
}
shfree ( db_musics ) ;
shfree ( db_albums ) ;
shfree ( db_artists ) ;
shfree ( db_genres ) ;
sh_new_strdup ( db_musics ) ;
sh_new_strdup ( db_albums ) ;
sh_new_strdup ( db_artists ) ;
sh_new_strdup ( db_genres ) ;
shdefault ( db_musics , 0 ) ;
shdefault ( db_albums , 0 ) ;
shdefault ( db_artists , 0 ) ;
shdefault ( db_genres , 0 ) ;
2025-11-23 18:31:34 +09:00
2025-11-27 03:34:18 +09:00
if ( sqlite3_prepare_v2 ( db , " SELECT * FROM cache ORDER BY title ASC " , - 1 , & stmt , NULL ) ! = SQLITE_OK ) {
2025-11-23 18:31:34 +09:00
return ;
}
while ( sqlite3_step ( stmt ) = = SQLITE_ROW ) {
2025-11-23 21:12:09 +09:00
char * s_path = MDEStringDuplicate ( sqlite3_column_text ( stmt , 0 ) ) ;
char * s_title = MDEStringDuplicate ( sqlite3_column_text ( stmt , 1 ) ) ;
char * s_album = MDEStringDuplicate ( sqlite3_column_text ( stmt , 3 ) ) ;
char * s_artist = MDEStringDuplicate ( sqlite3_column_text ( stmt , 2 ) ) ;
char * s_genre = MDEStringDuplicate ( sqlite3_column_text ( stmt , 4 ) ) ;
int s_length = sqlite3_column_int ( stmt , 5 ) ;
int ind ;
2025-11-27 03:34:18 +09:00
int incr ;
2025-11-23 21:12:09 +09:00
shput ( db_musics , s_path , 0 ) ;
ind = shgeti ( db_musics , s_path ) ;
db_musics [ ind ] . title = s_title ;
db_musics [ ind ] . album = s_album ;
db_musics [ ind ] . artist = s_artist ;
db_musics [ ind ] . genre = s_genre ;
db_musics [ ind ] . length = s_length ;
2025-11-27 03:34:18 +09:00
incr = shget ( db_albums , s_album ) + 1 ;
shput ( db_albums , s_album , incr ) ;
2025-11-23 21:12:09 +09:00
ind = shgeti ( db_albums , s_album ) ;
if ( shget ( db_albums , s_album ) = = 1 ) {
db_albums [ ind ] . length = s_length ;
} else {
db_albums [ ind ] . length + = s_length ;
}
2025-11-27 03:34:18 +09:00
incr = shget ( db_artists , s_artist ) + 1 ;
shput ( db_artists , s_artist , incr ) ;
2025-11-23 21:12:09 +09:00
ind = shgeti ( db_artists , s_artist ) ;
if ( shget ( db_artists , s_artist ) = = 1 ) {
db_artists [ ind ] . length = s_length ;
} else {
db_artists [ ind ] . length + = s_length ;
}
2025-11-27 03:34:18 +09:00
incr = shget ( db_genres , s_genre ) + 1 ;
shput ( db_genres , s_genre , incr ) ;
2025-11-23 21:12:09 +09:00
ind = shgeti ( db_genres , s_genre ) ;
if ( shget ( db_genres , s_genre ) = = 1 ) {
db_genres [ ind ] . length = s_length ;
} else {
db_genres [ ind ] . length + = s_length ;
}
2025-11-23 18:31:34 +09:00
}
sqlite3_finalize ( stmt ) ;
2025-11-23 21:12:09 +09:00
ui_set_all_music ( shlen ( db_musics ) ) ;
ui_set_albums ( shlen ( db_albums ) ) ;
ui_set_artists ( shlen ( db_artists ) ) ;
ui_set_genres ( shlen ( db_genres ) ) ;
MwDispatchUserHandler ( tree , MwNactivateHandler , ui_last ) ;
2025-11-23 18:31:34 +09:00
}
2025-11-25 04:27:27 +09:00
char * * db_find ( const char * query , const char * param , const char * additional ) {
char * * r = NULL ;
sqlite3_stmt * stmt ;
char q [ 128 ] ;
sprintf ( q , " SELECT * FROM cache WHERE %s = ? ORDER BY %s ASC " , query , additional = = NULL ? query : additional ) ;
if ( sqlite3_prepare_v2 ( db , q , - 1 , & stmt , NULL ) ! = SQLITE_OK ) {
return NULL ;
}
sqlite3_bind_text ( stmt , 1 , param , - 1 , SQLITE_TRANSIENT ) ;
while ( sqlite3_step ( stmt ) = = SQLITE_ROW ) {
char * p = MDEStringDuplicate ( sqlite3_column_text ( stmt , 0 ) ) ;
arrput ( r , p ) ;
}
sqlite3_finalize ( stmt ) ;
return r ;
}