Skip to content

Commit

Permalink
Merge remote-tracking branch 'mixxx/2.4' into 2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
ronso0 committed Sep 27, 2024
2 parents c12d6bd + 9db85cf commit 5bf07b5
Show file tree
Hide file tree
Showing 27 changed files with 525 additions and 334 deletions.
128 changes: 64 additions & 64 deletions res/controllers/Reloop Beatmix 2-4.midi.xml

Large diffs are not rendered by default.

74 changes: 46 additions & 28 deletions res/controllers/Reloop-Beatmix-2-4-scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const JogFlashCriticalTime = 15; // number of seconds to quickly blink at the en
**********************************************************************
* User References
* ---------------
* Wiki/manual : http://www.mixxx.org/wiki/doku.php/reloop_beatmix_2
* Wiki/manual : http://www.mixxx.org/wiki/doku.php/reloop_beatmix_4
* support forum : http://mixxx.org/forums/viewtopic.php?f=7&t=8428
* Wiki/manual : https://github.com/mixxxdj/mixxx/wiki/reloop-beatmix-2
* Wiki/manual : https://github.com/mixxxdj/mixxx/wiki/Reloop-Beatmix-4
* support forum : https://mixxx.discourse.group/t/reloop-beatmix-2-4-mapping/16049
*
* Thanks
* ----------------
Expand All @@ -35,10 +35,11 @@ const JogFlashCriticalTime = 15; // number of seconds to quickly blink at the en
* 2016-08-15 - v1.2.1 - fix small typos and bugs
* 2016-08-17 - v1.3 - sync each item on the controller with Mixxx at launch
* 2016-08-19 - v1.3.1 - fix nex/prev effect button release and superknob responsiveness
* 2024-08-25 - v2.0.0 - Fixes & rewrites for Mixxx 2.4
***********************************************************************
* GPL v2 licence
* --------------
* Reloop Beatmix controller script script 1.3.1 for Mixxx 2.1.0
* Reloop Beatmix controller script script 2.0.0 for Mixxx 2.4+
* Copyright (C) 2016 Sébastien Blaisot
*
* This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -158,30 +159,38 @@ ReloopBeatmix24.connectControls = function() {
// Channels controls
for (let i = 1; i <= 4; i++) {
group = "[Channel" + i + "]";
engine.connectControl(group, "track_samples",
"ReloopBeatmix24.deckLoaded");
engine.connectControl(group, "play",
"ReloopBeatmix24.ChannelPlay");
engine.connectControl(group, "playposition",
"ReloopBeatmix24.JogLed");
engine.connectControl(group, "loop_end_position",
"ReloopBeatmix24.loopDefined");
engine.makeConnection(group, "track_loaded",
ReloopBeatmix24.deckLoaded);
engine.trigger(group, "track_loaded");
engine.makeConnection(group, "play",
ReloopBeatmix24.ChannelPlay);
engine.trigger(group, "play");
engine.makeConnection(group, "playposition",
ReloopBeatmix24.JogLed);
engine.trigger(group, "playposition");
engine.makeConnection(group, "loop_end_position",
ReloopBeatmix24.loopDefined);
engine.trigger(group, "loop_end_position");
engine.softTakeover(group, "rate", true);
engine.setValue("[EffectRack1_EffectUnit1]",
"group_" + group + "_enable", 0);
engine.setValue("[EffectRack1_EffectUnit2]",
"group_" + group + "_enable", 0);
engine.trigger("[EffectRack1_EffectUnit1]", `group_${ group }_enable`);
engine.trigger("[EffectRack1_EffectUnit2]", `group_${ group }_enable`);
channelPlaying[group] = !!engine.getValue(group, "play");
JogBlinking[group] = false;
}

// Samplers controls
for (let i = 1; i <= 8; i++) {
group = "[Sampler" + i + "]";
engine.connectControl(group, "track_samples",
"ReloopBeatmix24.deckLoaded");
engine.connectControl(group, "play",
"ReloopBeatmix24.SamplerPlay");
engine.makeConnection(group, "track_loaded",
ReloopBeatmix24.deckLoaded);
engine.trigger(group, "track_loaded");
engine.makeConnection(group, "play",
ReloopBeatmix24.SamplerPlay);
engine.trigger(group, "play");
}

// Effects reset
Expand All @@ -195,23 +204,29 @@ ReloopBeatmix24.init = function(id, _debug) {
if (engine.getValue("[App]", "num_samplers") < 8) {
engine.setValue("[App]", "num_samplers", 8);
}
ReloopBeatmix24.connectControls(false);
ReloopBeatmix24.connectControls();

for (let i = 1; i <= 4; i++) {
engine.trigger("[Channel" + i + "]", "loop_end_position");
}

// After midi controller receive this Outbound Message request SysEx Message,
// midi controller will send the status of every item on the
// control surface. (Mixxx will be initialized with current values)
midi.sendSysexMsg(ControllerStatusSysex, ControllerStatusSysex.length);
// Delay controller status request to give time to the controller to be ready
engine.beginTimer(1500,
() => {
console.log(`Reloop Beatmix: ${ id } Requesting Controller Status`);

print("Reloop Beatmix: " + id + " initialized.");
// After midi controller receive this Outbound Message request SysEx Message,
// midi controller will send the status of every item on the
// control surface. (Mixxx will be initialized with current values)
midi.sendSysexMsg(ControllerStatusSysex, ControllerStatusSysex.length);

}, true);
console.log(`Reloop Beatmix: ${ id } initialized.`);
};

ReloopBeatmix24.shutdown = function() {
ReloopBeatmix24.TurnLEDsOff(); // Turn off all LEDs
print("Reloop Beatmix: " + ReloopBeatmix24.id + " shut down.");
console.log(`Reloop Beatmix: ${ ReloopBeatmix24.id } shut down.`);
};

// Button functions.
Expand Down Expand Up @@ -350,7 +365,7 @@ ReloopBeatmix24.LoadButton = function(channel, control, value, status, group) {
// ========================================================
ReloopBeatmix24.SamplerPad = function(channel, control, value, status, group) {
if (value === DOWN) {
if (engine.getValue(group, "track_samples")) { //Sampler loaded (playing or not)
if (engine.getValue(group, "track_loaded")) { //Sampler loaded (playing or not)
engine.setValue(group, "cue_gotoandplay", 1);
} else {
engine.setValue(group, "LoadSelectedTrack", 1);
Expand All @@ -361,7 +376,7 @@ ReloopBeatmix24.SamplerPad = function(channel, control, value, status, group) {
ReloopBeatmix24.ShiftSamplerPad = function(channel, control, value, status,
group) {
if (value === DOWN) {
if (engine.getValue(group, "track_samples")) { //Sampler loaded (playing or not)
if (engine.getValue(group, "track_loaded")) { //Sampler loaded (playing or not)
if (engine.getValue(group, "play")) { // Sampler is playing
engine.setValue(group, "cue_gotoandstop", 1);
} else {
Expand All @@ -371,7 +386,7 @@ ReloopBeatmix24.ShiftSamplerPad = function(channel, control, value, status,
engine.setValue(group, "LoadSelectedTrack", 1);
}
} else { // UP
if (!engine.getValue(group, "track_samples")) { // if empty
if (!engine.getValue(group, "track_loaded")) { // if empty
// Set eject back to 0 to turn off the eject button on screen
engine.setValue(group, "eject", 0);
}
Expand Down Expand Up @@ -426,7 +441,7 @@ ReloopBeatmix24.deckLoaded = function(value, group, _control) {
{
const channelChan = parseInt(channelRegEx.exec(group)[1]);
if (channelChan <= 4) {
// shut down load button
// shut down load button
midi.sendShortMsg(0x90 + channelChan, 0x50,
value ? ON : OFF);

Expand Down Expand Up @@ -473,7 +488,7 @@ ReloopBeatmix24.SamplerPlay = function(value, group, _control) {
if (value) {
ledColor = VIOLET;
} else {
ledColor = engine.getValue(group, "track_samples") ? RED : OFF;
ledColor = engine.getValue(group, "track_loaded") ? RED : OFF;
}

// We need to switch off pad lights before changing color otherwise
Expand Down Expand Up @@ -528,6 +543,9 @@ ReloopBeatmix24.ChannelPlay = function(value, group, _control) {
// so value here represent the position in the track in the range [-0.14..1.14]
// (0 = beginning, 1 = end)
ReloopBeatmix24.JogLed = function(value, group, _control) {
if (engine.getValue(group, "track_loaded") === 0) {
return;
}
// time computation
const trackDuration = engine.getValue(group, "duration");
const timeLeft = trackDuration * (1.0 - value);
Expand Down
6 changes: 5 additions & 1 deletion src/analyzer/analyzerebur128.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ void AnalyzerEbur128::storeResults(TrackPointer pTrack) {
qWarning() << "AnalyzerEbur128::storeResults() failed with" << e;
return;
}
if (averageLufs == -HUGE_VAL || averageLufs == 0.0) {
if (averageLufs == -HUGE_VAL ||
averageLufs == HUGE_VAL ||
// This catches 0 and abnormal values inf and -inf (that may have
// slipped through in libebur for some reason.
util_isnormal(averageLufs)) {
qWarning() << "AnalyzerEbur128::storeResults() averageLufs invalid:"
<< averageLufs;
return;
Expand Down
6 changes: 6 additions & 0 deletions src/controllers/midi/portmidienumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ bool namesMatchAllowableEdgeCases(const QString& input_name,
if (input_name == "MIDIIN2 (Ableton Push)" && output_name == "MIDIOUT2 (Ableton Push)") {
return true;
}

// Novation Launchpad X (macOS)
if (input_name == "Launchpad X LPX DAW Out" && output_name == "Launchpad X LPX DAW In") {
return true;
}

return false;
}

Expand Down
1 change: 1 addition & 0 deletions src/library/autodj/autodjfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "library/autodj/autodjprocessor.h"
#include "library/autodj/dlgautodj.h"
#include "library/dao/trackschema.h"
#include "library/library.h"
#include "library/parser.h"
#include "library/trackcollection.h"
Expand Down
1 change: 1 addition & 0 deletions src/library/banshee/bansheeplaylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "library/banshee/bansheedbconnection.h"
#include "library/dao/playlistdao.h"
#include "library/dao/trackschema.h"
#include "library/queryutil.h"
#include "library/trackcollectionmanager.h"
#include "mixer/playermanager.h"
Expand Down
2 changes: 1 addition & 1 deletion src/library/baseexternalplaylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void BaseExternalPlaylistModel::setPlaylistById(int playlistId) {
// The ordering of columns is relevant (see below)!
auto playlistViewColumns = QStringList{
QStringLiteral("track_id"),
QStringLiteral("position"),
PLAYLISTTRACKSTABLE_POSITION,
QStringLiteral("'' AS ") + LIBRARYTABLE_PREVIEW};
const auto queryString =
QStringLiteral(
Expand Down
53 changes: 38 additions & 15 deletions src/library/basesqltablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,18 @@ void BaseSqlTableModel::clearRows() {
beginRemoveRows(QModelIndex(), 0, m_rowInfo.size() - 1);
m_rowInfo.clear();
m_trackIdToRows.clear();
m_trackPosToRow.clear();
endRemoveRows();
}
DEBUG_ASSERT(m_rowInfo.isEmpty());
DEBUG_ASSERT(m_trackIdToRows.isEmpty());
DEBUG_ASSERT(m_trackPosToRow.isEmpty());
}

void BaseSqlTableModel::replaceRows(
QVector<RowInfo>&& rows,
TrackId2Rows&& trackIdToRows) {
TrackId2Rows&& trackIdToRows,
TrackPos2Row&& trackPosToRows) {
// NOTE(uklotzde): Use r-value references for parameters here, because
// conceptually those parameters should replace the corresponding internal
// member variables. Currently Qt4/5 doesn't support move semantics and
Expand All @@ -182,12 +185,16 @@ void BaseSqlTableModel::replaceRows(
// its container types in the future this code becomes even more efficient.
DEBUG_ASSERT(rows.empty() == trackIdToRows.empty());
DEBUG_ASSERT(rows.size() >= trackIdToRows.size());
if (hasPositionColumn()) {
DEBUG_ASSERT(rows.size() == trackPosToRows.size());
}
if (rows.isEmpty()) {
clearRows();
} else {
beginInsertRows(QModelIndex(), 0, rows.size() - 1);
m_rowInfo = rows;
m_trackIdToRows = trackIdToRows;
m_trackPosToRow = trackPosToRows;
endInsertRows();
}
}
Expand Down Expand Up @@ -246,18 +253,23 @@ void BaseSqlTableModel::select() {
QVector<RowInfo> rowInfos;
QSet<TrackId> trackIds;
int idColumn = -1;
int posColumn = -1;
while (query.next()) {
QSqlRecord sqlRecord = query.record();

if (idColumn < 0) {
idColumn = sqlRecord.indexOf(m_idColumn);
}

if (posColumn == -1 && hasPositionColumn()) {
posColumn = sqlRecord.indexOf(PLAYLISTTABLE_POSITION);
}

// TODO(XXX): Can we get rid of the hard-coded assumption that
// the the first column always contains the id?
DEBUG_ASSERT(idColumn == kIdColumn);

VERIFY_OR_DEBUG_ASSERT(idColumn >= 0) {
VERIFY_OR_DEBUG_ASSERT(idColumn != -1) {
qCritical()
<< "ID column not available in database query results:"
<< m_idColumn;
Expand All @@ -269,11 +281,11 @@ void BaseSqlTableModel::select() {

RowInfo rowInfo;
rowInfo.trackId = trackId;
// current position defines the ordering
rowInfo.order = rowInfos.size();
rowInfo.metadata.reserve(sqlRecord.count());
rowInfo.row = rowInfos.size();

rowInfo.columnValues.reserve(sqlRecord.count());
for (int i = 0; i < m_tableColumns.size(); ++i) {
rowInfo.metadata.push_back(sqlRecord.value(i));
rowInfo.columnValues.push_back(sqlRecord.value(i));
}
rowInfos.push_back(rowInfo);
}
Expand All @@ -298,9 +310,9 @@ void BaseSqlTableModel::select() {
// separate removed tracks (order == -1) from present tracks (order ==
// 0). Otherwise we sort by the order that filterAndSort returned to us.
if (m_trackSourceOrderBy.isEmpty()) {
rowInfo.order = m_trackSortOrder.contains(rowInfo.trackId) ? 0 : -1;
rowInfo.row = m_trackSortOrder.contains(rowInfo.trackId) ? 0 : -1;
} else {
rowInfo.order = m_trackSortOrder.value(rowInfo.trackId, -1);
rowInfo.row = m_trackSortOrder.value(rowInfo.trackId, -1);
}
}
}
Expand All @@ -317,8 +329,7 @@ void BaseSqlTableModel::select() {
trackIdToRows.reserve(rowInfos.size());
for (int i = 0; i < rowInfos.size(); ++i) {
const RowInfo& rowInfo = rowInfos[i];

if (rowInfo.order == -1) {
if (rowInfo.row == -1) {
// We've reached the end of valid rows. Resize rowInfo to cut off
// this and all further elements.
rowInfos.resize(i);
Expand All @@ -330,10 +341,22 @@ void BaseSqlTableModel::select() {
// number of total rows returned by the query
DEBUG_ASSERT(trackIdToRows.size() <= rowInfos.size());

TrackPos2Row trackPosToRows;
if (hasPositionColumn()) {
// We expect as many positions as we have rows
trackPosToRows.reserve(rowInfos.size());
for (int i = 0; i < rowInfos.size(); ++i) {
const RowInfo& rowInfo = rowInfos[i];
trackPosToRows.insert(rowInfo.getPosition(posColumn), i);
}
DEBUG_ASSERT(trackPosToRows.size() == rowInfos.size());
}

// We're done! Issue the update signals and replace the main maps.
replaceRows(
std::move(rowInfos),
std::move(trackIdToRows));
std::move(trackIdToRows),
std::move(trackPosToRows));
// Both rowInfo and trackIdToRows (might) have been moved and
// must not be used afterwards!

Expand Down Expand Up @@ -651,13 +674,13 @@ QVariant BaseSqlTableModel::rawValue(
return previewDeckTrackId() == trackId;
}

const QVector<QVariant>& columns = rowInfo.metadata;
const QVector<QVariant>& columnValues = rowInfo.columnValues;
if (sDebug) {
qDebug() << "Returning table-column value"
<< columns.at(column)
<< "for column" << column;
<< columnValues.at(column)
<< "for column" << column;
}
return columns[column];
return columnValues[column];
}

// Otherwise, return the information from the track record cache for the
Expand Down
Loading

0 comments on commit 5bf07b5

Please sign in to comment.