Bind Bliss to MPD.

analysis.c 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. #include "analysis.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/stat.h>
  6. #include <bliss.h>
  7. #include "constants.h"
  8. #include "utilities.h"
  9. int _init_db(char *data_folder, char* db_path)
  10. {
  11. data_folder[0] = '\0';
  12. db_path[0] = '\0';
  13. char *xdg_data_home_env = getenv("XDG_DATA_HOME");
  14. if (NULL == xdg_data_home_env) {
  15. strncat(data_folder, getenv("HOME"), DEFAULT_STRING_LENGTH);
  16. strip_trailing_slash(data_folder);
  17. strncat(data_folder, "/.local/share/blissify", DEFAULT_STRING_LENGTH - strlen(data_folder));
  18. }
  19. else {
  20. strncat(data_folder, xdg_data_home_env, DEFAULT_STRING_LENGTH);
  21. strip_trailing_slash(data_folder);
  22. strncat(data_folder, "/blissify", DEFAULT_STRING_LENGTH - strlen(data_folder));
  23. }
  24. // Ensure data folder exists
  25. mkdir(data_folder, 0700);
  26. // Db path
  27. strncat(db_path, data_folder, DEFAULT_STRING_LENGTH);
  28. strncat(db_path, "/db.sqlite3", DEFAULT_STRING_LENGTH - strlen(db_path));
  29. sqlite3 *dbh;
  30. if (0 != sqlite3_open_v2(db_path, &dbh, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
  31. fprintf(stderr, "Unable to open SQLite db.\n");
  32. return 1;
  33. }
  34. int dberr = sqlite3_exec(dbh, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);
  35. if (SQLITE_OK != dberr) {
  36. fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
  37. sqlite3_close(dbh);
  38. return 1;
  39. }
  40. dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS songs( \
  41. id INTEGER PRIMARY KEY, \
  42. tempo REAL, \
  43. amplitude REAL, \
  44. frequency REAL, \
  45. attack REAL, \
  46. filename TEXT UNIQUE)",
  47. NULL, NULL, NULL);
  48. if (SQLITE_OK != dberr) {
  49. fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
  50. sqlite3_close(dbh);
  51. return 1;
  52. }
  53. dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS distances( \
  54. song1 INTEGER, \
  55. song2 INTEGER, \
  56. distance REAL, \
  57. similarity REAL, \
  58. FOREIGN KEY(song1) REFERENCES songs(id) ON DELETE CASCADE, \
  59. FOREIGN KEY(song2) REFERENCES songs(id) ON DELETE CASCADE, \
  60. UNIQUE (song1, song2))",
  61. NULL, NULL, NULL);
  62. if (SQLITE_OK != dberr) {
  63. fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
  64. sqlite3_close(dbh);
  65. return 1;
  66. }
  67. dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS errors( \
  68. id INTEGER PRIMARY KEY, \
  69. filename TEXT UNIQUE)", NULL, NULL, NULL);
  70. if (SQLITE_OK != dberr) {
  71. fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
  72. sqlite3_close(dbh);
  73. return 1;
  74. }
  75. dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS metadata( \
  76. name TEXT UNIQUE, \
  77. value TEXT)", NULL, NULL, NULL);
  78. if (SQLITE_OK != dberr) {
  79. fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh));
  80. sqlite3_close(dbh);
  81. return 1;
  82. }
  83. sqlite3_stmt *res;
  84. sqlite3_prepare_v2(dbh,
  85. "INSERT INTO metadata(name, value) VALUES(?, ?)",
  86. -1, &res, 0);
  87. sqlite3_bind_text(res, 1, "version", strlen("version"), SQLITE_STATIC);
  88. sqlite3_bind_text(res, 2, VERSION, strlen(VERSION), SQLITE_STATIC);
  89. sqlite3_step(res);
  90. sqlite3_finalize(res);
  91. sqlite3_close(dbh);
  92. return 0;
  93. }
  94. int _parse_music_helper(
  95. sqlite3* dbh,
  96. const char *base_path,
  97. const char *song_uri)
  98. {
  99. sqlite3_stmt *res;
  100. // Compute full uri
  101. printf("\nAdding new song to db: %s\n", song_uri);
  102. char song_full_uri[DEFAULT_STRING_LENGTH + 1] = "";
  103. strncat(song_full_uri, base_path, DEFAULT_STRING_LENGTH);
  104. strncat(song_full_uri, song_uri, DEFAULT_STRING_LENGTH - strlen(song_full_uri));
  105. // Pass it to bliss
  106. struct bl_song song_analysis;
  107. bl_initialize_song(&song_analysis);
  108. if (BL_UNEXPECTED == bl_analyze(song_full_uri, &song_analysis)) {
  109. fprintf(stderr, "Error while parsing song: %s.\n\n", song_full_uri);
  110. // Free song analysis
  111. bl_free_song(&song_analysis);
  112. // Store error in db
  113. sqlite3_prepare_v2(dbh,
  114. "INSERT INTO errors(filename) VALUES(?)",
  115. -1, &res, 0);
  116. sqlite3_bind_text(res, 1, song_uri, strlen(song_uri), SQLITE_STATIC);
  117. sqlite3_step(res);
  118. sqlite3_finalize(res);
  119. // Pass file
  120. return 1;
  121. }
  122. // Insert into db
  123. // Begin transaction
  124. int dberr = sqlite3_exec(dbh, "BEGIN TRANSACTION", NULL, NULL, NULL);
  125. if (SQLITE_OK != dberr) {
  126. fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh));
  127. // Free song analysis
  128. bl_free_song(&song_analysis);
  129. sqlite3_exec(dbh, "ROLLBACK", NULL, NULL, NULL);
  130. // Store error in db
  131. sqlite3_prepare_v2(dbh,
  132. "INSERT INTO errors(filename) VALUES(?)",
  133. -1, &res, 0);
  134. sqlite3_bind_text(res, 1, song_uri, strlen(song_uri), SQLITE_STATIC);
  135. sqlite3_step(res);
  136. sqlite3_finalize(res);
  137. // Pass file
  138. return 1;
  139. }
  140. // Insert song analysis in database
  141. dberr = sqlite3_prepare_v2(dbh,
  142. "INSERT INTO songs(tempo, amplitude, frequency, attack, filename) VALUES(?, ?, ?, ?, ?)",
  143. -1, &res, 0);
  144. if (SQLITE_OK != dberr) {
  145. fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh));
  146. // Free song analysis
  147. bl_free_song(&song_analysis);
  148. sqlite3_exec(dbh, "ROLLBACK", NULL, NULL, NULL);
  149. // Store error in db
  150. sqlite3_prepare_v2(dbh,
  151. "INSERT INTO errors(filename) VALUES(?)",
  152. -1, &res, 0);
  153. sqlite3_bind_text(res, 1, song_uri, strlen(song_uri), SQLITE_STATIC);
  154. sqlite3_step(res);
  155. sqlite3_finalize(res);
  156. // Pass file
  157. return 1;
  158. }
  159. sqlite3_bind_double(res, 1, song_analysis.force_vector.tempo);
  160. sqlite3_bind_double(res, 2, song_analysis.force_vector.amplitude);
  161. sqlite3_bind_double(res, 3, song_analysis.force_vector.frequency);
  162. sqlite3_bind_double(res, 4, song_analysis.force_vector.attack);
  163. sqlite3_bind_text(res, 5, song_uri, strlen(song_uri), SQLITE_STATIC);
  164. dberr = sqlite3_step(res);
  165. if (SQLITE_DONE != dberr) {
  166. // Free song analysis
  167. bl_free_song(&song_analysis);
  168. sqlite3_exec(dbh, "ROLLBACK", NULL, NULL, NULL);
  169. // Store error in db
  170. sqlite3_prepare_v2(dbh,
  171. "INSERT INTO errors(filename) VALUES(?)",
  172. -1, &res, 0);
  173. sqlite3_bind_text(res, 1, song_uri, strlen(song_uri), SQLITE_STATIC);
  174. sqlite3_step(res);
  175. sqlite3_finalize(res);
  176. // Pass file
  177. return 1;
  178. }
  179. sqlite3_finalize(res);
  180. // Commit transaction
  181. dberr = sqlite3_exec(dbh, "COMMIT", NULL, NULL, NULL);
  182. if (SQLITE_OK != dberr) {
  183. fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh));
  184. // Free song analysis
  185. bl_free_song(&song_analysis);
  186. sqlite3_exec(dbh, "ROLLBACK", NULL, NULL, NULL);
  187. // Store error in db
  188. sqlite3_prepare_v2(dbh,
  189. "INSERT INTO errors(filename) VALUES(?)",
  190. -1, &res, 0);
  191. sqlite3_bind_text(res, 1, song_uri, strlen(song_uri), SQLITE_STATIC);
  192. sqlite3_step(res);
  193. sqlite3_finalize(res);
  194. // Pass file
  195. return 1;
  196. }
  197. // Free song analysis
  198. bl_free_song(&song_analysis);
  199. return 0;
  200. }
  201. int _rescan_errored(const char *db_path, const char *base_path)
  202. {
  203. // Connect to SQLite db
  204. sqlite3 *dbh;
  205. if (0 != sqlite3_open(db_path, &dbh)) {
  206. fprintf(stderr, "Unable to open SQLite db.\n");
  207. return 1;
  208. }
  209. // Get the list of all the files to process
  210. sqlite3_stmt *res = NULL;
  211. int dberr = sqlite3_exec(dbh, "SELECT filename FROM errors", NULL, NULL, NULL);
  212. if (SQLITE_OK != dberr) {
  213. fprintf(stderr, "Error while fetching data in db: %s\n\n", sqlite3_errmsg(dbh));
  214. sqlite3_close(dbh);
  215. return 1;
  216. }
  217. // Handle the files
  218. while (sqlite3_step(res) == SQLITE_ROW) {
  219. const char* filename = (char*) sqlite3_column_text(res, 1);
  220. // Delete it from errors list
  221. sqlite3_stmt *res2;
  222. int dberr2 = sqlite3_prepare_v2(dbh,
  223. "DELETE FROM errors WHERE filename=?",
  224. -1, &res2, 0);
  225. if (SQLITE_OK != dberr2) {
  226. fprintf(stderr, "Error while deleting error from db: %s\n\n", sqlite3_errmsg(dbh));
  227. continue;
  228. }
  229. sqlite3_bind_text(res2, 1, filename, strlen(filename), SQLITE_STATIC);
  230. sqlite3_step(res2);
  231. sqlite3_finalize(res2);
  232. // Try to import it back
  233. if (1 == _parse_music_helper(dbh, base_path, filename)) {
  234. continue;
  235. }
  236. }
  237. sqlite3_finalize(res);
  238. // Close SQLite connection
  239. sqlite3_close(dbh);
  240. printf("Done! :)\n");
  241. return 0;
  242. }
  243. int _purge_db(const char* db_path)
  244. {
  245. sqlite3 *dbh;
  246. if (0 != sqlite3_open_v2(db_path, &dbh, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
  247. fprintf(stderr, "Unable to open SQLite db.\n");
  248. return 1;
  249. }
  250. int dberr = sqlite3_exec(dbh, "PRAGMA foreign_keys = ON", NULL, NULL, NULL);
  251. if (SQLITE_OK != dberr) {
  252. fprintf(stderr, "Unable to open SQLite db.\n");
  253. sqlite3_close(dbh);
  254. return 1;
  255. }
  256. dberr = sqlite3_exec(dbh, "BEGIN TRANSACTION; DELETE FROM distances; DELETE FROM songs; DELETE FROM errors; COMMIT", NULL, NULL, NULL);
  257. if (SQLITE_OK != dberr) {
  258. fprintf(stderr, "Error purging existing data in db: %s.\n", sqlite3_errmsg(dbh));
  259. sqlite3_close(dbh);
  260. return 1;
  261. }
  262. sqlite3_close(dbh);
  263. return 0;
  264. }