00001
00007 #include <limits.h>
00008 #include <stdbool.h>
00009 #include <stddef.h>
00010 #include <string.h>
00011 #include <strings.h>
00012 #include <unistd.h>
00013
00014 #include "asf.h"
00015 #include "check.h"
00016 #include "config.h"
00017 #include "db5.h"
00018 #include "db5_dat.h"
00019 #include "db5_hdr.h"
00020 #include "db5_index.h"
00021 #include "db5_types.h"
00022 #include "file.h"
00023 #include "mp3.h"
00024 #include "names.h"
00025 #include "utf8.h"
00026 #include "wstring.h"
00027
00028 bool db5_init()
00029 {
00030 if (db5_hdr_init() == false)
00031 {
00032 return false;
00033 }
00034 if (db5_dat_init() == false)
00035 {
00036 db5_hdr_free();
00037 return false;
00038 }
00039 if (names_init() == false)
00040 {
00041 db5_hdr_free();
00042 db5_dat_free();
00043 return false;
00044 }
00045
00046 return true;
00047 }
00048
00049 void db5_widechar_row(db5_row *row)
00050 {
00051 check(row != NULL);
00052
00053 ws_atows(row->filepath, membersizeof(db5_row, filepath));
00054 ws_atows(row->filename, membersizeof(db5_row, filename));
00055 ws_atows(row->artist, membersizeof(db5_row, artist));
00056 ws_atows(row->album, membersizeof(db5_row, album));
00057 ws_atows(row->genre, membersizeof(db5_row, genre));
00058 ws_atows(row->title, membersizeof(db5_row, title));
00059 }
00060
00061 void db5_unwidechar_row(db5_row *row)
00062 {
00063 check(row != NULL);
00064
00065 ws_wstoa(row->filepath, membersizeof(db5_row, filepath));
00066 ws_wstoa(row->filename, membersizeof(db5_row, filename));
00067 ws_wstoa(row->artist, membersizeof(db5_row, artist));
00068 ws_wstoa(row->album, membersizeof(db5_row, album));
00069 ws_wstoa(row->genre, membersizeof(db5_row, genre));
00070 ws_wstoa(row->title, membersizeof(db5_row, title));
00071 }
00072
00073 bool db5_generate_row(const char *localfile, db5_row *row)
00074 {
00075 char *dir, *file, *ext;
00076 char localfile_latin1[PATH_MAX];
00077 char namebuffer[PATH_MAX];
00078
00079 check(localfile != NULL);
00080 check(row != NULL);
00081
00082 add_log(ADDLOG_DUMP, "[db5]generate_row", "building informations for '%s'\n", localfile);
00083
00084
00085 memset(row, 0, sizeof(db5_row));
00086 snprintf(row->artist,membersizeof(db5_row, artist)/2, CONFIG_DEFAULT_ARTIST);
00087 snprintf(row->album, membersizeof(db5_row, album)/2, CONFIG_DEFAULT_ALBUM);
00088 snprintf(row->genre, membersizeof(db5_row, genre)/2, CONFIG_DEFAULT_GENRE);
00089 snprintf(row->title, membersizeof(db5_row, title)/2, CONFIG_DEFAULT_TITLE);
00090
00091
00092 utf8_iso8859(localfile, localfile_latin1, sizeof(localfile_latin1));
00093
00094
00095 strncpy(namebuffer, localfile_latin1, sizeof(namebuffer));
00096 file_path_explode(namebuffer, &dir, &file, &ext);
00097
00098
00099 if (ext == NULL)
00100 {
00101 ext = "";
00102 add_log(ADDLOG_RECOVER, "[db5]generate_row", "unable to get extension of '%s'\n", localfile);
00103 }
00104 if (strcasecmp(ext, CONFIG_ASF_EXT) != 0 && strcasecmp(ext, CONFIG_MPEG_EXT) != 0)
00105 {
00106 add_log(ADDLOG_FAIL, "[db5]generate_row", "extension is unknow\n");
00107 log_dump_latin1("ext", ext);
00108 return false;
00109 }
00110
00111
00112 snprintf(row->filepath, membersizeof(db5_row, filepath)/2, "%s/", dir);
00113 file_windows_slashes(row->filepath);
00114
00115
00116 snprintf(row->filename, membersizeof(db5_row, filename)/2, "%s.%s", file, ext);
00117
00118 if (!file_exists(localfile))
00119 {
00120 add_log(ADDLOG_RECOVER, "[db5]generate_row", "unable to get information from file, default values will be used\n");
00121 log_dump("localfile", localfile);
00122
00123 return true;
00124 }
00125
00126 if (strcasecmp(ext, CONFIG_ASF_EXT) == 0)
00127 {
00128 return asf_generate_row(localfile, row);
00129 }
00130 else if (strcasecmp(ext, CONFIG_MPEG_EXT) == 0)
00131 {
00132 return mp3_generate_row(localfile, row);
00133 }
00134
00135 return false;
00136 }
00137
00138
00139 char **db5_select_filename()
00140 {
00141 uint32_t count, i;
00142 db5_row row;
00143 char **result;
00144 char filename[PATH_MAX];
00145
00146 add_log(ADDLOG_DEBUG, "[db5]select_filename", "called\n");
00147
00148 count = db5_hdr_count();
00149
00150 result = (char **)malloc((count+1) * sizeof(char *));
00151 if (result == NULL)
00152 {
00153 add_log(ADDLOG_CRITICAL, "[db5]select_filename", "not enougth memory\n");
00154 return NULL;
00155 }
00156
00157 for(i=0; i < count; i++)
00158 {
00159 if (db5_dat_select_row(i, &row) != true)
00160 {
00161 add_log(ADDLOG_FAIL, "[db5]select_filename", "unable to get file information form database, entry id: %u\n", i);
00162 free(result);
00163 return NULL;
00164 }
00165
00166 db5_unwidechar_row(&row);
00167
00168 iso8859_utf8(names_select_longname(row.filename), filename, sizeof(filename));
00169
00170 result[i] = (char *)malloc((strlen(filename)+1)*sizeof(char));
00171 if (result[i] == NULL)
00172 {
00173 add_log(ADDLOG_CRITICAL, "[db5]select_filename", "not enougth memory\n");
00174 return NULL;
00175 }
00176
00177 strcpy(result[i], filename);
00178 }
00179
00180 result[count] = NULL;
00181
00182 add_log(ADDLOG_DUMP, "[db5]select_filename", "returns %u file(s)\n", count);
00183
00184 return result;
00185 }
00186
00187 void db5_free()
00188 {
00189 db5_hdr_free();
00190 db5_dat_free();
00191 names_free();
00192 }
00193
00194 bool db5_insert(const char *filename)
00195 {
00196 char shortname[membersizeof(db5_row, filename)];
00197 char filename_latin1[PATH_MAX];
00198 char localfile[PATH_MAX];
00199 db5_row row;
00200
00201 check(filename != NULL);
00202
00203
00204 utf8_iso8859(filename, filename_latin1, sizeof(filename_latin1));
00205
00206
00207 if (!names_select_shortname(filename_latin1, shortname, sizeof(shortname)))
00208 {
00209 names_insert(filename_latin1);
00210 }
00211
00212
00213 if (!names_select_shortname(filename_latin1, shortname, sizeof(shortname)))
00214 {
00215 add_log(ADDLOG_FAIL, "[db5]insert", "unable to insert file '%s' into name database\n", filename);
00216 return false;
00217 }
00218
00219 add_log(ADDLOG_DUMP, "[db5]insert", "$filename -> $shortname\n");
00220 log_dump("filename", filename);
00221 log_dump_latin1("shortname", shortname);
00222
00223
00224 if (db5_dat_select_by_filename(filename_latin1) != DB5_ROW_NOT_FOUND)
00225 {
00226 add_log(ADDLOG_FAIL, "[db5]insert", "file '%s' already exists\n", filename);
00227 return false;
00228 }
00229
00230
00231 db5_shortname_to_localfile(shortname, localfile, sizeof(localfile));
00232
00233
00234 if (db5_generate_row(localfile, &row) != true)
00235 {
00236 add_log(ADDLOG_FAIL, "[db5]insert", "unable to generate row from file '%s'\n", filename);
00237 return false;
00238 }
00239 db5_widechar_row(&row);
00240
00241
00242 row.hidden = (uint32_t)(filename[0] == '.');
00243
00244
00245 if (db5_dat_insert(&row) != true)
00246 {
00247 add_log(ADDLOG_FAIL, "[db5]insert", "unable to insert row in database '%s'\n", filename);
00248 return false;
00249 }
00250
00251 return true;
00252 }
00253
00254 bool db5_update(const char *filename)
00255 {
00256 uint32_t row_index;
00257 db5_row row;
00258 char shortname[membersizeof(db5_row, filename)];
00259 char localfile[PATH_MAX];
00260
00261 check(filename != NULL);
00262
00263
00264 if (!db5_longname_to_shortname(filename, shortname, sizeof(shortname)))
00265 {
00266 add_log(ADDLOG_FAIL, "[db5]update", "unable to get short file name for '%s'\n", filename);
00267 return false;
00268 }
00269
00270
00271 row_index = db5_dat_select_by_filename(shortname);
00272 if (row_index == DB5_ROW_NOT_FOUND)
00273 {
00274 add_log(ADDLOG_FAIL, "[db5]update", "unable to find file in database\n");
00275 log_dump_latin1("shortname", shortname);
00276 log_dump("filename", filename);
00277 return false;
00278 }
00279
00280 add_log(ADDLOG_DUMP, "[db5]update", "database entry is %u\n", row_index);
00281
00282
00283 db5_shortname_to_localfile(shortname, localfile, sizeof(localfile));
00284
00285
00286 if (!db5_generate_row(localfile, &row))
00287 {
00288 add_log(ADDLOG_FAIL, "[db5]update", "unable to generate row from file\n");
00289 log_dump("localfile", localfile);
00290 log_dump("filename", filename);
00291 return false;
00292 }
00293 db5_widechar_row(&row);
00294
00295
00296 row.hidden = (uint32_t)(filename[0] == '.');
00297
00298
00299 if (!db5_dat_update(row_index, &row))
00300 {
00301 add_log(ADDLOG_FAIL, "[db5]update", "error writting info in database for file '%s'\n", filename);
00302 return false;
00303 }
00304
00305 return true;
00306 }
00307
00308 bool db5_delete(const char *filename)
00309 {
00310 uint32_t row_index;
00311 char shortname[membersizeof(db5_row, filename)];
00312
00313 check(filename != NULL);
00314
00315
00316 if (!db5_longname_to_shortname(filename, shortname, sizeof(shortname)))
00317 {
00318 add_log(ADDLOG_FAIL, "[db5]delete", "unable to get short file name for '%s'\n", filename);
00319 return false;
00320 }
00321
00322
00323 row_index = db5_dat_select_by_filename(shortname);
00324 if (row_index == DB5_ROW_NOT_FOUND)
00325 {
00326 add_log(ADDLOG_FAIL, "[db5]delete", "unable to find file in database\n");
00327 log_dump_latin1("shortname", shortname);
00328 log_dump("filename", filename);
00329 return false;
00330 }
00331
00332 if (!db5_dat_delete_row(row_index))
00333 {
00334 add_log(ADDLOG_FAIL, "[db5]remove", "unable to delete file from dat database, row is %u\n", row_index);
00335 log_dump_latin1("shortname", shortname);
00336 log_dump("filename", filename);
00337 return false;
00338 }
00339
00340 if (names_delete(filename))
00341 {
00342 add_log(ADDLOG_RECOVER, "[db5]remove", "unable to remove file '%s' from names database\n", filename);
00343 }
00344
00345 return true;
00346 }
00347
00348
00355 #define db5_index_col(bitmap, item, code) bitmap <<= 1; if (db5_index_colindex(item, code)) { bitmap++; }
00356
00357 bool db5_index()
00358 {
00359 unsigned int result;
00360
00361 result = 0;
00362 db5_index_col(result, filename, DB5_IDX_CODE_FILENAME);
00363 db5_index_col(result, filepath, DB5_IDX_CODE_FILEPATH);
00364 db5_index_col(result, album, DB5_IDX_CODE_ALBUM);
00365 db5_index_col(result, genre, DB5_IDX_CODE_GENRE);
00366 db5_index_col(result, title, DB5_IDX_CODE_TITLE);
00367 db5_index_col(result, artist, DB5_IDX_CODE_ARTIST);
00368 db5_index_col(result, track, DB5_IDX_CODE_TRACK);
00369 db5_index_col(result, source, DB5_IDX_CODE_SOURCE);
00370 db5_index_col(result, reserved, DB5_IDX_CODE_DEV);
00371
00372 if (result != 0x1ff)
00373 {
00374 add_log(ADDLOG_RECOVER, "[db5]index", "error during indexing, success bitmap=0x%p", result);
00375
00376 return false;
00377 }
00378
00379 return true;
00380 }
00381
00382 bool db5_localfile(const char *filename, char *localfile, const size_t localfile_size)
00383 {
00384 char shortname[membersizeof(db5_row, filename)];
00385
00386 check(filename != NULL);
00387 check(localfile != NULL);
00388 check(localfile_size > 0);
00389
00390 if (!db5_longname_to_shortname(filename, shortname, sizeof(shortname)))
00391 {
00392 add_log(ADDLOG_USER_ERROR, "[db5]localfile", "unable to get short file name for '%s'\n", filename);
00393 localfile[0] = '\0';
00394 return false;
00395 }
00396
00397 db5_shortname_to_localfile(shortname, localfile, localfile_size);
00398
00399 return true;
00400 }
00401
00402 bool db5_longname_to_shortname(const char *longname, char *shortname, const size_t shortname_size)
00403 {
00404 char longname_latin1[PATH_MAX];
00405
00406 check(longname != NULL);
00407 check(shortname != NULL);
00408 check(shortname_size > 0);
00409
00410
00411 utf8_iso8859(longname, longname_latin1, sizeof(longname_latin1));
00412
00413
00414 if (names_generate_shortname(longname_latin1, shortname, shortname_size) != true)
00415 {
00416 add_log(ADDLOG_FAIL, "[db5]long_to_short", "cannot generate short filename, longname:'%s'\n", longname);
00417 return false;
00418 }
00419 if (db5_dat_select_by_filename(shortname) != DB5_ROW_NOT_FOUND)
00420 {
00421 add_log(ADDLOG_DUMP, "[db5]long_to_short", "$longname -> $shortname (checksum)\n");
00422 log_dump("longname", longname);
00423 log_dump_latin1("shortname", shortname);
00424 return true;
00425 }
00426
00427
00428 strncpy(shortname, longname_latin1, shortname_size);
00429 if (db5_dat_select_by_filename(shortname) != DB5_ROW_NOT_FOUND)
00430 {
00431 add_log(ADDLOG_DUMP, "[db5]long_to_short", "$longname -> $shortname (same name)\n");
00432 log_dump("longname", longname);
00433 log_dump_latin1("shortname", shortname);
00434 return true;
00435 }
00436
00437
00438 if (names_select_shortname(longname_latin1, shortname, shortname_size) == true)
00439 {
00440 if (db5_dat_select_by_filename(shortname) != DB5_ROW_NOT_FOUND)
00441 {
00442 add_log(ADDLOG_DUMP, "[db5]long_to_short", "$longname -> $shortname (database)\n");
00443 log_dump("longname", longname);
00444 log_dump_latin1("shortname", shortname);
00445 return true;
00446 }
00447 }
00448
00449
00450 shortname[0] = '\0';
00451 add_log(ADDLOG_USER_ERROR, "[db5]long_to_short", "file '%s' not found\n", longname);
00452 return false;
00453 }
00454
00455 bool db5_shortname_to_localfile(const char *shortname, char *localfile, const size_t localfile_size)
00456 {
00457 char localfile_latin1[PATH_MAX];
00458
00459 check(shortname != NULL);
00460 check(localfile != NULL);
00461 check(localfile_size > 0);
00462
00463 if (snprintf(localfile_latin1, sizeof(localfile_latin1), "%s/%s", CONFIG_MUSIC_PATH, shortname) >= localfile_size)
00464 {
00465
00466 add_log(ADDLOG_FAIL, "[db5]short_to_local", "not enough size to write result in localfile, sizeof(localfile):%u\n", localfile_size);
00467 return false;
00468 }
00469
00470 iso8859_utf8(localfile_latin1, localfile, localfile_size);
00471
00472 add_log(ADDLOG_DUMP, "[db5]short_to_local", "$shortname -> $localfile\n");
00473 log_dump_latin1("shortname", shortname);
00474 log_dump("localfile", localfile);
00475
00476 return true;
00477 }
00478
00479 bool db5_exists(const char *filename)
00480 {
00481 char shortname[membersizeof(db5_row, filename)];
00482
00483 check(filename != NULL);
00484
00485 add_log(ADDLOG_DEBUG, "[db5]exists", "called, filename:'%s'\n", filename);
00486
00487
00488 if (db5_longname_to_shortname(filename, shortname, sizeof(shortname)))
00489 {
00490 add_log(ADDLOG_DEBUG, "[db5]exists", "returns true\n");
00491 return true;
00492 }
00493
00494 add_log(ADDLOG_DEBUG, "[db5]exists", "returns false\n");
00495 return false;
00496 }
00497
00498 uint32_t db5_count()
00499 {
00500 return db5_hdr_count();
00501 }
00502
00503 void db5_print_row(db5_row *row)
00504 {
00505 check(row != NULL);
00506
00507 log_dump_latin1("(longname)", names_select_longname(row->filename));
00508 log_dump_latin1("dir", row->filepath);
00509 log_dump_latin1("file", row->filename);
00510 add_log(ADDLOG_DUMP, "[db5]print_row", "bitrate: %d bit/s\n", row->bitrate);
00511 add_log(ADDLOG_DUMP, "[db5]print_row", "samplerate: %d Hz\n", row->samplerate);
00512 add_log(ADDLOG_DUMP, "[db5]print_row", "duration: %d s\n", row->duration);
00513 log_dump_latin1("artist", row->artist);
00514 log_dump_latin1("album", row->album);
00515 log_dump_latin1("genere", row->genre);
00516 log_dump_latin1("title", row->title);
00517 add_log(ADDLOG_DUMP, "[db5]print_row", "track: %d\n", row->track);
00518 add_log(ADDLOG_DUMP, "[db5]print_row", "year: %d\n", row->year);
00519 add_log(ADDLOG_DUMP, "[db5]print_row", "filesize: %d\n", row->filesize);
00520 add_log(ADDLOG_DUMP, "[db5]print_row", "source: %d\n", row->source);
00521 }
00522