diff --git a/Browser.py b/Browser.py index 9f7de76..4d3ed8e 100644 --- a/Browser.py +++ b/Browser.py @@ -203,7 +203,7 @@ def __init__(self, browser, log): self._filtered = [] self._current_index = 0 self._iterate_and_find_audio(browser.user_library) - self._playing_tracks = {} + self._decks = {} if os.path.exists(self.SOCKET_IN): os.remove(self.SOCKET_IN) @@ -274,8 +274,10 @@ def _apply_filter(self): def _update_key_distance(self): self._playing_key = None - for i in self._playing_tracks.keys(): - self._playing_key = self._playing_tracks[i].open_key + for deck in self._decks: + if deck == None: + continue + self._playing_key = deck.open_key break for item in self._current: @@ -306,21 +308,23 @@ def _update(self): r.append(getattr(item, k.lower())) d["rows"].append(r) - for track_ix in self._playing_tracks.keys(): - d["playing"][track_ix] = [] - for k in d["cols"]: - d["playing"][track_ix].append(getattr(self._playing_tracks[track_ix], k.lower())) + d["decks"] = [] + for deck in self._decks: + d["decks"].append([]) + if deck != None: + for k in d["cols"]: + d["decks"][-1].append(getattr(deck, k.lower())) try: self._socket.sendto(json.dumps(d, indent=1).encode('utf-8'), self.SOCKET_OUT) except: pass - def set_playing_tracks(self, playing_tracks): - p = {} - for i in playing_tracks.keys(): - p[i] = TaggedFile(playing_tracks[i]) - self._playing_tracks = p + def set_decks(self, decks): + d = [] + for f in decks: + d.append(TaggedFile(f) if f != None else None) + self._decks = d self._update_key_distance() self._apply_filter() self._update() diff --git a/src/LiveMusicBrowser.cpp b/src/LiveMusicBrowser.cpp index 470a882..121b3e7 100644 --- a/src/LiveMusicBrowser.cpp +++ b/src/LiveMusicBrowser.cpp @@ -34,16 +34,17 @@ void drawFilters(const json11::Json& data, json11::Json& send_data) } } -void drawPlayingTracks(const json11::Json& data) +void drawPlayingDecks(const json11::Json& data) { ImGui::Text("Now Playing:"); ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit; - if (not data["playing"].is_null() and ImGui::BeginTable("playing", data["cols"].array_items().size(), flags)) + if (not data["decks"].is_null() and ImGui::BeginTable("decks", data["cols"].array_items().size(), flags)) { ImGui::TableSetupColumn("Deck"); int key_distance_col_ix = -1; - int col_ix = 1; + int col_ix = 0; + int num_columns = 0; for (const auto& col_name: data["cols"].array_items()) { if (col_name.string_value() == "KeyDistance") @@ -52,30 +53,38 @@ void drawPlayingTracks(const json11::Json& data) continue; } ImGui::TableSetupColumn(col_name.string_value().c_str()); + num_columns++; col_ix++; } ImGui::TableHeadersRow(); - int display_column_offset = 0; - for (const auto& track: data["playing"].object_items()) + num_columns++; // account for the 'deck' column + int deck_displayed_index = 1; + for (const auto& row: data["decks"].array_items()) { + int display_column_offset = 0; ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - ImGui::TextUnformatted(track.first.c_str()); - for (int column = 1; column <= track.second.array_items().size(); column++) + ImGui::Text("%d", deck_displayed_index++); + for (int column = 0; column < row.array_items().size(); column++) { if (column == key_distance_col_ix) { // skip the column with the key distance display_column_offset++; continue; } - ImGui::TableSetColumnIndex(column - display_column_offset); - if (track.second[column-1].is_number()) { - ImGui::Text("%3.5g", track.second[column-1].number_value()); + ImGui::TableSetColumnIndex(column - display_column_offset + 1); + if (row[column].is_number()) { + ImGui::Text("%3.5g", row[column].number_value()); } else { - ImGui::TextUnformatted(track.second[column-1].string_value().c_str()); + ImGui::TextUnformatted(row[column].string_value().c_str()); } } + // pad missing columns (e.g. for empty rows) + for (int column = ImGui::TableGetColumnIndex() + 1; column < num_columns; column++) { + ImGui::TableSetColumnIndex(column); + ImGui::Text(""); + } } ImGui::EndTable(); } @@ -185,7 +194,7 @@ void drawFrame(int display_w, int display_h, const json11::Json& data, json11::J ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::Begin("Browse", nullptr, window_flags); - drawPlayingTracks(data); + drawPlayingDecks(data); ImGui::Separator(); drawFilters(data, send_data); ImGui::Separator(); diff --git a/xone.py b/xone.py index b183d19..a3f1887 100644 --- a/xone.py +++ b/xone.py @@ -762,33 +762,34 @@ def is_track_playing(self, track): def is_selected_slot_playing(self, track_idx): slot = self.song().view.selected_scene.clip_slots[track_idx] state = ClipState.STOPPED - playing_file = None if slot.has_clip: if slot.clip.is_playing: state = ClipState.PLAYING - playing_file = slot.clip.file_path elif slot.clip.is_triggered: state = ClipState.TRIGGERED elif slot.clip.is_audio_clip and not slot.clip.warping: # special state so we can emit warning when warping is not on state = ClipState.STOPPED_NO_WARP - return slot.has_clip, state, playing_file - + return slot.has_clip, state def update_track_playing_status(self): i = 0 - playing_tracks = {} + playing_tracks = [] for track in self.song().tracks: if i >= NUM_TRACKS: return - is_selected, clip_state, playing_file = self.is_selected_slot_playing(i) + is_selected, clip_state = self.is_selected_slot_playing(i) self.clip_start_buttons[i].set_clip_selected(is_selected, clip_state) self.track_stop_buttons[i].set_track_playing(self.is_track_playing(track)) - if playing_file != None: - playing_tracks[i] = playing_file + + if track.playing_slot_index >= 0: + slot = track.clip_slots[track.playing_slot_index] + playing_tracks.append(slot.clip.file_path) + else: + playing_tracks.append(None) i += 1 - self.browser_repr.set_playing_tracks(playing_tracks) + self.browser_repr.set_decks(playing_tracks) def clip_add_callback(self, clip, track_idx, clip_idx): callback = lambda : self.on_clip_playing_changed(clip, track_idx, clip_idx)