pyrekordbox 0.4.0__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.pre-commit-config.yaml +1 -1
  2. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/CHANGELOG.md +26 -1
  3. {pyrekordbox-0.4.0/pyrekordbox.egg-info → pyrekordbox-0.4.1}/PKG-INFO +16 -9
  4. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/README.md +13 -7
  5. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyproject.toml +1 -1
  6. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/_version.py +9 -4
  7. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/anlz/tags.py +5 -15
  8. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/config.py +46 -33
  9. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/database.py +38 -75
  10. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/smartlist.py +2 -5
  11. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/tables.py +69 -117
  12. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/rbxml.py +3 -9
  13. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1/pyrekordbox.egg-info}/PKG-INFO +16 -9
  14. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/test_config.py +3 -9
  15. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/test_db6.py +22 -0
  16. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  17. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
  18. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  19. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/workflows/codeql.yml +0 -0
  20. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/workflows/pypi-publish.yml +0 -0
  21. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.github/workflows/tests.yml +0 -0
  22. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.gitignore +0 -0
  23. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.readthedocs.yaml +0 -0
  24. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/DEVSETTING.DAT +0 -0
  25. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/DJMMYSETTING.DAT +0 -0
  26. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/MYSETTING.DAT +0 -0
  27. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/MYSETTING2.DAT +0 -0
  28. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P016/0000875E/ANLZ0000.2EX +0 -0
  29. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P016/0000875E/ANLZ0000.DAT +0 -0
  30. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P016/0000875E/ANLZ0000.EXT +0 -0
  31. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P017/00009B77/ANLZ0000.2EX +0 -0
  32. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P017/00009B77/ANLZ0000.DAT +0 -0
  33. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P017/00009B77/ANLZ0000.EXT +0 -0
  34. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P019/00020AA9/ANLZ0000.2EX +0 -0
  35. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P019/00020AA9/ANLZ0000.DAT +0 -0
  36. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P019/00020AA9/ANLZ0000.EXT +0 -0
  37. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P021/00006D2B/ANLZ0000.2EX +0 -0
  38. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P021/00006D2B/ANLZ0000.DAT +0 -0
  39. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P021/00006D2B/ANLZ0000.EXT +0 -0
  40. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P043/00011517/ANLZ0000.2EX +0 -0
  41. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P043/00011517/ANLZ0000.DAT +0 -0
  42. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P043/00011517/ANLZ0000.EXT +0 -0
  43. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P053/0001D21F/ANLZ0000.2EX +0 -0
  44. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P053/0001D21F/ANLZ0000.DAT +0 -0
  45. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/USBANLZ/P053/0001D21F/ANLZ0000.EXT +0 -0
  46. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/rekordbox/export.pdb +0 -0
  47. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/export/PIONEER/rekordbox/exportExt.pdb +0 -0
  48. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/DEVSETTING.DAT +0 -0
  49. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/DJMMYSETTING.DAT +0 -0
  50. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/MYSETTING.DAT +0 -0
  51. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/MYSETTING2.DAT +0 -0
  52. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/beat_fx_quantize/off/DJMMYSETTING.DAT +0 -0
  53. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/beat_fx_quantize/on/DJMMYSETTING.DAT +0 -0
  54. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve/linear/DJMMYSETTING.DAT +0 -0
  55. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve/steep_bottom/DJMMYSETTING.DAT +0 -0
  56. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve/steep_top/DJMMYSETTING.DAT +0 -0
  57. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve_long/exponential/DJMMYSETTING.DAT +0 -0
  58. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve_long/linear/DJMMYSETTING.DAT +0 -0
  59. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/channel_fader_curve_long/smooth/DJMMYSETTING.DAT +0 -0
  60. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/cross_fader_curve/constant/DJMMYSETTING.DAT +0 -0
  61. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/cross_fader_curve/fast_cut/DJMMYSETTING.DAT +0 -0
  62. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/cross_fader_curve/slow_cut/DJMMYSETTING.DAT +0 -0
  63. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/five/DJMMYSETTING.DAT +0 -0
  64. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/four/DJMMYSETTING.DAT +0 -0
  65. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/one/DJMMYSETTING.DAT +0 -0
  66. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/three/DJMMYSETTING.DAT +0 -0
  67. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/two/DJMMYSETTING.DAT +0 -0
  68. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/display_brightness/white/DJMMYSETTING.DAT +0 -0
  69. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/headphones_mono_split/mono_split/DJMMYSETTING.DAT +0 -0
  70. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/headphones_mono_split/stereo/DJMMYSETTING.DAT +0 -0
  71. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/headphones_pre_eq/post_eq/DJMMYSETTING.DAT +0 -0
  72. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/headphones_pre_eq/pre_eq/DJMMYSETTING.DAT +0 -0
  73. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/indicator_brightness/one/DJMMYSETTING.DAT +0 -0
  74. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/indicator_brightness/three/DJMMYSETTING.DAT +0 -0
  75. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/indicator_brightness/two/DJMMYSETTING.DAT +0 -0
  76. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/mic_low_cut/off/DJMMYSETTING.DAT +0 -0
  77. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/mic_low_cut/on/DJMMYSETTING.DAT +0 -0
  78. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_button_type/toggle/DJMMYSETTING.DAT +0 -0
  79. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_button_type/trigger/DJMMYSETTING.DAT +0 -0
  80. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/eight/DJMMYSETTING.DAT +0 -0
  81. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/eleven/DJMMYSETTING.DAT +0 -0
  82. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/fifteen/DJMMYSETTING.DAT +0 -0
  83. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/five/DJMMYSETTING.DAT +0 -0
  84. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/four/DJMMYSETTING.DAT +0 -0
  85. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/fourteen/DJMMYSETTING.DAT +0 -0
  86. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/nine/DJMMYSETTING.DAT +0 -0
  87. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/one/DJMMYSETTING.DAT +0 -0
  88. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/seven/DJMMYSETTING.DAT +0 -0
  89. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/six/DJMMYSETTING.DAT +0 -0
  90. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/sixteen/DJMMYSETTING.DAT +0 -0
  91. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/ten/DJMMYSETTING.DAT +0 -0
  92. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/thirteen/DJMMYSETTING.DAT +0 -0
  93. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/three/DJMMYSETTING.DAT +0 -0
  94. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/twelve/DJMMYSETTING.DAT +0 -0
  95. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/midi_channel/two/DJMMYSETTING.DAT +0 -0
  96. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_level/minus_12db/DJMMYSETTING.DAT +0 -0
  97. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_level/minus_18db/DJMMYSETTING.DAT +0 -0
  98. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_level/minus_24db/DJMMYSETTING.DAT +0 -0
  99. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_level/minus_6db/DJMMYSETTING.DAT +0 -0
  100. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_mode/advanced/DJMMYSETTING.DAT +0 -0
  101. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/djmmysetting/talk_over_mode/normal/DJMMYSETTING.DAT +0 -0
  102. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue/off/MYSETTING.DAT +0 -0
  103. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue/on/MYSETTING.DAT +0 -0
  104. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/memory/MYSETTING.DAT +0 -0
  105. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_36db/MYSETTING.DAT +0 -0
  106. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_42db/MYSETTING.DAT +0 -0
  107. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_48db/MYSETTING.DAT +0 -0
  108. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_54db/MYSETTING.DAT +0 -0
  109. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_60db/MYSETTING.DAT +0 -0
  110. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_66db/MYSETTING.DAT +0 -0
  111. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_72db/MYSETTING.DAT +0 -0
  112. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/auto_cue_level/minus_78db/MYSETTING.DAT +0 -0
  113. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/disc_slot_illumination/bright/MYSETTING.DAT +0 -0
  114. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/disc_slot_illumination/dark/MYSETTING.DAT +0 -0
  115. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/disc_slot_illumination/off/MYSETTING.DAT +0 -0
  116. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/eject_lock/lock/MYSETTING.DAT +0 -0
  117. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/eject_lock/unlock/MYSETTING.DAT +0 -0
  118. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/hotcue_autoload/off/MYSETTING.DAT +0 -0
  119. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/hotcue_autoload/on/MYSETTING.DAT +0 -0
  120. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/hotcue_autoload/rekordbox/MYSETTING.DAT +0 -0
  121. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/hotcue_color/off/MYSETTING.DAT +0 -0
  122. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/hotcue_color/on/MYSETTING.DAT +0 -0
  123. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_mode/cdj/MYSETTING.DAT +0 -0
  124. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_mode/vinyl/MYSETTING.DAT +0 -0
  125. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_ring_brightness/bright/MYSETTING.DAT +0 -0
  126. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_ring_brightness/dark/MYSETTING.DAT +0 -0
  127. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_ring_brightness/off/MYSETTING.DAT +0 -0
  128. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_ring_indicator/off/MYSETTING.DAT +0 -0
  129. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/jog_ring_indicator/on/MYSETTING.DAT +0 -0
  130. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/chinese_simplified/MYSETTING.DAT +0 -0
  131. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/chinese_traditional/MYSETTING.DAT +0 -0
  132. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/czech/MYSETTING.DAT +0 -0
  133. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/danish/MYSETTING.DAT +0 -0
  134. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/dutch/MYSETTING.DAT +0 -0
  135. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/english/MYSETTING.DAT +0 -0
  136. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/french/MYSETTING.DAT +0 -0
  137. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/german/MYSETTING.DAT +0 -0
  138. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/greek/MYSETTING.DAT +0 -0
  139. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/hungarian/MYSETTING.DAT +0 -0
  140. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/italian/MYSETTING.DAT +0 -0
  141. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/japanese/MYSETTING.DAT +0 -0
  142. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/korean/MYSETTING.DAT +0 -0
  143. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/portuguese/MYSETTING.DAT +0 -0
  144. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/russian/MYSETTING.DAT +0 -0
  145. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/spanish/MYSETTING.DAT +0 -0
  146. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/swedish/MYSETTING.DAT +0 -0
  147. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/language/turkish/MYSETTING.DAT +0 -0
  148. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/lcd_brightness/five/MYSETTING.DAT +0 -0
  149. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/lcd_brightness/four/MYSETTING.DAT +0 -0
  150. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/lcd_brightness/one/MYSETTING.DAT +0 -0
  151. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/lcd_brightness/three/MYSETTING.DAT +0 -0
  152. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/lcd_brightness/two/MYSETTING.DAT +0 -0
  153. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/master_tempo/off/MYSETTING.DAT +0 -0
  154. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/master_tempo/on/MYSETTING.DAT +0 -0
  155. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/needle_lock/lock/MYSETTING.DAT +0 -0
  156. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/needle_lock/unlock/MYSETTING.DAT +0 -0
  157. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/on_air_display/off/MYSETTING.DAT +0 -0
  158. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/on_air_display/on/MYSETTING.DAT +0 -0
  159. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/phase_meter/type1/MYSETTING.DAT +0 -0
  160. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/phase_meter/type2/MYSETTING.DAT +0 -0
  161. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/play_mode/continue_/MYSETTING.DAT +0 -0
  162. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/play_mode/single/MYSETTING.DAT +0 -0
  163. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize/off/MYSETTING.DAT +0 -0
  164. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize/on/MYSETTING.DAT +0 -0
  165. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize_beat_value/eighth/MYSETTING.DAT +0 -0
  166. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize_beat_value/half/MYSETTING.DAT +0 -0
  167. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize_beat_value/one/MYSETTING.DAT +0 -0
  168. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/quantize_beat_value/quarter/MYSETTING.DAT +0 -0
  169. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/slip_flashing/off/MYSETTING.DAT +0 -0
  170. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/slip_flashing/on/MYSETTING.DAT +0 -0
  171. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/sync/off/MYSETTING.DAT +0 -0
  172. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/sync/on/MYSETTING.DAT +0 -0
  173. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/tempo_range/six/MYSETTING.DAT +0 -0
  174. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/tempo_range/sixteen/MYSETTING.DAT +0 -0
  175. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/tempo_range/ten/MYSETTING.DAT +0 -0
  176. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/tempo_range/wide/MYSETTING.DAT +0 -0
  177. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/time_mode/elapsed/MYSETTING.DAT +0 -0
  178. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting/time_mode/remain/MYSETTING.DAT +0 -0
  179. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/eight/MYSETTING2.DAT +0 -0
  180. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/four/MYSETTING2.DAT +0 -0
  181. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/half/MYSETTING2.DAT +0 -0
  182. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/one/MYSETTING2.DAT +0 -0
  183. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/sixteen/MYSETTING2.DAT +0 -0
  184. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/sixtyfour/MYSETTING2.DAT +0 -0
  185. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/thirtytwo/MYSETTING2.DAT +0 -0
  186. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/beat_jump_beat_value/two/MYSETTING2.DAT +0 -0
  187. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_display_mode/artwork/MYSETTING2.DAT +0 -0
  188. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_display_mode/auto/MYSETTING2.DAT +0 -0
  189. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_display_mode/info/MYSETTING2.DAT +0 -0
  190. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_display_mode/simple/MYSETTING2.DAT +0 -0
  191. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_lcd_brightness/five/MYSETTING2.DAT +0 -0
  192. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_lcd_brightness/four/MYSETTING2.DAT +0 -0
  193. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_lcd_brightness/one/MYSETTING2.DAT +0 -0
  194. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_lcd_brightness/three/MYSETTING2.DAT +0 -0
  195. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/jog_lcd_brightness/two/MYSETTING2.DAT +0 -0
  196. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/pad_button_brightness/four/MYSETTING2.DAT +0 -0
  197. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/pad_button_brightness/one/MYSETTING2.DAT +0 -0
  198. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/pad_button_brightness/three/MYSETTING2.DAT +0 -0
  199. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/pad_button_brightness/two/MYSETTING2.DAT +0 -0
  200. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/vinyl_speed_adjust/release/MYSETTING2.DAT +0 -0
  201. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/vinyl_speed_adjust/touch/MYSETTING2.DAT +0 -0
  202. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/vinyl_speed_adjust/touch_release/MYSETTING2.DAT +0 -0
  203. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/waveform/phase_meter/MYSETTING2.DAT +0 -0
  204. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/waveform/waveform/MYSETTING2.DAT +0 -0
  205. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/waveform_divisions/phrase/MYSETTING2.DAT +0 -0
  206. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/mysettings/mysetting2/waveform_divisions/time_scale/MYSETTING2.DAT +0 -0
  207. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/DEVSETTING.DAT +0 -0
  208. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/ExtData.edb +0 -0
  209. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/MYSETTING.DAT +0 -0
  210. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P002/00009C2E/ANLZ0000.DAT +0 -0
  211. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P002/00009C2E/ANLZ0000.EXT +0 -0
  212. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P02B/00023587/ANLZ0000.DAT +0 -0
  213. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P02B/00023587/ANLZ0000.EXT +0 -0
  214. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P035/00027763/ANLZ0000.DAT +0 -0
  215. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P035/00027763/ANLZ0000.EXT +0 -0
  216. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P038/0002AAA0/ANLZ0000.DAT +0 -0
  217. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P038/0002AAA0/ANLZ0000.EXT +0 -0
  218. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P068/00012CA2/ANLZ0000.DAT +0 -0
  219. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P068/00012CA2/ANLZ0000.EXT +0 -0
  220. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P076/00013B6E/ANLZ0000.DAT +0 -0
  221. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/PIONEER/USBANLZ/P076/00013B6E/ANLZ0000.EXT +0 -0
  222. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/datafile.edb +0 -0
  223. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/backup/masterPlaylists3.xml +0 -0
  224. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/database.xml +0 -0
  225. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 5/datafile.edb +0 -0
  226. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/DEVSETTING.DAT +0 -0
  227. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/DJMMYSETTING.DAT +0 -0
  228. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/MYSETTING.DAT +0 -0
  229. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/MYSETTING2.DAT +0 -0
  230. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/masterPlaylists3.xml +0 -0
  231. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/masterPlaylists6.xml +0 -0
  232. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/003/c9538-33bc-4ca7-b6c7-e63ebf9a96f8/ANLZ0000.2EX +0 -0
  233. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/003/c9538-33bc-4ca7-b6c7-e63ebf9a96f8/ANLZ0000.DAT +0 -0
  234. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/003/c9538-33bc-4ca7-b6c7-e63ebf9a96f8/ANLZ0000.EXT +0 -0
  235. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/104/c82cc-661c-4f30-ab60-51ce1effeeed/ANLZ0000.2EX +0 -0
  236. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/104/c82cc-661c-4f30-ab60-51ce1effeeed/ANLZ0000.DAT +0 -0
  237. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/104/c82cc-661c-4f30-ab60-51ce1effeeed/ANLZ0000.EXT +0 -0
  238. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/36d/ad2b4-5d4e-4b94-9a5d-a5bb241aee4b/ANLZ0000.2EX +0 -0
  239. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/36d/ad2b4-5d4e-4b94-9a5d-a5bb241aee4b/ANLZ0000.DAT +0 -0
  240. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/36d/ad2b4-5d4e-4b94-9a5d-a5bb241aee4b/ANLZ0000.EXT +0 -0
  241. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/731/0104f-53cb-453e-8b83-e0dfd5cff825/ANLZ0000.2EX +0 -0
  242. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/731/0104f-53cb-453e-8b83-e0dfd5cff825/ANLZ0000.DAT +0 -0
  243. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/731/0104f-53cb-453e-8b83-e0dfd5cff825/ANLZ0000.EXT +0 -0
  244. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/c8b/ac74a-bbfc-4fce-8fb8-50aa4e974273/ANLZ0000.2EX +0 -0
  245. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/c8b/ac74a-bbfc-4fce-8fb8-50aa4e974273/ANLZ0000.DAT +0 -0
  246. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/c8b/ac74a-bbfc-4fce-8fb8-50aa4e974273/ANLZ0000.EXT +0 -0
  247. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/e35/fa187-3f34-47e2-9880-2b33cb8d1304/ANLZ0000.2EX +0 -0
  248. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/e35/fa187-3f34-47e2-9880-2b33cb8d1304/ANLZ0000.DAT +0 -0
  249. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/backup/share/PIONEER/USBANLZ/e35/fa187-3f34-47e2-9880-2b33cb8d1304/ANLZ0000.EXT +0 -0
  250. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/database.xml +0 -0
  251. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/masterPlaylists6_template.xml +0 -0
  252. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/master_locked.db +0 -0
  253. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/.testdata/rekordbox 6/master_unlocked.db +0 -0
  254. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/CONTRIBUTING.md +0 -0
  255. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/LICENSE +0 -0
  256. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/Makefile +0 -0
  257. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/make.bat +0 -0
  258. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_beat.svg +0 -0
  259. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_file.svg +0 -0
  260. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pco2.svg +0 -0
  261. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pcob.svg +0 -0
  262. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pcp2.svg +0 -0
  263. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pcpt.svg +0 -0
  264. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_ppth.svg +0 -0
  265. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pqt2.svg +0 -0
  266. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pqt2_2.svg +0 -0
  267. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pqtz.svg +0 -0
  268. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pssi.svg +0 -0
  269. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pssi_entry.svg +0 -0
  270. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pvbr.svg +0 -0
  271. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwav.svg +0 -0
  272. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv3.svg +0 -0
  273. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv4.svg +0 -0
  274. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv5.svg +0 -0
  275. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv5_entry.svg +0 -0
  276. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv6.svg +0 -0
  277. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwv7.svg +0 -0
  278. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_pwvc.svg +0 -0
  279. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/anlz_tag.svg +0 -0
  280. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/images/x64dbg_rb_key.png +0 -0
  281. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/logos/dark/logo_primary.svg +0 -0
  282. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/logos/light/logo_primary.svg +0 -0
  283. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_static/logos/mid/logo_primary.svg +0 -0
  284. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_templates/apidoc/module.rst_t +0 -0
  285. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_templates/apidoc/package.rst_t +0 -0
  286. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_templates/apidoc/toc.rst_t +0 -0
  287. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_templates/autosummary/class.rst +0 -0
  288. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/_templates/autosummary/module.rst +0 -0
  289. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/api.md +0 -0
  290. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/conf.py +0 -0
  291. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/development/changes.md +0 -0
  292. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/development/contributing.md +0 -0
  293. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/formats/anlz.md +0 -0
  294. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/formats/db6.md +0 -0
  295. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/formats/mysetting.md +0 -0
  296. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/formats/xml.md +0 -0
  297. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/index.md +0 -0
  298. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/installation.md +0 -0
  299. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/key.md +0 -0
  300. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/quickstart.md +0 -0
  301. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/requirements.txt +0 -0
  302. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/anlz.md +0 -0
  303. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/configuration.md +0 -0
  304. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/db6.md +0 -0
  305. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/index.md +0 -0
  306. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/mysetting.md +0 -0
  307. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/docs/source/tutorial/xml.md +0 -0
  308. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/__init__.py +0 -0
  309. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/__main__.py +0 -0
  310. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/anlz/__init__.py +0 -0
  311. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/anlz/file.py +0 -0
  312. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/anlz/structs.py +0 -0
  313. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/__init__.py +0 -0
  314. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/aux_files.py +0 -0
  315. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/db6/registry.py +0 -0
  316. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/logger.py +0 -0
  317. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/mysettings/__init__.py +0 -0
  318. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/mysettings/file.py +0 -0
  319. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/mysettings/structs.py +0 -0
  320. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox/utils.py +0 -0
  321. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox.egg-info/SOURCES.txt +0 -0
  322. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox.egg-info/dependency_links.txt +0 -0
  323. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox.egg-info/not-zip-safe +0 -0
  324. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox.egg-info/requires.txt +0 -0
  325. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/pyrekordbox.egg-info/top_level.txt +0 -0
  326. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/requirements.txt +0 -0
  327. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/setup.cfg +0 -0
  328. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/__init__.py +0 -0
  329. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/test_anlz.py +0 -0
  330. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/test_mysetting.py +0 -0
  331. {pyrekordbox-0.4.0 → pyrekordbox-0.4.1}/tests/test_xml.py +0 -0
@@ -13,7 +13,7 @@ repos:
13
13
  - id: check-yaml
14
14
 
15
15
  - repo: https://github.com/astral-sh/ruff-pre-commit
16
- rev: v0.9.6
16
+ rev: v0.11.4
17
17
  hooks:
18
18
  # Run the linter.
19
19
  - id: ruff
@@ -1,5 +1,29 @@
1
1
  # What's New
2
2
 
3
+
4
+ <a name="v0.4.1"></a>
5
+ ## [v0.4.1] - 2025-04-20
6
+
7
+ This release improves database functionality by allowing commits when playlists are missing in
8
+ XML (with warnings for non-special playlists), adds timezone support for date fields,
9
+ and fixes date format issues.
10
+ Configuration enhancements include relocating the pyrekordbox cache file to the user's
11
+ appdata directory and fixing an asar file decoding error.
12
+
13
+ ### Improvements/Bug Fixes
14
+
15
+ - **db:** **allow commiting if playlist is not found in XML ([#149](https://github.com/dylanljones/pyrekordbox/issues/149))**
16
+ This fixes an issue where the changes to the DB can not be commited if the playlist is missing
17
+ in the playlist-xml. A warning is now shown instead. The warning is not shown for special
18
+ playlists.
19
+ - **db:** **add timezone support and fix date format issue ([#161](https://github.com/dylanljones/pyrekordbox/issues/161))**
20
+ Date formats in the DB are now converted to the local timezone. It is now also possible to read date fields with other formats.
21
+ - **config:** **move pyrekordbox cache file to appdir**
22
+ The cache file is now stored in the appdata directory of the user.
23
+ This avoids writing to the pyrekordbox package directory.
24
+ - **config:** **fix asar file decoding error ([#154](https://github.com/dylanljones/pyrekordbox/issues/154))**
25
+
26
+
3
27
  <a name="v0.4.0"></a>
4
28
  ## [v0.4.0] - 2025-02-12
5
29
 
@@ -610,7 +634,8 @@ This release contains documentation fixes.
610
634
  - **add missing djmd tables to `master.db` database documentation**
611
635
 
612
636
 
613
- [Unreleased]: https://github.com/dylanljones/pyrekordbox/compare/v0.4.0...HEAD
637
+ [Unreleased]: https://github.com/dylanljones/pyrekordbox/compare/v0.4.1...HEAD
638
+ [v0.4.1]: https://github.com/dylanljones/pyrekordbox/compare/v0.4.0...v0.4.1
614
639
  [v0.4.0]: https://github.com/dylanljones/pyrekordbox/compare/v0.3.2...v0.4.0
615
640
  [v0.3.2]: https://github.com/dylanljones/pyrekordbox/compare/v0.3.1...v0.3.2
616
641
  [v0.3.1]: https://github.com/dylanljones/pyrekordbox/compare/0.3.0...v0.3.1
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pyrekordbox
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Inofficial Python package for interacting with the library of Pioneers Rekordbox DJ software.
5
5
  Author-email: Dylan Jones <dylanljones94@gmail.com>
6
6
  License: MIT License
@@ -61,6 +61,7 @@ Provides-Extra: test
61
61
  Requires-Dist: hypothesis>=6.0.0; extra == "test"
62
62
  Requires-Dist: pytest>=6.2.0; extra == "test"
63
63
  Requires-Dist: pytest-cov; extra == "test"
64
+ Dynamic: license-file
64
65
 
65
66
 
66
67
  <p align="center">
@@ -88,9 +89,9 @@ Pioneers Rekordbox DJ Software. It currently supports
88
89
 
89
90
  Tested Rekordbox versions: ``5.8.6 | 6.7.7 | 7.0.9``
90
91
 
91
-
92
- |⚠️| This project is still under development and might contain bugs or have breaking API changes in the future. Check the [changelog][CHANGELOG] for recent changes! |
93
- |----|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|
92
+ > [!WARNING]
93
+ > This project is still under development and might contain bugs or have breaking API changes in the future.
94
+ > Check the [changelog][CHANGELOG] for recent changes!
94
95
 
95
96
 
96
97
  ## 🔧 Installation
@@ -118,8 +119,10 @@ If this fails, it can be installed manually following the [installation guide][i
118
119
 
119
120
  [Read the full documentation on ReadTheDocs!][documentation]
120
121
 
121
- | ❗ | Please make sure to back up your Rekordbox collection before making changes with pyrekordbox or developing/testing new features. The backup dialog can be found under "File" > "Library" > "Backup Library" |
122
- |----|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
122
+ > [!CAUTION]
123
+ > Please make sure to back up your Rekordbox collection before making changes with pyrekordbox
124
+ > or developing/testing new features.
125
+ > The backup dialog can be found under "File" > "Library" > "Backup Library"
123
126
 
124
127
 
125
128
  ### Configuration
@@ -174,9 +177,13 @@ can be changed via the corresponding property of the object:
174
177
  ````python
175
178
  content = db.get_content()[0]
176
179
  content.Title = "New Title"
180
+ db.commit()
177
181
  ````
178
- Some fields are stored as references to other tables, for example the artist of a track.
179
- Check the [documentation][db6-doc] of the corresponding object for more information.
182
+
183
+ > [!NOTE]
184
+ > Some fields are stored as references to other tables, for example the artist of a track.
185
+ > Check the [documentation][db6-doc] of the corresponding object for more information.
186
+
180
187
  So far only a few tables support adding or deleting entries:
181
188
  - ``DjmdContent``: Tracks
182
189
  - ``DjmdPlaylist``: Playlists/Playlist Folders
@@ -24,9 +24,9 @@ Pioneers Rekordbox DJ Software. It currently supports
24
24
 
25
25
  Tested Rekordbox versions: ``5.8.6 | 6.7.7 | 7.0.9``
26
26
 
27
-
28
- |⚠️| This project is still under development and might contain bugs or have breaking API changes in the future. Check the [changelog][CHANGELOG] for recent changes! |
29
- |----|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|
27
+ > [!WARNING]
28
+ > This project is still under development and might contain bugs or have breaking API changes in the future.
29
+ > Check the [changelog][CHANGELOG] for recent changes!
30
30
 
31
31
 
32
32
  ## 🔧 Installation
@@ -54,8 +54,10 @@ If this fails, it can be installed manually following the [installation guide][i
54
54
 
55
55
  [Read the full documentation on ReadTheDocs!][documentation]
56
56
 
57
- | ❗ | Please make sure to back up your Rekordbox collection before making changes with pyrekordbox or developing/testing new features. The backup dialog can be found under "File" > "Library" > "Backup Library" |
58
- |----|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
57
+ > [!CAUTION]
58
+ > Please make sure to back up your Rekordbox collection before making changes with pyrekordbox
59
+ > or developing/testing new features.
60
+ > The backup dialog can be found under "File" > "Library" > "Backup Library"
59
61
 
60
62
 
61
63
  ### Configuration
@@ -110,9 +112,13 @@ can be changed via the corresponding property of the object:
110
112
  ````python
111
113
  content = db.get_content()[0]
112
114
  content.Title = "New Title"
115
+ db.commit()
113
116
  ````
114
- Some fields are stored as references to other tables, for example the artist of a track.
115
- Check the [documentation][db6-doc] of the corresponding object for more information.
117
+
118
+ > [!NOTE]
119
+ > Some fields are stored as references to other tables, for example the artist of a track.
120
+ > Check the [documentation][db6-doc] of the corresponding object for more information.
121
+
116
122
  So far only a few tables support adding or deleting entries:
117
123
  - ``DjmdContent``: Tracks
118
124
  - ``DjmdPlaylist``: Playlists/Playlist Folders
@@ -93,7 +93,7 @@ exclude = [
93
93
  "*/_version.py",
94
94
  "docs/*",
95
95
  ]
96
- line-length = 88
96
+ line-length = 100
97
97
  indent-width = 4
98
98
 
99
99
  [tool.ruff.lint]
@@ -1,8 +1,13 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
3
6
  TYPE_CHECKING = False
4
7
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
8
+ from typing import Tuple
9
+ from typing import Union
10
+
6
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
7
12
  else:
8
13
  VERSION_TUPLE = object
@@ -12,5 +17,5 @@ __version__: str
12
17
  __version_tuple__: VERSION_TUPLE
13
18
  version_tuple: VERSION_TUPLE
14
19
 
15
- __version__ = version = '0.4.0'
16
- __version_tuple__ = version_tuple = (0, 4, 0)
20
+ __version__ = version = '0.4.1'
21
+ __version_tuple__ = version_tuple = (0, 4, 1)
@@ -162,13 +162,9 @@ class PQTZAnlzTag(AbstractAnlzTag):
162
162
  n_bpms = len(bpms)
163
163
  n_times = len(times)
164
164
  if n_bpms != n_beats:
165
- raise ValueError(
166
- f"Number of bpms not equal to number of beats: {n_bpms} != {n_beats}"
167
- )
165
+ raise ValueError(f"Number of bpms not equal to number of beats: {n_bpms} != {n_beats}")
168
166
  if n_times != n_beats:
169
- raise ValueError(
170
- f"Number of times not equal to number of beats: {n_bpms} != {n_times}"
171
- )
167
+ raise ValueError(f"Number of times not equal to number of beats: {n_bpms} != {n_times}")
172
168
 
173
169
  # For now only values of existing beats can be set
174
170
  if n_beats != n:
@@ -184,9 +180,7 @@ class PQTZAnlzTag(AbstractAnlzTag):
184
180
  n = len(self.content.entries)
185
181
  n_new = len(beats)
186
182
  if n_new != n:
187
- raise ValueError(
188
- f"Number of beats not equal to current content length: {n_new} != {n}"
189
- )
183
+ raise ValueError(f"Number of beats not equal to current content length: {n_new} != {n}")
190
184
 
191
185
  for i, beat in enumerate(beats):
192
186
  self.content.entries[i].beat = beat
@@ -195,9 +189,7 @@ class PQTZAnlzTag(AbstractAnlzTag):
195
189
  n = len(self.content.entries)
196
190
  n_new = len(bpms)
197
191
  if n_new != n:
198
- raise ValueError(
199
- f"Number of bpms not equal to current content length: {n_new} != {n}"
200
- )
192
+ raise ValueError(f"Number of bpms not equal to current content length: {n_new} != {n}")
201
193
 
202
194
  for i, bpm in enumerate(bpms):
203
195
  self.content.entries[i].tempo = int(bpm * 100)
@@ -206,9 +198,7 @@ class PQTZAnlzTag(AbstractAnlzTag):
206
198
  n = len(self.content.entries)
207
199
  n_new = len(times)
208
200
  if n_new != n:
209
- raise ValueError(
210
- f"Number of times not equal to current content length: {n_new} != {n}"
211
- )
201
+ raise ValueError(f"Number of times not equal to current content length: {n_new} != {n}")
212
202
 
213
203
  for i, t in enumerate(times):
214
204
  self.content.entries[i].time = int(1000 * t)
@@ -30,7 +30,7 @@ logger = logging.getLogger(__name__)
30
30
 
31
31
  # Cache file for pyrekordbox data
32
32
  _cache_file_version = 2
33
- _cache_file = Path(__file__).parent / "rb.cache"
33
+ _cache_file_name = "rb.cache"
34
34
 
35
35
  # Define empty pyrekordbox configuration
36
36
  __config__ = {
@@ -48,6 +48,25 @@ class InvalidApplicationDirname(Exception):
48
48
  pass
49
49
 
50
50
 
51
+ def get_appdata_dir() -> Path:
52
+ """Returns the path of the application data directory.
53
+
54
+ On Windows, the application data is stored in `/Users/user/AppData/Roaming`.
55
+ On macOS the application data is stored in `~/Libary/Application Support`.
56
+ """
57
+ if sys.platform == "win32":
58
+ # Windows: located in /Users/user/AppData/Roaming/
59
+ app_data = Path(os.environ["AppData"])
60
+ elif sys.platform == "darwin":
61
+ # MacOS: located in ~/Library/Application Support/
62
+ app_data = Path("~").expanduser() / "Library" / "Application Support"
63
+ else:
64
+ # Linux: not supported
65
+ logger.warning(f"OS {sys.platform} not supported!")
66
+ return Path("~").expanduser() / ".local" / "share"
67
+ return app_data
68
+
69
+
51
70
  def get_pioneer_install_dir(path: Union[str, Path] = None) -> Path: # pragma: no cover
52
71
  """Returns the path of the Pioneer program installation directory.
53
72
 
@@ -234,12 +253,7 @@ def read_rekordbox6_asar(rb6_install_dir: Union[str, Path]) -> str:
234
253
  if not str(rb6_install_dir).endswith(".app"):
235
254
  rb6_install_dir = rb6_install_dir / "rekordbox.app"
236
255
  location = (
237
- rb6_install_dir
238
- / "Contents"
239
- / "MacOS"
240
- / "rekordboxAgent.app"
241
- / "Contents"
242
- / "Resources"
256
+ rb6_install_dir / "Contents" / "MacOS" / "rekordboxAgent.app" / "Contents" / "Resources"
243
257
  )
244
258
  encoding = "cp437"
245
259
  else:
@@ -249,7 +263,7 @@ def read_rekordbox6_asar(rb6_install_dir: Union[str, Path]) -> str:
249
263
  # Read asar file
250
264
  path = (location / "app.asar").absolute()
251
265
  with open(path, "rb") as fh:
252
- data = fh.read().decode(encoding)
266
+ data = fh.read().decode(encoding, errors="replace")
253
267
  return data
254
268
 
255
269
 
@@ -360,9 +374,7 @@ def _get_rb_config(
360
374
  return conf
361
375
 
362
376
 
363
- def _get_rb5_config(
364
- pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = ""
365
- ) -> dict:
377
+ def _get_rb5_config(pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = "") -> dict:
366
378
  """Get the program configuration for Rekordbox v5.x.x."""
367
379
  major_version = 5
368
380
  conf = _get_rb_config(pioneer_prog_dir, pioneer_app_dir, major_version, dirname)
@@ -414,8 +426,7 @@ class KeyExtractor:
414
426
  pid = get_rekordbox_pid()
415
427
  if pid:
416
428
  raise RuntimeError(
417
- "Rekordbox is running. "
418
- "Please close Rekordbox before running the `KeyExtractor`."
429
+ "Rekordbox is running. Please close Rekordbox before running the `KeyExtractor`."
419
430
  )
420
431
  # Spawn Rekordbox process and attach to it
421
432
  pid = frida.spawn(self.executable)
@@ -434,12 +445,16 @@ class KeyExtractor:
434
445
 
435
446
 
436
447
  def write_db6_key_cache(key: str) -> None: # pragma: no cover
437
- """Writes the decrypted Rekordbox6 database key to the cache file.
448
+ r"""Writes the decrypted Rekordbox6 database key to the cache file.
438
449
 
439
450
  This method can also be used to manually cache the database key, provided
440
451
  the user has found the key somewhere else. The key can be, for example,
441
452
  found in some other projects that hard-coded it.
442
453
 
454
+ The cache file is stored in the application data directory of pyrekordbox:
455
+ Windows: `C:\Users\<user>\AppData\Roaming\pyrekordbox`
456
+ macOS: `~/Library/Application Support/pyrekordbox`
457
+
443
458
  Parameters
444
459
  ----------
445
460
  key : str
@@ -461,7 +476,12 @@ def write_db6_key_cache(key: str) -> None: # pragma: no cover
461
476
  lines.append(f"version: {_cache_file_version}")
462
477
  lines.append("dp: " + key)
463
478
  text = "\n".join(lines)
464
- with open(_cache_file, "w") as fh:
479
+
480
+ cache_file = get_appdata_dir() / "pyrekordbox" / _cache_file_name
481
+ if not cache_file.parent.exists():
482
+ cache_file.parent.mkdir()
483
+
484
+ with open(cache_file, "w") as fh:
465
485
  fh.write(text)
466
486
  # Set the config key to make sure the key is present after calling method
467
487
  if __config__["rekordbox6"]:
@@ -473,10 +493,13 @@ def write_db6_key_cache(key: str) -> None: # pragma: no cover
473
493
  def _update_sqlite_key(opts, conf):
474
494
  cache_version = 0
475
495
  pw, dp = "", ""
476
- if _cache_file.exists(): # pragma: no cover
477
- logger.debug("Found cache file %s", _cache_file)
496
+
497
+ cache_file = get_appdata_dir() / "pyrekordbox" / _cache_file_name
498
+
499
+ if cache_file.exists(): # pragma: no cover
500
+ logger.debug("Found cache file %s", cache_file)
478
501
  # Read cache file
479
- with open(_cache_file, "r") as fh:
502
+ with open(cache_file, "r") as fh:
480
503
  text = fh.read()
481
504
  lines = text.splitlines()
482
505
  if lines[0].startswith("version:"):
@@ -551,9 +574,7 @@ def _update_sqlite_key(opts, conf):
551
574
  conf["dp"] = dp
552
575
 
553
576
 
554
- def _get_rb6_config(
555
- pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = ""
556
- ) -> dict:
577
+ def _get_rb6_config(pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = "") -> dict:
557
578
  """Get the program configuration for Rekordbox v6.x.x."""
558
579
  major_version = 6
559
580
  conf = _get_rb_config(pioneer_prog_dir, pioneer_app_dir, major_version, dirname)
@@ -571,9 +592,7 @@ def _get_rb6_config(
571
592
  return conf
572
593
 
573
594
 
574
- def _get_rb7_config(
575
- pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = ""
576
- ) -> dict:
595
+ def _get_rb7_config(pioneer_prog_dir: Path, pioneer_app_dir: Path, dirname: str = "") -> dict:
577
596
  """Get the program configuration for Rekordbox v7.x.x."""
578
597
  major_version = 7
579
598
  conf = _get_rb_config(pioneer_prog_dir, pioneer_app_dir, major_version, dirname)
@@ -715,27 +734,21 @@ def update_config(
715
734
 
716
735
  # Update Rekordbox 5 config
717
736
  try:
718
- conf = _get_rb5_config(
719
- pioneer_install_dir, pioneer_app_dir, rb5_install_dirname
720
- )
737
+ conf = _get_rb5_config(pioneer_install_dir, pioneer_app_dir, rb5_install_dirname)
721
738
  __config__["rekordbox5"].update(conf)
722
739
  except FileNotFoundError as e:
723
740
  logger.info(e)
724
741
 
725
742
  # Update Rekordbox 6 config
726
743
  try:
727
- conf = _get_rb6_config(
728
- pioneer_install_dir, pioneer_app_dir, rb6_install_dirname
729
- )
744
+ conf = _get_rb6_config(pioneer_install_dir, pioneer_app_dir, rb6_install_dirname)
730
745
  __config__["rekordbox6"].update(conf)
731
746
  except FileNotFoundError as e:
732
747
  logger.info(e)
733
748
 
734
749
  # Update Rekordbox 7 config
735
750
  try:
736
- conf = _get_rb7_config(
737
- pioneer_install_dir, pioneer_app_dir, rb7_install_dirname
738
- )
751
+ conf = _get_rb7_config(pioneer_install_dir, pioneer_app_dir, rb7_install_dirname)
739
752
  __config__["rekordbox7"].update(conf)
740
753
  except FileNotFoundError as e:
741
754
  logger.info(e)
@@ -33,6 +33,10 @@ except ImportError:
33
33
  _sqlcipher_available = False
34
34
 
35
35
  MAX_VERSION = "6.6.5"
36
+ SPECIAL_PLAYLIST_IDS = [
37
+ "100000", # Cloud Library Sync
38
+ "200000", # CUE Analysis Playlist
39
+ ]
36
40
 
37
41
  logger = logging.getLogger(__name__)
38
42
 
@@ -114,9 +118,7 @@ class Rekordbox6Database:
114
118
  path = rb_config.get("db_path", "")
115
119
  if not path:
116
120
  pdir = get_config("pioneer", "install_dir")
117
- raise FileNotFoundError(
118
- f"No Rekordbox v6/v7 directory found in '{pdir}'"
119
- )
121
+ raise FileNotFoundError(f"No Rekordbox v6/v7 directory found in '{pdir}'")
120
122
  path = Path(path)
121
123
  # make sure file exists
122
124
  if not path.exists():
@@ -124,9 +126,7 @@ class Rekordbox6Database:
124
126
  # Open database
125
127
  if unlock:
126
128
  if not _sqlcipher_available:
127
- raise ImportError(
128
- "Could not unlock database: 'sqlcipher3' package not found"
129
- )
129
+ raise ImportError("Could not unlock database: 'sqlcipher3' package not found")
130
130
  if not key:
131
131
  try:
132
132
  key = rb_config["dp"]
@@ -404,17 +404,20 @@ class Rekordbox6Database:
404
404
  # Sync the updated_at values of the playlists in the DB and the XML file
405
405
  for pl in self.get_playlist():
406
406
  plxml = self.playlist_xml.get(pl.ID)
407
- if plxml is None:
408
- raise ValueError(
409
- f"Playlist {pl.ID} not found in masterPlaylists6.xml! "
410
- "Did you add it manually? "
411
- "Use the create_playlist method instead."
412
- )
413
- ts = plxml["Timestamp"]
414
- diff = pl.updated_at - ts
415
- if abs(diff.total_seconds()) > 1:
416
- logger.debug("Updating updated_at of playlist %s in XML", pl.ID)
417
- self.playlist_xml.update(pl.ID, updated_at=pl.updated_at)
407
+ if plxml is not None:
408
+ ts = plxml["Timestamp"]
409
+ diff = pl.updated_at - ts
410
+ if abs(diff.total_seconds()) > 1:
411
+ logger.debug("Updating updated_at of playlist %s in XML", pl.ID)
412
+ self.playlist_xml.update(pl.ID, updated_at=pl.updated_at)
413
+ else:
414
+ # Dont warn for special playlists
415
+ if pl.ID not in SPECIAL_PLAYLIST_IDS:
416
+ logger.warning(
417
+ f"Playlist {pl.ID} not found in masterPlaylists6.xml! "
418
+ "Did you add it manually? "
419
+ "Use the create_playlist method instead."
420
+ )
418
421
 
419
422
  # Save the XML file if it was modified
420
423
  if self.playlist_xml.modified:
@@ -726,9 +729,7 @@ class Rekordbox6Database:
726
729
 
727
730
  # -- Database updates --------------------------------------------------------------
728
731
 
729
- def generate_unused_id(
730
- self, table, is_28_bit: bool = True, id_field_name: str = "ID"
731
- ) -> int:
732
+ def generate_unused_id(self, table, is_28_bit: bool = True, id_field_name: str = "ID") -> int:
732
733
  """Generates an unused ID for the given table."""
733
734
  max_tries = 1000000
734
735
  for _ in range(max_tries):
@@ -803,20 +804,14 @@ class Rekordbox6Database:
803
804
  uuid = str(uuid4())
804
805
  id_ = str(uuid4())
805
806
  now = datetime.datetime.now()
806
- nsongs = (
807
- self.query(tables.DjmdSongPlaylist)
808
- .filter_by(PlaylistID=playlist.ID)
809
- .count()
810
- )
807
+ nsongs = self.query(tables.DjmdSongPlaylist).filter_by(PlaylistID=playlist.ID).count()
811
808
  if track_no is not None:
812
809
  insert_at_end = False
813
810
  track_no = int(track_no)
814
811
  if track_no < 1:
815
812
  raise ValueError("Track number must be greater than 0")
816
813
  if track_no > nsongs + 1:
817
- raise ValueError(
818
- f"Track number too high, parent contains {nsongs} items"
819
- )
814
+ raise ValueError(f"Track number too high, parent contains {nsongs} items")
820
815
  else:
821
816
  insert_at_end = True
822
817
  track_no = nsongs + 1
@@ -892,9 +887,7 @@ class Rekordbox6Database:
892
887
  playlist = self.get_playlist(ID=playlist)
893
888
  if isinstance(song, (int, str)):
894
889
  song = self.query(tables.DjmdSongPlaylist).filter_by(ID=song).one()
895
- logger.info(
896
- "Removing song with ID=%s from playlist with ID=%s", song.ID, playlist.ID
897
- )
890
+ logger.info("Removing song with ID=%s from playlist with ID=%s", song.ID, playlist.ID)
898
891
  now = datetime.datetime.now()
899
892
  # Remove track from playlist
900
893
  track_no = song.TrackNo
@@ -965,11 +958,7 @@ class Rekordbox6Database:
965
958
  playlist = self.get_playlist(ID=playlist)
966
959
  if isinstance(song, (int, str)):
967
960
  song = self.query(tables.DjmdSongPlaylist).filter_by(ID=song).one()
968
- nsongs = (
969
- self.query(tables.DjmdSongPlaylist)
970
- .filter_by(PlaylistID=playlist.ID)
971
- .count()
972
- )
961
+ nsongs = self.query(tables.DjmdSongPlaylist).filter_by(PlaylistID=playlist.ID).count()
973
962
  if new_track_no < 1:
974
963
  raise ValueError("Track number must be greater than 0")
975
964
  if new_track_no > nsongs + 1:
@@ -1019,9 +1008,7 @@ class Rekordbox6Database:
1019
1008
  self.registry.enable_tracking()
1020
1009
  self.registry.on_move(moved)
1021
1010
 
1022
- def _create_playlist(
1023
- self, name, seq, image_path, parent, smart_list=None, attribute=None
1024
- ):
1011
+ def _create_playlist(self, name, seq, image_path, parent, smart_list=None, attribute=None):
1025
1012
  """Creates a new playlist object."""
1026
1013
  table = tables.DjmdPlaylist
1027
1014
  id_ = str(self.generate_unused_id(table, is_28_bit=True))
@@ -1046,9 +1033,7 @@ class Rekordbox6Database:
1046
1033
  else:
1047
1034
  # Check if parent exists and is a folder
1048
1035
  parent_id = parent
1049
- query = self.query(table.ID).filter(
1050
- table.ID == parent_id, table.Attribute == 1
1051
- )
1036
+ query = self.query(table.ID).filter(table.ID == parent_id, table.Attribute == 1)
1052
1037
  if not self.query(query.exists()).scalar():
1053
1038
  raise ValueError("Parent does not exist or is not a folder")
1054
1039
 
@@ -1107,9 +1092,7 @@ class Rekordbox6Database:
1107
1092
 
1108
1093
  # Update masterPlaylists6.xml
1109
1094
  if self.playlist_xml is not None:
1110
- self.playlist_xml.add(
1111
- id_, parent_id, attribute, now, lib_type=0, check_type=0
1112
- )
1095
+ self.playlist_xml.add(id_, parent_id, attribute, now, lib_type=0, check_type=0)
1113
1096
 
1114
1097
  return playlist
1115
1098
 
@@ -1157,9 +1140,7 @@ class Rekordbox6Database:
1157
1140
  '123456'
1158
1141
  """
1159
1142
  logger.info("Creating playlist %s", name)
1160
- return self._create_playlist(
1161
- name, seq, image_path, parent, attribute=PlaylistType.PLAYLIST
1162
- )
1143
+ return self._create_playlist(name, seq, image_path, parent, attribute=PlaylistType.PLAYLIST)
1163
1144
 
1164
1145
  def create_playlist_folder(self, name, parent=None, seq=None, image_path=None):
1165
1146
  """Creates a new playlist folder in the database.
@@ -1199,9 +1180,7 @@ class Rekordbox6Database:
1199
1180
  '123456'
1200
1181
  """
1201
1182
  logger.info("Creating playlist folder %s", name)
1202
- return self._create_playlist(
1203
- name, seq, image_path, parent, attribute=PlaylistType.FOLDER
1204
- )
1183
+ return self._create_playlist(name, seq, image_path, parent, attribute=PlaylistType.FOLDER)
1205
1184
 
1206
1185
  def create_smart_playlist(
1207
1186
  self, name, smart_list: SmartList, parent=None, seq=None, image_path=None
@@ -1276,9 +1255,7 @@ class Rekordbox6Database:
1276
1255
  playlist = self.get_playlist(ID=playlist)
1277
1256
 
1278
1257
  if playlist.Attribute == 1:
1279
- logger.info(
1280
- "Deleting playlist folder '%s' with ID=%s", playlist.Name, playlist.ID
1281
- )
1258
+ logger.info("Deleting playlist folder '%s' with ID=%s", playlist.Name, playlist.ID)
1282
1259
  else:
1283
1260
  logger.info("Deleting playlist '%s' with ID=%s", playlist.Name, playlist.ID)
1284
1261
 
@@ -1391,9 +1368,7 @@ class Rekordbox6Database:
1391
1368
  else:
1392
1369
  # Check if parent exists and is a folder
1393
1370
  parent_id = str(parent)
1394
- query = self.query(table.ID).filter(
1395
- table.ID == parent_id, table.Attribute == 1
1396
- )
1371
+ query = self.query(table.ID).filter(table.ID == parent_id, table.Attribute == 1)
1397
1372
  if not self.query(query.exists()).scalar():
1398
1373
  raise ValueError("Parent does not exist or is not a folder")
1399
1374
 
@@ -1414,9 +1389,7 @@ class Rekordbox6Database:
1414
1389
  if seq < 1:
1415
1390
  raise ValueError("Sequence number must be greater than 0")
1416
1391
  elif seq > n + 1:
1417
- raise ValueError(
1418
- f"Sequence number too high, parent contains {n} items"
1419
- )
1392
+ raise ValueError(f"Sequence number too high, parent contains {n} items")
1420
1393
 
1421
1394
  if not insert_at_end:
1422
1395
  # Get all playlists with seq between old_seq and seq
@@ -1550,9 +1523,7 @@ class Rekordbox6Database:
1550
1523
  with self.registry.disabled():
1551
1524
  playlist.updated_at = now
1552
1525
 
1553
- def add_album(
1554
- self, name, artist=None, image_path=None, compilation=None, search_str=None
1555
- ):
1526
+ def add_album(self, name, artist=None, image_path=None, compilation=None, search_str=None):
1556
1527
  """Adds a new album to the database.
1557
1528
 
1558
1529
  Parameters
@@ -1684,9 +1655,7 @@ class Rekordbox6Database:
1684
1655
 
1685
1656
  id_ = self.generate_unused_id(tables.DjmdArtist)
1686
1657
  uuid = str(uuid4())
1687
- artist = tables.DjmdArtist.create(
1688
- ID=id_, Name=name, SearchStr=search_str, UUID=uuid
1689
- )
1658
+ artist = tables.DjmdArtist.create(ID=id_, Name=name, SearchStr=search_str, UUID=uuid)
1690
1659
  self.add(artist)
1691
1660
  self.flush()
1692
1661
  return artist
@@ -1828,9 +1797,7 @@ class Rekordbox6Database:
1828
1797
  raise ValueError(f"Track with path '{path}' already exists in database")
1829
1798
 
1830
1799
  id_ = self.generate_unused_id(tables.DjmdContent)
1831
- file_id = self.generate_unused_id(
1832
- tables.DjmdContent, id_field_name="rb_file_id"
1833
- )
1800
+ file_id = self.generate_unused_id(tables.DjmdContent, id_field_name="rb_file_id")
1834
1801
  uuid = str(uuid4())
1835
1802
  content_link = self.get_menu_items(Name="TRACK").one()
1836
1803
  date_created = datetime.date.today()
@@ -1987,9 +1954,7 @@ class Rekordbox6Database:
1987
1954
  return AnlzFile.parse_file(path)
1988
1955
  return None
1989
1956
 
1990
- def update_content_path(
1991
- self, content, path, save=True, check_path=True, commit=True
1992
- ):
1957
+ def update_content_path(self, content, path, save=True, check_path=True, commit=True):
1993
1958
  """Update the file path of a track in the Rekordbox v6 database.
1994
1959
 
1995
1960
  This changes the `FolderPath` entry in the ``DjmdContent`` table and the
@@ -2080,9 +2045,7 @@ class Rekordbox6Database:
2080
2045
  logger.debug("Committing changes to the database")
2081
2046
  self.commit()
2082
2047
 
2083
- def update_content_filename(
2084
- self, content, name, save=True, check_path=True, commit=True
2085
- ):
2048
+ def update_content_filename(self, content, name, save=True, check_path=True, commit=True):
2086
2049
  """Update the file name of a track in the Rekordbox v6 database.
2087
2050
 
2088
2051
  This changes the `FolderPath` entry in the ``DjmdContent`` table and the