diff --git a/.eslintrc.json b/.eslintrc.json index 7d2927c69ba..5b871fcb9b9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -84,6 +84,7 @@ "object-curly-spacing": "warn", "prefer-const": "warn", "prefer-regex-literals": "warn", + "prefer-template": "warn", "quotes": [ "warn", "double" ], "require-atomic-updates": "error", "semi": "warn", diff --git a/cmake/modules/FindTagLib.cmake b/cmake/modules/FindTagLib.cmake index 63aa6d8c25e..7e907f6794b 100644 --- a/cmake/modules/FindTagLib.cmake +++ b/cmake/modules/FindTagLib.cmake @@ -48,8 +48,8 @@ include(IsStaticLibrary) find_package(PkgConfig QUIET) if(PkgConfig_FOUND) if(UNIX AND NOT APPLE) - # priorize the taglib1 package introduced in https://aur.archlinux.org/packages/taglib1 - set(ENV{PKG_CONFIG_PATH} "/usr/lib/taglib1/lib/pkgconfig/:$ENV{PKG_CONFIG_PATH}") + # priorize the taglib1 package introduced in https://www.archlinux.de/packages/extra/x86_64/taglib1 + set(ENV{PKG_CONFIG_PATH} "/usr/lib/taglib1/pkgconfig/:$ENV{PKG_CONFIG_PATH}") endif() pkg_check_modules(PC_TagLib QUIET taglib) endif() diff --git a/res/controllers/Pioneer-DDJ-FLX4-script.js b/res/controllers/Pioneer-DDJ-FLX4-script.js index 3514f52421e..3c1db2b4c97 100644 --- a/res/controllers/Pioneer-DDJ-FLX4-script.js +++ b/res/controllers/Pioneer-DDJ-FLX4-script.js @@ -276,6 +276,18 @@ PioneerDDJFLX4.init = function() { PioneerDDJFLX4.sendKeepAlive(); // the query seems to double as a keep alive message }; +// +// Waveform zoom +// + +PioneerDDJFLX4.waveformZoom = function(midichan, control, value, status, group) { + if (value === 0x7f) { + script.triggerControl(group, "waveform_zoom_up", 100); + } else { + script.triggerControl(group, "waveform_zoom_down", 100); + } +}; + // // Channel level lights // diff --git a/res/controllers/Pioneer-DDJ-FLX4.midi.xml b/res/controllers/Pioneer-DDJ-FLX4.midi.xml index 1e99c3d0cbd..12875bbd5a4 100644 --- a/res/controllers/Pioneer-DDJ-FLX4.midi.xml +++ b/res/controllers/Pioneer-DDJ-FLX4.midi.xml @@ -25,6 +25,16 @@ + + BROWSE +SHIFT - Zoom waveform + [Channel1] + PioneerDDJFLX4.waveformZoom + 0xB6 + 0x64 + + + + BROWSE - press - Move cursor between track list and tree view [Library] diff --git a/res/controllers/Traktor-Kontrol-F1-scripts.js b/res/controllers/Traktor-Kontrol-F1-scripts.js index c02d2ca2172..7c004cf3b4d 100644 --- a/res/controllers/Traktor-Kontrol-F1-scripts.js +++ b/res/controllers/Traktor-Kontrol-F1-scripts.js @@ -75,94 +75,94 @@ function KontrolF1Controller() { this.registerOutputPackets = function() { var packet = new HIDPacket("lights", 0x80); // Right 7-segment element - 0x0 off, 0x40 on - packet.addControl("hid", "right_segment_dp", 0,"B"); - packet.addControl("hid", "right_segment_1", 1,"B"); - packet.addControl("hid", "right_segment_2", 2,"B"); - packet.addControl("hid", "right_segment_3", 3,"B"); - packet.addControl("hid", "right_segment_4", 4,"B"); - packet.addControl("hid", "right_segment_5", 5,"B"); - packet.addControl("hid", "right_segment_6", 6,"B"); - packet.addControl("hid", "right_segment_7", 7,"B"); + packet.addOutput("hid", "right_segment_dp", 1, "B"); + packet.addOutput("hid", "right_segment_1", 2, "B"); + packet.addOutput("hid", "right_segment_2", 3, "B"); + packet.addOutput("hid", "right_segment_3", 4, "B"); + packet.addOutput("hid", "right_segment_4", 5, "B"); + packet.addOutput("hid", "right_segment_5", 6, "B"); + packet.addOutput("hid", "right_segment_6", 7, "B"); + packet.addOutput("hid", "right_segment_7", 8, "B"); // Left 7-segment element - 0x0 off, 0x40 on - packet.addControl("hid", "left_segment_dp", 8,"B"); - packet.addControl("hid", "left_segment_1", 9,"B"); - packet.addControl("hid", "left_segment_2", 10,"B"); - packet.addControl("hid", "left_segment_3", 11,"B"); - packet.addControl("hid", "left_segment_4", 12,"B"); - packet.addControl("hid", "left_segment_5", 13,"B"); - packet.addControl("hid", "left_segment_6", 14,"B"); - packet.addControl("hid", "left_segment_7", 15,"B"); + packet.addOutput("hid", "left_segment_dp", 9, "B"); + packet.addOutput("hid", "left_segment_1", 10, "B"); + packet.addOutput("hid", "left_segment_2", 11, "B"); + packet.addOutput("hid", "left_segment_3", 12, "B"); + packet.addOutput("hid", "left_segment_4", 13, "B"); + packet.addOutput("hid", "left_segment_5", 14, "B"); + packet.addOutput("hid", "left_segment_6", 15, "B"); + packet.addOutput("hid", "left_segment_7", 16, "B"); // Button led brightness, 0-0xff - packet.addControl("hid", "browse_brightness", 16,"B"); - packet.addControl("hid", "size_brightness", 17,"B"); - packet.addControl("hid", "type_brightness", 18,"B"); - packet.addControl("hid", "reverse_brightness", 19,"B"); - packet.addControl("hid", "shift_brightness", 20,"B"); - packet.addControl("hid", "capture_brightness", 21,"B"); - packet.addControl("hid", "quant_brightness", 22,"B"); - packet.addControl("hid", "sync_brightness", 23,"B"); + packet.addOutput("hid", "browse_brightness", 17, "B"); + packet.addOutput("hid", "size_brightness", 18, "B"); + packet.addOutput("hid", "type_brightness", 19, "B"); + packet.addOutput("hid", "reverse_brightness", 20, "B"); + packet.addOutput("hid", "shift_brightness", 21, "B"); + packet.addOutput("hid", "capture_brightness", 22, "B"); + packet.addOutput("hid", "quant_brightness", 23, "B"); + packet.addOutput("hid", "sync_brightness", 24, "B"); // Pad RGB color button controls, 3 bytes per pad - packet.addControl("hid", "grid_1_blue", 24,"B") - packet.addControl("hid", "grid_1_red", 25,"B") - packet.addControl("hid", "grid_1_green", 26,"B") - packet.addControl("hid", "grid_2_blue", 27,"B") - packet.addControl("hid", "grid_2_red", 28,"B") - packet.addControl("hid", "grid_2_green", 29,"B") - packet.addControl("hid", "grid_3_blue", 30,"B") - packet.addControl("hid", "grid_3_red", 31,"B") - packet.addControl("hid", "grid_3_green", 32,"B") - packet.addControl("hid", "grid_4_blue", 33,"B") - packet.addControl("hid", "grid_4_red", 34,"B") - packet.addControl("hid", "grid_4_green", 35,"B") - packet.addControl("hid", "grid_5_blue", 36,"B") - packet.addControl("hid", "grid_5_red", 37,"B") - packet.addControl("hid", "grid_5_green", 38,"B") - packet.addControl("hid", "grid_6_blue", 39,"B") - packet.addControl("hid", "grid_6_red", 40,"B") - packet.addControl("hid", "grid_6_green", 41,"B") - packet.addControl("hid", "grid_7_blue", 42,"B") - packet.addControl("hid", "grid_7_red", 43,"B") - packet.addControl("hid", "grid_7_green", 44,"B") - packet.addControl("hid", "grid_8_blue", 45,"B") - packet.addControl("hid", "grid_8_red", 46,"B") - packet.addControl("hid", "grid_8_green", 47,"B") - packet.addControl("hid", "grid_9_blue", 48,"B") - packet.addControl("hid", "grid_9_red", 49,"B") - packet.addControl("hid", "grid_9_green", 50,"B") - packet.addControl("hid", "grid_10_blue", 51,"B") - packet.addControl("hid", "grid_10_red", 52,"B") - packet.addControl("hid", "grid_10_green", 53,"B") - packet.addControl("hid", "grid_11_blue", 54,"B") - packet.addControl("hid", "grid_11_red", 55,"B") - packet.addControl("hid", "grid_11_green", 56,"B") - packet.addControl("hid", "grid_12_blue", 57,"B") - packet.addControl("hid", "grid_12_red", 58,"B") - packet.addControl("hid", "grid_12_green", 59,"B") - packet.addControl("hid", "grid_13_blue", 60,"B") - packet.addControl("hid", "grid_13_red", 61,"B") - packet.addControl("hid", "grid_13_green", 62,"B") - packet.addControl("hid", "grid_14_blue", 63,"B") - packet.addControl("hid", "grid_14_red", 64,"B") - packet.addControl("hid", "grid_14_green", 65,"B") - packet.addControl("hid", "grid_15_blue", 66,"B") - packet.addControl("hid", "grid_15_red", 67,"B") - packet.addControl("hid", "grid_15_green", 68,"B") - packet.addControl("hid", "grid_16_blue", 69,"B") - packet.addControl("hid", "grid_16_red", 70,"B") - packet.addControl("hid", "grid_16_green", 71,"B") + packet.addOutput("hid", "grid_1_blue", 25, "B"); + packet.addOutput("hid", "grid_1_red", 26, "B"); + packet.addOutput("hid", "grid_1_green", 27, "B"); + packet.addOutput("hid", "grid_2_blue", 28, "B"); + packet.addOutput("hid", "grid_2_red", 29, "B"); + packet.addOutput("hid", "grid_2_green", 30, "B"); + packet.addOutput("hid", "grid_3_blue", 31, "B"); + packet.addOutput("hid", "grid_3_red", 32, "B"); + packet.addOutput("hid", "grid_3_green", 33, "B"); + packet.addOutput("hid", "grid_4_blue", 34, "B"); + packet.addOutput("hid", "grid_4_red", 35, "B"); + packet.addOutput("hid", "grid_4_green", 36, "B"); + packet.addOutput("hid", "grid_5_blue", 37, "B"); + packet.addOutput("hid", "grid_5_red", 38, "B"); + packet.addOutput("hid", "grid_5_green", 39, "B"); + packet.addOutput("hid", "grid_6_blue", 40, "B"); + packet.addOutput("hid", "grid_6_red", 41, "B"); + packet.addOutput("hid", "grid_6_green", 42, "B"); + packet.addOutput("hid", "grid_7_blue", 43, "B"); + packet.addOutput("hid", "grid_7_red", 44, "B"); + packet.addOutput("hid", "grid_7_green", 45, "B"); + packet.addOutput("hid", "grid_8_blue", 46, "B"); + packet.addOutput("hid", "grid_8_red", 47, "B"); + packet.addOutput("hid", "grid_8_green", 48, "B"); + packet.addOutput("hid", "grid_9_blue", 49, "B"); + packet.addOutput("hid", "grid_9_red", 50, "B"); + packet.addOutput("hid", "grid_9_green", 51, "B"); + packet.addOutput("hid", "grid_10_blue", 52, "B"); + packet.addOutput("hid", "grid_10_red", 53, "B"); + packet.addOutput("hid", "grid_10_green", 54, "B"); + packet.addOutput("hid", "grid_11_blue", 55, "B"); + packet.addOutput("hid", "grid_11_red", 56, "B"); + packet.addOutput("hid", "grid_11_green", 57, "B"); + packet.addOutput("hid", "grid_12_blue", 58, "B"); + packet.addOutput("hid", "grid_12_red", 59, "B"); + packet.addOutput("hid", "grid_12_green", 60, "B"); + packet.addOutput("hid", "grid_13_blue", 61, "B"); + packet.addOutput("hid", "grid_13_red", 62, "B"); + packet.addOutput("hid", "grid_13_green", 63, "B"); + packet.addOutput("hid", "grid_14_blue", 64, "B"); + packet.addOutput("hid", "grid_14_red", 65, "B"); + packet.addOutput("hid", "grid_14_green", 66, "B"); + packet.addOutput("hid", "grid_15_blue", 67, "B"); + packet.addOutput("hid", "grid_15_red", 68, "B"); + packet.addOutput("hid", "grid_15_green", 69, "B"); + packet.addOutput("hid", "grid_16_blue", 70, "B"); + packet.addOutput("hid", "grid_16_red", 71, "B"); + packet.addOutput("hid", "grid_16_green", 72, "B"); // Play key brightness control, 0-0xff - packet.addControl("hid", "play_4_1_brightness", 72,"B"); - packet.addControl("hid", "play_4_2_brightness", 73,"B"); - packet.addControl("hid", "play_3_1_brightness", 74,"B"); - packet.addControl("hid", "play_3_2_brightness", 75,"B"); - packet.addControl("hid", "play_2_1_brightness", 76,"B"); - packet.addControl("hid", "play_2_2_brightness", 77,"B"); - packet.addControl("hid", "play_1_1_brightness", 78,"B"); - packet.addControl("hid", "play_1_2_brightness", 79,"B"); + packet.addOutput("hid", "play_4_1_brightness", 73, "B"); + packet.addOutput("hid", "play_4_2_brightness", 74, "B"); + packet.addOutput("hid", "play_3_1_brightness", 75, "B"); + packet.addOutput("hid", "play_3_2_brightness", 76, "B"); + packet.addOutput("hid", "play_2_1_brightness", 77, "B"); + packet.addOutput("hid", "play_2_2_brightness", 78, "B"); + packet.addOutput("hid", "play_1_1_brightness", 79, "B"); + packet.addOutput("hid", "play_1_2_brightness", 80, "B"); this.controller.registerOutputPacket(packet); diff --git a/res/controllers/common-hid-packet-parser.js b/res/controllers/common-hid-packet-parser.js index 2b66d00fade..5547af90050 100644 --- a/res/controllers/common-hid-packet-parser.js +++ b/res/controllers/common-hid-packet-parser.js @@ -696,14 +696,14 @@ class HIDPacket { field.auto_repeat = undefined; field.auto_repeat_interval = undefined; - const packet_max_value = Math.pow(2, this.packSizes[field.pack] * 8); + const packet_max_value = Math.pow(2, this.packSizes[field.pack] * 8) - 1; const signed = this.signedPackFormats.includes(field.pack); if (signed) { - field.min = 0 - (packet_max_value / 2) + 1; - field.max = (packet_max_value / 2) - 1; + field.min = 0 - ((packet_max_value + 1) / 2) + 1; + field.max = ((packet_max_value + 1) / 2) - 1; } else { field.min = 0; - field.max = packet_max_value - 1; + field.max = packet_max_value; } if (bitmask === undefined || bitmask === packet_max_value) { @@ -1679,7 +1679,7 @@ class HIDController { */ processIncomingPacket(packet, delta) { - HIDController.fastForIn(delta, (field_name) => { + HIDController.fastForIn(delta, (function(field_name) { // @ts-ignore ignoredControlChanges should be defined in the users mapping // see EKS-Otus.js for an example if (this.ignoredControlChanges !== undefined && @@ -1697,8 +1697,7 @@ class HIDController { } else { console.warn(`HIDController.processIncomingPacket - Unknown field ${field.name} type ${field.type}`); } - } - ); + }).bind(this)); // Qt < 6.2.4 : .bind(this) needed because of QTBUG-95677 } /** * Get active group for this field diff --git a/src/dialog/dlgdevelopertools.cpp b/src/dialog/dlgdevelopertools.cpp index 4e9af0206cd..6d9c34a3b2f 100644 --- a/src/dialog/dlgdevelopertools.cpp +++ b/src/dialog/dlgdevelopertools.cpp @@ -18,6 +18,7 @@ DlgDeveloperTools::DlgDeveloperTools(QWidget* pParent, controlsTable->hideColumn(ControlModel::CONTROL_COLUMN_TITLE); controlsTable->hideColumn(ControlModel::CONTROL_COLUMN_DESCRIPTION); controlsTable->hideColumn(ControlModel::CONTROL_COLUMN_FILTER); + m_controlProxyModel.sort(0, Qt::AscendingOrder); StatsManager* pManager = StatsManager::instance(); if (pManager) { diff --git a/src/library/trackset/baseplaylistfeature.cpp b/src/library/trackset/baseplaylistfeature.cpp index ac81372e687..0b18a37b1ae 100644 --- a/src/library/trackset/baseplaylistfeature.cpp +++ b/src/library/trackset/baseplaylistfeature.cpp @@ -804,6 +804,16 @@ void BasePlaylistFeature::markTreeItem(TreeItem* pTreeItem) { } } +QString BasePlaylistFeature::createPlaylistLabel(const QString& name, + int count, + int duration) const { + return QStringLiteral("%1 (%2) %3") + .arg(name, + QString::number(count), + mixxx::Duration::formatTime( + duration, mixxx::Duration::Precision::SECONDS)); +} + void BasePlaylistFeature::slotResetSelectedTrack() { slotTrackSelected(TrackId{}); } diff --git a/src/library/trackset/baseplaylistfeature.h b/src/library/trackset/baseplaylistfeature.h index 761f94305be..fbcbf16586a 100644 --- a/src/library/trackset/baseplaylistfeature.h +++ b/src/library/trackset/baseplaylistfeature.h @@ -92,6 +92,8 @@ class BasePlaylistFeature : public BaseTrackSetFeature { QModelIndex indexFromPlaylistId(int playlistId); bool isChildIndexSelectedInSidebar(const QModelIndex& index); + QString createPlaylistLabel(const QString& name, int count, int duration) const; + PlaylistDAO& m_playlistDao; QModelIndex m_lastClickedIndex; QModelIndex m_lastRightClickedIndex; diff --git a/src/library/trackset/playlistfeature.cpp b/src/library/trackset/playlistfeature.cpp index d76e0923a83..4f00f80f07b 100644 --- a/src/library/trackset/playlistfeature.cpp +++ b/src/library/trackset/playlistfeature.cpp @@ -18,21 +18,6 @@ #include "widget/wlibrarysidebar.h" #include "widget/wtracktableview.h" -namespace { - -QString createPlaylistLabel( - const QString& name, - int count, - int duration) { - return QStringLiteral("%1 (%2) %3") - .arg(name, - QString::number(count), - mixxx::Duration::formatTime( - duration, mixxx::Duration::Precision::SECONDS)); -} - -} // anonymous namespace - PlaylistFeature::PlaylistFeature(Library* pLibrary, UserSettingsPointer pConfig) : BasePlaylistFeature(pLibrary, pConfig, @@ -152,7 +137,7 @@ QList PlaylistFeature::createPlaylistLabels() { " ON PlaylistTracks.playlist_id = Playlists.id " "LEFT JOIN library " " ON PlaylistTracks.track_id = library.id " - " WHERE Playlists.hidden = 0 " + " WHERE Playlists.hidden = 0 " // PlaylistDAO::HiddenType::PLHT_NOT_HIDDEN " GROUP BY Playlists.id"); queryString.append( mixxx::DbConnection::collateLexicographically( diff --git a/src/library/trackset/setlogfeature.cpp b/src/library/trackset/setlogfeature.cpp index 74ca557f2b6..e27527e5923 100644 --- a/src/library/trackset/setlogfeature.cpp +++ b/src/library/trackset/setlogfeature.cpp @@ -226,14 +226,42 @@ void SetlogFeature::onRightClickChild(const QPoint& globalPos, const QModelIndex /// Use a custom model in the history for grouping by year /// @param selectedId row which should be selected QModelIndex SetlogFeature::constructChildModel(int selectedId) { - // qDebug() << "SetlogFeature::constructChildModel() id:" << selectedId; + // qDebug() << "SetlogFeature::constructChildModel() selected:" << selectedId; // Setup the sidebar playlist model - QSqlTableModel playlistTableModel(this, - m_pLibrary->trackCollectionManager()->internalCollection()->database()); - playlistTableModel.setTable("Playlists"); - playlistTableModel.setFilter("hidden=" + QString::number(PlaylistDAO::PLHT_SET_LOG)); - playlistTableModel.setSort( - playlistTableModel.fieldIndex("id"), Qt::DescendingOrder); + QSqlDatabase database = + m_pLibrary->trackCollectionManager()->internalCollection()->database(); + + QString queryString = QStringLiteral( + "CREATE TEMPORARY VIEW IF NOT EXISTS SetlogCountsDurations " + "AS SELECT " + " Playlists.id AS id, " + " Playlists.name AS name, " + " Playlists.date_created AS date_created, " + " LOWER(Playlists.name) AS sort_name, " + " COUNT(case library.mixxx_deleted when 0 then 1 else null end) " + " AS count, " + " SUM(case library.mixxx_deleted " + " when 0 then library.duration else 0 end) AS durationSeconds " + "FROM Playlists " + "LEFT JOIN PlaylistTracks " + " ON PlaylistTracks.playlist_id = Playlists.id " + "LEFT JOIN library " + " ON PlaylistTracks.track_id = library.id " + " WHERE Playlists.hidden = %1 " + " GROUP BY Playlists.id") + .arg(QString::number(PlaylistDAO::HiddenType::PLHT_SET_LOG)); + queryString.append( + mixxx::DbConnection::collateLexicographically( + " ORDER BY sort_name")); + QSqlQuery query(database); + if (!query.exec(queryString)) { + LOG_FAILED_QUERY(query); + } + + // Setup the sidebar playlist model + QSqlTableModel playlistTableModel(this, database); + playlistTableModel.setTable("SetlogCountsDurations"); + playlistTableModel.setSort(playlistTableModel.fieldIndex("id"), Qt::DescendingOrder); playlistTableModel.select(); while (playlistTableModel.canFetchMore()) { playlistTableModel.fetchMore(); @@ -242,6 +270,8 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) { int nameColumn = record.indexOf("name"); int idColumn = record.indexOf("id"); int createdColumn = record.indexOf("date_created"); + int countColumn = record.indexOf("count"); + int durationColumn = record.indexOf("durationSeconds"); // Nice to have: restore previous expanded/collapsed state of YEAR items clearChildModel(); @@ -263,8 +293,16 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) { playlistTableModel .data(playlistTableModel.index(row, createdColumn)) .toDateTime(); + int count = playlistTableModel + .data(playlistTableModel.index(row, countColumn)) + .toInt(); + int duration = + playlistTableModel + .data(playlistTableModel.index(row, durationColumn)) + .toInt(); + QString label = createPlaylistLabel(name, count, duration); - // Create the TreeItem whose parent is the invisible root item + // Create the TreeItem whose parent is the invisible root item. // Show only [kNumToplevelHistoryEntries] recent playlists at the top level // before grouping them by year. if (row >= kNumToplevelHistoryEntries) { @@ -286,12 +324,12 @@ QModelIndex SetlogFeature::constructChildModel(int selectedId) { itemList.push_back(std::move(pNewGroupItem)); } - TreeItem* pItem = pGroupItem->appendChild(name, id); + TreeItem* pItem = pGroupItem->appendChild(label, id); pItem->setBold(m_playlistIdsOfSelectedTrack.contains(id)); decorateChild(pItem, id); } else { // add most recent top-level playlist - auto pItem = std::make_unique(name, id); + auto pItem = std::make_unique(label, id); pItem->setBold(m_playlistIdsOfSelectedTrack.contains(id)); decorateChild(pItem.get(), id);