Bind Bliss to MPD.

build_cache.py 3.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env python3
  2. import logging
  3. import math
  4. import os
  5. import sqlite3
  6. logging.basicConfig(level=logging.DEBUG)
  7. if "XDG_DATA_HOME" in os.environ:
  8. _BLISSIFY_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/blissify")
  9. else:
  10. _BLISSIFY_DATA_HOME = os.path.expanduser("~/.local/share/blissify")
  11. def main():
  12. db_path = os.path.join(_BLISSIFY_DATA_HOME, "db.sqlite3")
  13. logging.debug("Using DB path: %s." % (db_path,))
  14. conn = sqlite3.connect(db_path)
  15. conn.row_factory = sqlite3.Row
  16. conn.execute('pragma foreign_keys=ON')
  17. cur = conn.cursor()
  18. # Get cached distances from db
  19. cur.execute("SELECT song1, song2, distance, similarity FROM distances")
  20. cached_distances = cur.fetchall()
  21. # Get all songs
  22. cur.execute("SELECT id, tempo, amplitude, frequency, attack, filename FROM songs")
  23. all_songs = cur.fetchall()
  24. for i in range(len(all_songs)):
  25. for j in range(i + 1, len(all_songs)):
  26. song1 = all_songs[i]
  27. song2 = all_songs[j]
  28. is_cached = len([i for i in cached_distances
  29. if(i["song1"] == song1["id"] and
  30. i["song2"] == song2["id"]) or
  31. (i["song1"] == song2["id"] and
  32. i["song2"] == song1["id"])]) > 0
  33. if is_cached:
  34. # Pass pair if cached value is already there
  35. continue
  36. # Compute distance
  37. distance = math.sqrt(
  38. (song1["tempo"] - song2["tempo"])**2 +
  39. (song1["amplitude"] - song2["amplitude"])**2 +
  40. (song1["frequency"] - song2["frequency"])**2 +
  41. (song1["attack"] - song2["attack"])**2
  42. )
  43. similarity = (
  44. (song1["tempo"] * song2["tempo"] +
  45. song1["amplitude"] * song2["amplitude"] +
  46. song1["frequency"] * song2["frequency"] +
  47. song1["attack"] * song2["attack"]) /
  48. (
  49. math.sqrt(
  50. song1["tempo"]**2 +
  51. song1["amplitude"]**2 +
  52. song1["frequency"]**2 +
  53. song1["attack"]**2) *
  54. math.sqrt(
  55. song2["tempo"]**2 +
  56. song2["amplitude"]**2 +
  57. song2["frequency"]**2 +
  58. song2["attack"]**2)
  59. )
  60. )
  61. logging.debug("Distance between %s and %s is (%f, %f)." %
  62. (song1["filename"], song2["filename"], distance,
  63. similarity))
  64. # Store distance in db cache
  65. try:
  66. logging.debug("Storing distance in database.")
  67. conn.execute(
  68. "INSERT INTO distances(song1, song2, distance, similarity) VALUES(?, ?, ?, ?)",
  69. (song1["id"], song2["id"], distance, similarity))
  70. conn.commit()
  71. # Update cached_distances list
  72. cached_distances.append({
  73. "song1": song1["id"],
  74. "song2": song2["id"],
  75. "distance": distance,
  76. "similarity": similarity
  77. })
  78. except sqlite3.IntegrityError:
  79. logging.warning("Unable to insert distance in database.")
  80. conn.rollback()
  81. # Close connection
  82. conn.close()
  83. if __name__ == "__main__":
  84. try:
  85. main()
  86. except KeyboardInterrupt:
  87. pass