Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 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 : #ifndef MUSE_GLOBAL_PROGRESS_H
23 : #define MUSE_GLOBAL_PROGRESS_H
24 :
25 : #include <memory>
26 : #include <atomic>
27 :
28 : #include "async/channel.h"
29 : #include "async/notification.h"
30 :
31 : #include "types/retval.h"
32 : #include "types/val.h"
33 :
34 : namespace muse {
35 : using ProgressResult = RetVal<Val>;
36 :
37 : class Progress
38 : {
39 : struct Data {
40 : async::Notification started;
41 : async::Channel<ProgressResult> finished;
42 : async::Notification canceled;
43 : std::atomic<bool> isStarted = false;
44 : std::atomic<bool> isCanceled = false;
45 : std::atomic<int64_t> prevCurrent = -1;
46 : std::atomic<int64_t> prevTotal = -1;
47 : std::atomic<int64_t> maxNumIncrements = 0;
48 :
49 : async::Channel<int64_t /*current*/, int64_t /*total*/, std::string /*title*/> progressChanged;
50 : };
51 :
52 : public:
53 :
54 785 : Progress()
55 785 : : m_data(std::make_shared<Data>()) {}
56 :
57 862 : Progress(const Progress& p)
58 862 : : m_data(p.m_data) {}
59 :
60 1617 : ~Progress() {}
61 :
62 253 : Progress& operator=(const Progress& p)
63 : {
64 253 : m_data = p.m_data;
65 253 : return *this;
66 : }
67 :
68 : // start
69 119 : void start()
70 : {
71 119 : m_data->isCanceled = false;
72 119 : m_data->isStarted = true;
73 119 : m_data->prevCurrent = -1;
74 119 : m_data->prevTotal = -1;
75 119 : m_data->started.notify();
76 119 : }
77 :
78 0 : async::Notification& started() { return m_data->started; }
79 14 : bool isStarted() const { return m_data->isStarted; }
80 :
81 1 : void setMaxNumIncrements(int64_t maxNumIncrements) { m_data->maxNumIncrements = maxNumIncrements; }
82 :
83 : // progress
84 143 : bool progress(int64_t current, int64_t total, const std::string& msg = {})
85 : {
86 143 : const int64_t maxNumIncrements = m_data->maxNumIncrements;
87 143 : if (maxNumIncrements > 0 && total > maxNumIncrements) {
88 100 : current *= static_cast<double>(maxNumIncrements) / total;
89 100 : total = maxNumIncrements;
90 : }
91 :
92 143 : if (current == m_data->prevCurrent && total == m_data->prevTotal) {
93 92 : return false;
94 : }
95 :
96 51 : m_data->prevCurrent = current;
97 51 : m_data->prevTotal = total;
98 51 : m_data->progressChanged.send(current, total, msg);
99 :
100 51 : return true;
101 : }
102 :
103 124 : async::Channel<int64_t /*current*/, int64_t /*total*/, std::string /*title*/>& progressChanged()
104 : {
105 124 : return m_data->progressChanged;
106 : }
107 :
108 307 : void finish(const ProgressResult& res)
109 : {
110 307 : m_data->prevCurrent = -1;
111 307 : m_data->prevTotal = -1;
112 307 : m_data->isStarted = false;
113 307 : m_data->finished.send(res);
114 307 : }
115 :
116 291 : async::Channel<ProgressResult>& finished() { return m_data->finished; }
117 :
118 9 : void cancel()
119 : {
120 9 : m_data->isCanceled = true;
121 9 : m_data->canceled.notify();
122 9 : finish(make_ret(Ret::Code::Cancel));
123 9 : }
124 :
125 53 : async::Notification& canceled() { return m_data->canceled; }
126 47 : bool isCanceled() const { return m_data->isCanceled; }
127 :
128 : private:
129 :
130 : std::shared_ptr<Data> m_data = nullptr;
131 : };
132 :
133 : using ProgressPtr = std::shared_ptr<Progress>;
134 : }
135 :
136 : #ifndef NO_QT_SUPPORT
137 0 : Q_DECLARE_METATYPE(muse::Progress)
138 : #endif
139 :
140 : #endif // MUSE_GLOBAL_PROGRESS_H
|