Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2025 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <QAbstractListModel>
26 : #include <QTransform>
27 : #include <qqmlintegration.h>
28 :
29 : #include "async/asyncable.h"
30 : #include "modularity/ioc.h"
31 :
32 : #include "project/iprojectsession.h"
33 : #include "audio/main/iplayback.h"
34 : #include "iplaybackcontroller.h"
35 : #include "iplaybackconfiguration.h"
36 : #include "notation/inotationconfiguration.h"
37 :
38 : namespace mu::playback {
39 : class NotationRegionsBeingProcessedModel : public QAbstractListModel, public muse::async::Asyncable, public muse::Contextable
40 : {
41 : Q_OBJECT
42 :
43 : Q_PROPERTY(QVariant notationViewMatrix READ notationViewMatrix WRITE setNotationViewMatrix NOTIFY notationViewMatrixChanged)
44 :
45 : Q_PROPERTY(bool isEmpty READ isEmpty NOTIFY isEmptyChanged)
46 :
47 : Q_PROPERTY(QColor progressBackgroundColor READ progressBackgroundColor CONSTANT)
48 : Q_PROPERTY(QColor progressTextColor READ progressTextColor CONSTANT)
49 :
50 : QML_ELEMENT
51 :
52 : muse::GlobalInject<IPlaybackConfiguration> configuration;
53 : muse::GlobalInject<notation::INotationConfiguration> notationConfiguration;
54 : muse::ContextInject<muse::audio::IPlayback> playback = { this };
55 : muse::ContextInject<mu::project::IProjectSession> projectSession = { this };
56 : muse::ContextInject<IPlaybackController> playbackController = { this };
57 :
58 : public:
59 : explicit NotationRegionsBeingProcessedModel(QObject* parent = nullptr);
60 :
61 : QVariant data(const QModelIndex& index, int role) const override;
62 : int rowCount(const QModelIndex& parent = QModelIndex()) const override;
63 : QHash<int, QByteArray> roleNames() const override;
64 :
65 : Q_INVOKABLE void load();
66 :
67 : QVariant notationViewMatrix() const;
68 :
69 : bool isEmpty() const;
70 :
71 : QColor progressBackgroundColor() const;
72 : QColor progressTextColor() const;
73 :
74 : public slots:
75 : void setNotationViewMatrix(const QVariant& matrix);
76 :
77 : signals:
78 : void notationViewMatrixChanged();
79 :
80 : void isEmptyChanged();
81 :
82 : private:
83 : enum Roles {
84 : RectRole = Qt::UserRole + 1,
85 : ProgressRole,
86 : };
87 :
88 : struct RegionInfo {
89 : mu::engraving::InstrumentTrackId trackId;
90 : QRectF logicRect;
91 : QRectF viewRect;
92 :
93 0 : bool operator==(const RegionInfo& r) const
94 : {
95 0 : return trackId == r.trackId && logicRect == r.logicRect && viewRect == r.viewRect;
96 : }
97 : };
98 :
99 : struct TickRange {
100 : int tickFrom = -1;
101 : int tickTo = -1;
102 :
103 0 : bool operator==(const TickRange& r) const
104 : {
105 0 : return tickFrom == r.tickFrom && tickTo == r.tickTo;
106 : }
107 : };
108 :
109 : struct TrackInfo {
110 : std::vector<TickRange> ranges;
111 : int progress = 0; // 0 - 100%
112 :
113 : bool operator==(const TrackInfo& t) const
114 : {
115 : return ranges == t.ranges && progress == t.progress;
116 : }
117 : };
118 :
119 : using TracksBeingProcessed = std::unordered_map<mu::engraving::InstrumentTrackId, TrackInfo>;
120 : using ChunkInfoList = muse::audio::InputProcessingProgress::ChunkInfoList;
121 :
122 : bool isPlaying() const;
123 :
124 : void clear();
125 : void setRegions(const QList<RegionInfo>& regions);
126 :
127 : void onOnlineSoundsChanged();
128 : void onIsPlayingChanged();
129 :
130 : void listenViewModeChanges();
131 :
132 : void startListeningToProgress(const muse::audio::TrackId trackId);
133 : void stopListeningToProgress(const muse::audio::TrackId trackId);
134 :
135 : void onProgressStarted(const mu::engraving::InstrumentTrackId& instrumentTrackId);
136 : void onChunksReceived(const mu::engraving::InstrumentTrackId& instrumentTrackId, const ChunkInfoList& chunks);
137 : void onProgressChanged(const mu::engraving::InstrumentTrackId& instrumentTrackId, int progress);
138 : void onProgressFinished(const mu::engraving::InstrumentTrackId& instrumentTrackId);
139 : void onViewMatrixChanged();
140 :
141 : void initShouldShowRegions();
142 :
143 : QList<RegionInfo> calculateRegions(const TracksBeingProcessed& tracks) const;
144 : std::vector<QRectF> calculateRects(const mu::engraving::Part* part, const std::vector<TickRange>& ranges) const;
145 : std::vector<QRectF> calculateRects(const mu::engraving::Part* part, const mu::engraving::System* system,
146 : const std::vector<TickRange>& ranges) const;
147 :
148 : QTransform m_notationViewMatrix;
149 : std::map<muse::audio::TrackId, muse::audio::AudioResourceMeta> m_onlineSounds;
150 : TracksBeingProcessed m_tracksBeingProcessed;
151 : QList<RegionInfo> m_regions; // main model
152 : bool m_shouldShowRegions = true;
153 : };
154 : }
|