Skip to content

Commit be0aa67

Browse files
committed
Add currently key and currently playing track(s)
1 parent b5bd8d5 commit be0aa67

File tree

5 files changed

+375
-202
lines changed

5 files changed

+375
-202
lines changed

Browser.py

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,106 @@
33
import os
44
import socket
55
import json
6+
import pathlib
7+
import time
68
from XoneK2_DJ.tinytag import TinyTag
79
from urllib.parse import unquote
810

9-
class BrowserItem():
10-
def __init__(self, live_browser_item):
11-
self._item = live_browser_item
12-
self._file_name = self._uri_to_path(self._item.uri)
11+
MUSIC_TO_OPEN_KEY = {
12+
'Am': '1m',
13+
'C': '1d',
14+
'Em': '2m',
15+
'G': '2d',
16+
'Bm': '3m',
17+
'D': '3d',
18+
'F#m': '4m',
19+
'Gbm': '4m',
20+
'A': '4d',
21+
'Dbm': '5m',
22+
'C#m': '5m',
23+
'E': '5d',
24+
'Abm': '6m',
25+
'G#m': '6m',
26+
'B': '6d',
27+
'Ebm': '7m',
28+
'D#m': '7m',
29+
'F#': '7d',
30+
'Gb': '7d',
31+
'Bbm': '8m',
32+
'A#m': '8m',
33+
'Db': '8d',
34+
'C#': '8d',
35+
'Fm': '9m',
36+
'Ab': '9d',
37+
'G#': '9d',
38+
'Cm': '10m',
39+
'Eb': '10d',
40+
'D#': '10d',
41+
'Gm': '11m',
42+
'Bb': '11d',
43+
'A#': '11d',
44+
'Dm': '12m',
45+
'F': '12d'
46+
}
47+
48+
OPEN_TO_MUSICAL_KEY = {
49+
'1m': 'Am',
50+
'1d': 'C',
51+
'2m': 'Em',
52+
'2d': 'G',
53+
'3m': 'Bm',
54+
'3d': 'D',
55+
'4m': 'F#m',
56+
'4d': 'A',
57+
'5m': 'C#m',
58+
'5d': 'E',
59+
'6m': 'G#m',
60+
'6d': 'B',
61+
'7m': 'D#m',
62+
'7d': 'F#',
63+
'8m': 'A#m',
64+
'8d': 'C#',
65+
'9m': 'Fm',
66+
'9d': 'G#',
67+
'10m': 'Cm',
68+
'10d': 'D#',
69+
'11m': 'Gm',
70+
'11d': 'A#',
71+
'12m': 'Dm',
72+
'12d': 'F'
73+
}
74+
75+
def uri_to_path(uri):
76+
path = re.sub('^query:UserLibrary#', '~/Music/Ableton/User Library/', uri)
77+
path = re.sub(':','/', path)
78+
path = unquote(path)
79+
return path
80+
81+
class TaggedFile():
82+
def __init__(self, filename):
83+
self._file_name = filename
1384
self._tags = TinyTag.get(self._file_name)
1485
self._duration = "%d:%02d" % (int(self._tags.duration)/60, int(self._tags.duration) % 60)
1586
self._bpm = self._tags.extra['bpm'] if 'bpm' in self._tags.extra else "none"
1687
self._key = self._tags.extra['initial_key'] if 'initial_key' in self._tags.extra else "none"
17-
18-
def _uri_to_path(self, uri):
19-
path = re.sub('^query:UserLibrary#', '~/Music/Ableton/User Library/', uri)
20-
path = re.sub(':','/', path)
21-
path = unquote(path)
22-
return path
88+
self._normaliseKey()
89+
90+
def _normaliseKey(self):
91+
self._open_key = ""
92+
self._musical_key = ""
93+
if re.match("[0-9]{1,2}[dm]", self._key):
94+
self._open_key = self._key
95+
self._musical_key = OPEN_TO_MUSICAL_KEY[self._key] if self._key in OPEN_TO_MUSICAL_KEY.keys() else "?"
96+
else:
97+
key = re.sub('maj', '', self._key)
98+
key = re.sub('min','m', key)
99+
self._musical_key = key
100+
self._open_key = MUSIC_TO_OPEN_KEY[key] if key in MUSIC_TO_OPEN_KEY.keys() else "?"
23101

24102
@property
25103
def filename(self):
26104
return self._file_name
27105

28-
def item(self):
29-
return self._item
30-
31106
@property
32107
def artist(self):
33108
return self._tags.artist
@@ -42,7 +117,7 @@ def duration(self):
42117

43118
@property
44119
def key(self):
45-
return self._key
120+
return self._open_key + " / " + self._musical_key
46121

47122
@property
48123
def bpm(self):
@@ -53,6 +128,14 @@ def genre(self):
53128
return self._tags.genre or "undefined"
54129

55130

131+
class BrowserItem(TaggedFile):
132+
def __init__(self, live_browser_item):
133+
super(BrowserItem, self).__init__(uri_to_path(live_browser_item.uri))
134+
self._item = live_browser_item
135+
136+
def item(self):
137+
return self._item
138+
56139
class BrowserRepresentation():
57140

58141
SOCKET_IN = "/tmp/LiveMusicBrowser.src.socket"
@@ -64,14 +147,15 @@ def __init__(self, browser):
64147
self._current = []
65148
self._current_index = 0
66149
self._iterate_and_find_audio(browser.user_library)
150+
self._playing_tracks = {}
67151

68152
if os.path.exists(self.SOCKET_IN):
69153
os.remove(self.SOCKET_IN)
70154

71155
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
72156
self._socket.bind(self.SOCKET_IN)
73157
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 250*1024)
74-
# os.system("/Users/sam/Projects/GeoLEDic/build/GeoLEDic.app/Contents/MacOS/GeoLEDic&")
158+
self.startUi()
75159
self._update()
76160

77161
def _iterate_and_find_audio(self, node):
@@ -111,7 +195,8 @@ def _update(self):
111195
"BPM",
112196
"Key"
113197
],
114-
"rows": []
198+
"rows": [],
199+
"playing": {}
115200
}
116201

117202
for item in self._current:
@@ -120,7 +205,40 @@ def _update(self):
120205
r.append(getattr(item, k.lower()))
121206
d["rows"].append(r)
122207

208+
for track_ix in self._playing_tracks.keys():
209+
d["playing"][track_ix] = []
210+
for k in d["cols"]:
211+
d["playing"][track_ix].append(getattr(self._playing_tracks[track_ix], k.lower()))
212+
123213
try:
124214
self._socket.sendto(json.dumps(d, indent=1).encode('utf-8'), self.SOCKET_OUT)
125215
except:
126-
pass
216+
pass
217+
218+
def setPlayingTracks(self, playing_tracks):
219+
p = {}
220+
for i in playing_tracks.keys():
221+
p[i] = TaggedFile(playing_tracks[i])
222+
self._playing_tracks = p
223+
self._update()
224+
225+
def startUi(self):
226+
pwd = pathlib.Path(__file__).parent.resolve()
227+
os.system("'%s/build/LiveMusicBrowser' &" % pwd)
228+
timeout = 10
229+
while (timeout > 0 and not os.path.exists(self.SOCKET_OUT)):
230+
time.sleep(0.1)
231+
timeout = timeout - 1
232+
233+
234+
def quitUi(self):
235+
try:
236+
self._socket.sendto(json.dumps({"quit": True}).encode('utf-8'), self.SOCKET_OUT)
237+
except:
238+
pass
239+
240+
def __del__(self):
241+
self.quitUi()
242+
243+
def disconnect(self):
244+
self.quitUi()

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_definitions(
2121
)
2222

2323
add_executable(LiveMusicBrowser
24+
${CMAKE_SOURCE_DIR}/main.cpp
2425
${CMAKE_SOURCE_DIR}/LiveMusicBrowser.cpp
2526
${CMAKE_SOURCE_DIR}/imgui/imgui.cpp
2627
${CMAKE_SOURCE_DIR}/imgui/imgui_demo.cpp

0 commit comments

Comments
 (0)