diff --git a/README.md b/README.md index 983162e..3f5ce98 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Blissify is a wrapper around [Bliss](https://github.com/Polochon-street/bliss) to compute and store values in an SQLite database. -It is done in an attempot to bind Bliss to MPD to be able to play +It is done in an attempt to bind Bliss to MPD to be able to play smooth mixes with MPD, _à la_ Grooveshark radio. ## Dependencies diff --git a/bliss b/bliss index 4781124..582b96d 160000 --- a/bliss +++ b/bliss @@ -1 +1 @@ -Subproject commit 4781124ff177fa1eb649b9b74993a0ae28b1e501 +Subproject commit 582b96d6ed217016363c7d7d5b24ee10d179a946 diff --git a/include/constants.h b/include/constants.h index f7aa188..9130cbc 100644 --- a/include/constants.h +++ b/include/constants.h @@ -2,5 +2,6 @@ #define CONSTANTS_H #define DEFAULT_STRING_LENGTH 10000 +#define VERSION "0.1" #endif // CONSTANTS_H diff --git a/mpd/client.py b/mpd/client.py index 3582500..5531ac1 100755 --- a/mpd/client.py +++ b/mpd/client.py @@ -146,7 +146,7 @@ def main(queue_length): logging.info("Currently played song is %s." % (current_song,)) # Get current song coordinates - cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs WHERE filename=?", (current_song,)) + cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs WHERE filename=?", (current_song,)) current_song_coords = cur.fetchone() if current_song_coords is None: logging.warning("Current song %s is not in db. You should update the db." % @@ -158,7 +158,7 @@ def main(queue_length): for i in range(queue_length): # Get cached distances from db cur.execute( - "SELECT id, filename, distance, similarity, tempo, amplitude, frequency, attack FROM (SELECT s2.id AS id, s2.filename AS filename, s2.tempo AS tempo, s2.amplitude AS amplitude, s2.frequency AS frequency, s2.attack AS attack, distances.distance AS distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s1.filename=? UNION SELECT s1.id as id, s1.filename AS filename, s1.tempo AS tempo, s1.amplitude AS amplitude, s1.frequency AS frequency, s1.attack AS attack, distances.distance as distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s2.filename=?) ORDER BY distance ASC", + "SELECT id, filename, distance, similarity, tempo1, tempo2, tempo3, amplitude, frequency, attack FROM (SELECT s2.id AS id, s2.filename AS filename, s2.tempo1 AS tempo1, s2.tempo2 AS tempo2, s2.tempo3 AS tempo3, s2.amplitude AS amplitude, s2.frequency AS frequency, s2.attack AS attack, distances.distance AS distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s1.filename=? UNION SELECT s1.id as id, s1.filename AS filename, s1.tempo1 AS tempo1, s1.tempo2 AS tempo2, s1.tempo3 AS tempo3, s1.amplitude AS amplitude, s1.frequency AS frequency, s1.attack AS attack, distances.distance as distance, distances.similarity AS similarity FROM distances INNER JOIN songs AS s1 ON s1.id=distances.song1 INNER JOIN songs AS s2 on s2.id=distances.song2 WHERE s2.filename=?) ORDER BY distance ASC", (current_song_coords["filename"], current_song_coords["filename"])) cached_distances = [row for row in cur.fetchall() @@ -181,7 +181,7 @@ def main(queue_length): # Get all other songs coordinates closest_song = None - cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs") + cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs") for tmp_song_data in cur.fetchall(): if(tmp_song_data["filename"] == current_song_coords["filename"] or tmp_song_data["filename"] in cached_distances_songs or @@ -191,24 +191,32 @@ def main(queue_length): continue # Compute distance distance = math.sqrt( - (current_song_coords["tempo"] - tmp_song_data["tempo"])**2 + + (current_song_coords["tempo1"] - tmp_song_data["tempo1"])**2 + + (current_song_coords["tempo2"] - tmp_song_data["tempo2"])**2 + + (current_song_coords["tempo3"] - tmp_song_data["tempo3"])**2 + (current_song_coords["amplitude"] - tmp_song_data["amplitude"])**2 + (current_song_coords["frequency"] - tmp_song_data["frequency"])**2 + (current_song_coords["attack"] - tmp_song_data["attack"])**2 ) similarity = ( - (current_song_coords["tempo"] * tmp_song_data["tempo"] + + (current_song_coords["tempo1"] * tmp_song_data["tempo1"] + + current_song_coords["tempo2"] * tmp_song_data["tempo2"] + + current_song_coords["tempo3"] * tmp_song_data["tempo3"] + current_song_coords["amplitude"] * tmp_song_data["amplitude"] + current_song_coords["frequency"] * tmp_song_data["frequency"] + current_song_coords["attack"] * tmp_song_data["attack"]) / ( math.sqrt( - current_song_coords["tempo"]**2 + + current_song_coords["tempo1"]**2 + + current_song_coords["tempo2"]**2 + + current_song_coords["tempo3"]**2 + current_song_coords["amplitude"]**2 + current_song_coords["frequency"]**2 + current_song_coords["attack"]**2) * math.sqrt( - tmp_song_data["tempo"]**2 + + tmp_song_data["tempo1"]**2 + + tmp_song_data["tempo2"]**2 + + tmp_song_data["tempo3"]**2 + tmp_song_data["amplitude"]**2 + tmp_song_data["frequency"]**2 + tmp_song_data["attack"]**2) diff --git a/scripts/build_cache.py b/scripts/build_cache.py index 1456bdb..26c42bd 100755 --- a/scripts/build_cache.py +++ b/scripts/build_cache.py @@ -25,7 +25,7 @@ def main(): cached_distances = cur.fetchall() # Get all songs - cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs") + cur.execute("SELECT id, tempo1, tempo2, tempo3, amplitude, frequency, attack, filename FROM songs") all_songs = cur.fetchall() for i in range(len(all_songs)): @@ -42,24 +42,32 @@ def main(): continue # Compute distance distance = math.sqrt( - (song1["tempo"] - song2["tempo"])**2 + + (song1["tempo1"] - song2["tempo1"])**2 + + (song1["tempo2"] - song2["tempo2"])**2 + + (song1["tempo3"] - song2["tempo3"])**2 + (song1["amplitude"] - song2["amplitude"])**2 + (song1["frequency"] - song2["frequency"])**2 + (song1["attack"] - song2["attack"])**2 ) similarity = ( - (song1["tempo"] * song2["tempo"] + + (song1["tempo1"] * song2["tempo1"] + + song1["tempo2"] * song2["tempo2"] + + song1["tempo3"] * song2["tempo3"] + song1["amplitude"] * song2["amplitude"] + song1["frequency"] * song2["frequency"] + song1["attack"] * song2["attack"]) / ( math.sqrt( - song1["tempo"]**2 + + song1["tempo1"]**2 + + song1["tempo2"]**2 + + song1["tempo3"]**2 + song1["amplitude"]**2 + song1["frequency"]**2 + song1["attack"]**2) * math.sqrt( - song2["tempo"]**2 + + song2["tempo1"]**2 + + song2["tempo2"]**2 + + song2["tempo3"]**2 + song2["amplitude"]**2 + song2["frequency"]**2 + song2["attack"]**2) diff --git a/src/analysis.c b/src/analysis.c index ff79bdf..1944a4d 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -47,7 +47,9 @@ int _init_db(char *data_folder, char* db_path) } dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS songs( \ id INTEGER PRIMARY KEY, \ - tempo REAL, \ + tempo1 REAL, \ + tempo2 REAL, \ + tempo3 REAL, \ amplitude REAL, \ frequency REAL, \ attack REAL, \ @@ -80,6 +82,22 @@ int _init_db(char *data_folder, char* db_path) sqlite3_close(dbh); return 1; } + dberr = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS metadata( \ + name TEXT UNIQUE, \ + value TEXT)", NULL, NULL, NULL); + if (SQLITE_OK != dberr) { + fprintf(stderr, "Error creating db: %s.\n", sqlite3_errmsg(dbh)); + sqlite3_close(dbh); + return 1; + } + sqlite3_stmt *res; + sqlite3_prepare_v2(dbh, + "INSERT INTO metadata(name, value) VALUES(?, ?)", + -1, &res, 0); + sqlite3_bind_text(res, 1, "version", strlen("version"), SQLITE_STATIC); + sqlite3_bind_text(res, 2, VERSION, strlen(VERSION), SQLITE_STATIC); + sqlite3_step(res); + sqlite3_finalize(res); sqlite3_close(dbh); return 0; } @@ -135,7 +153,7 @@ int _parse_music_helper( } // Insert song analysis in database dberr = sqlite3_prepare_v2(dbh, - "INSERT INTO songs(tempo, amplitude, frequency, attack, filename) VALUES(?, ?, ?, ?, ?)", + "INSERT INTO songs(tempo1, tempo2, tempo3, amplitude, frequency, attack, filename) VALUES(?, ?, ?, ?, ?)", -1, &res, 0); if (SQLITE_OK != dberr) { fprintf(stderr, "Error while inserting data in db: %s\n\n", sqlite3_errmsg(dbh)); @@ -152,11 +170,13 @@ int _parse_music_helper( // Pass file return 1; } - sqlite3_bind_double(res, 1, song_analysis.force_vector.tempo); - sqlite3_bind_double(res, 2, song_analysis.force_vector.amplitude); - sqlite3_bind_double(res, 3, song_analysis.force_vector.frequency); - sqlite3_bind_double(res, 4, song_analysis.force_vector.attack); - sqlite3_bind_text(res, 5, song_uri, strlen(song_uri), SQLITE_STATIC); + sqlite3_bind_double(res, 1, song_analysis.force_vector.tempo1); + sqlite3_bind_double(res, 2, song_analysis.force_vector.tempo2); + sqlite3_bind_double(res, 3, song_analysis.force_vector.tempo3); + sqlite3_bind_double(res, 4, song_analysis.force_vector.amplitude); + sqlite3_bind_double(res, 5, song_analysis.force_vector.frequency); + sqlite3_bind_double(res, 6, song_analysis.force_vector.attack); + sqlite3_bind_text(res, 7, song_uri, strlen(song_uri), SQLITE_STATIC); dberr = sqlite3_step(res); if (SQLITE_DONE != dberr) { // Free song analysis diff --git a/src/main.c b/src/main.c index 145e075..00b54d9 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,20 @@ int main(int argc, char** argv) { sqlite3_close(dbh); exit(EXIT_FAILURE); } + dberr = sqlite3_exec(dbh, "SELECT value FROM metadata WHERE name=version", NULL, NULL, NULL); + if (SQLITE_OK != dberr) { + fprintf(stderr, "Error while fetching data in db: %s\n\n", sqlite3_errmsg(dbh)); + sqlite3_close(dbh); + exit(EXIT_FAILURE); + } + sqlite3_stmt *res = NULL; + while (sqlite3_step(res) == SQLITE_ROW) { + const char* version = (char*) sqlite3_column_text(res, 1); + if (strcmp(version, VERSION) != 0) { + fprintf(stderr, "DB is in an older version. Run update script and start again.\n"); + exit(EXIT_FAILURE); + } + } for (int i = 2; i < argc; ++i) { _parse_music_helper(dbh, base_path, argv[i]);