1 /**
2  * @file parstore.h
3  * @brief Member definitions for the ParStore class.
4  *
5  *
6  *      Copyright 2009 - 2017 <qmidiarp-devel@lists.sourceforge.net>
7  *
8  *      This program is free software; you can redistribute it and/or modify
9  *      it under the terms of the GNU General Public License as published by
10  *      the Free Software Foundation; either version 2 of the License, or
11  *      (at your option) any later version.
12  *
13  *      This program is distributed in the hope that it will be useful,
14  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *      GNU General Public License for more details.
17  *
18  *      You should have received a copy of the GNU General Public License
19  *      along with this program; if not, write to the Free Software
20  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  *      MA 02110-1301, USA.
22  */
23 
24 #ifndef PARSTORE_H
25 #define PARSTORE_H
26 
27 #include <QMenu>
28 #include <QToolButton>
29 
30 #include "globstore.h"
31 #include "midievent.h"
32 
33 
34 /*!
35  * ParStore holds module parameter fields in its ParStore::list. These parameter
36  * fields can be read by the modules, which have a pointer to ParStore. ParStore
37  * also creates storage location GUI handling for each module. Each list entry
38  * is represented by a StorageButton and its associated context menu. GUI elements
39  * are dynamically added to and removed from the GlobStore Widget. ParStore is
40  * midi controllable and it can save all field lists to disk.
41 
42  * @brief Manages a list of module parameter fields and GUI elements
43  */
44 class ParStore : public QWidget
45 {
46   Q_OBJECT
47 
48   public:
49     ParStore(GlobStore *p_globStore, const QString &name = "",
50                 QAction* p_muteOutAction = 0,
51                 QAction* p_deferChangesAction = 0,
52                 QWidget *parent = 0);
53     GlobStore *globStore;
54     QToolButton *topButton;
55     QAction *muteOutAction;
56     QAction *deferChangesAction;
57     QToolButton *muteOut;
58     QToolButton *deferChanges;
59     Indicator *ndc;
60 /*! List of jumpTo configurations for each location
61 *    @see ParStore::updateRunOnce()
62 */
63     QList<int> jumpToList;
64 /*! List of switch configuration for each location
65 *   @see ParStore::updateOnlyPattern()
66 */
67     QList<bool> onlyPatternList;
68     QMenu *locContextMenu;
69     QMenu *jumpToIndexMenu;
70     QActionGroup *jumpToGroup;
71 
72     int activeStore; /**< Currently active location index*/
73     int currentRequest; /**< Currently pending location index*/
74     bool isRestoreMaster; /**< @brief Indicates whether this module triggers global restores */
75 
76     struct TempStore {
77         bool empty;
78         bool muteOut;
79         int res;
80         int size;
81         int loopMode;
82         int waveForm;
83         int portOut;
84         int channelOut;
85         int chIn;
86         QVector<Sample> wave;
87         QVector<bool> muteMask;
88         /* LFO Modules */
89         int ccnumber;
90         int ccnumberIn;
91         int freq;
92         int ampl;
93         int offs;
94         /* Seq Modules */
95         int loopMarker;
96         int notelen;
97         int vel;
98         int transp;
99         int dispVertIndex;
100         /* Arp Modules */
101         int indexIn0;
102         int indexIn1;
103         int rangeIn0;
104         int rangeIn1;
105         int attack;
106         int release;
107         int repeatMode;
108         int rndTick;
109         int rndLen;
110         int rndVel;
111         QString pattern;
112     };
113     TempStore temp; /**< Structure to which all module parameters are copied
114                         * before being appended to the ParStore::list*/
115     QList<TempStore> list; /**< List of TempStore structures for
116                         parameter storage*/
117 
118 /*! When this variable is greater than -1, ParStore::updateDisplay() will cause
119 * ParStore::restoreParams(restoreRequest) at pattern end
120 */
121     int restoreRequest;
122     int oldRestoreRequest; /**< Contains the last active location for jumping back*/
123 /*!
124 * Signals to ParStore::updateDisplay() that only one
125 * run is done and then a restore is required.
126 */
127     bool restoreRunOnce;
128 /*! Signals to ParStore::updateDisplay() that the location
129 * button color has to be updated.
130 */
131     bool needsGUIUpdate;
132 /*! When ParStore::needsGUIUpdate is true, ParStore::updateDisplay()
133 * sets colors to these values
134 */
135     int dispReqIx, dispReqSelected;
136 
137 /*!
138 * @brief stores all module parameters to ParStore::temp and stores temp
139 * in ParStore::list at index ix. If the given index is greater than the list size,
140 * temp is appended to ParStore::list.
141 *
142 * @param ix Index at which the parameters are stored.
143 */
144     void tempToList(int ix);
145 /*!
146 * @brief reads the ParStore::list from an XML stream
147 * passed by the caller, i.e. MainWindow.
148 *
149 * @param xml QXmlStreamWriter to read from
150 */
151     void readData(QXmlStreamReader& xml);
152 /*!
153 * @brief writes the ParStore::list to an XML stream
154 * passed by the caller, i.e. MainWindow.
155 *
156 * @param xml QXmlStreamWriter to write to
157 */
158     void writeData(QXmlStreamWriter& xml);
159 
160 /*!
161 * @brief sets ParStore::restoreRequest and ParStore::restoreRunOnce to the
162 * location specified
163 *
164 * This will cause ParStore::updateDisplay() to do the parameter restore on
165 * its next call
166 *
167 * @param ix Location index to be restored at pattern end
168 */
169     void setRestoreRequest(int ix);
170 /*!
171 * @brief sets the color of location button row to the specified color index
172 *
173 * @param row Location index at which button color is to be set
174 * @param color Location color (0: no color, 1: active color, 2: pending color)
175 */
176     void setBGColorAt(int row, int color);
177 /*!
178 * @brief is called by the parent widget and part of the display timer event loop.
179 
180 * sets the indicator position and handles storage requests as a function of the
181 * GUI requests and series parameters
182 *
183 * @param frame Current frame position of the parent module
184 * @param reverse Set to true if the parent module currently plays backward
185 */
186     void updateDisplay(int frame, bool reverse);
187 
188 #ifdef APPBUILD
189 /*!
190 * @brief allows ignoring one XML element in the XML stream
191 * passed by the caller.
192 *
193 * It also advances the stream read-in. It is used to
194 * ignore unknown elements for both-ways-compatibility
195 *
196 * @param xml reference to QXmlStreamReader containing the open XML stream
197 */
198 void skipXmlElement(QXmlStreamReader& xml);
199 #endif
200 
201   signals:
202 /*!
203 * @brief is connected to the parent widget and should cause it to store
204 * parameters to the location ix
205 *
206 * @param ix Storage location
207 * @param empty True if no parameters are stored and only the template is added
208 */
209     void store(int ix, bool empty);
210 /*!
211 * @brief is connected to the parent widget and should cause immediate
212 * parameter restore from location ix
213 *
214 * @param ix Storage location
215 */
216     void restore(int ix);
217 
218   public slots:
219 
220 /*!
221 * @brief a signal mapper for routing the ParStore::jumpToIndexMenu signals
222 * to the ParStore::updateRunOnce() slot
223 *
224 * @param *action Pointer to the action that has been activated in the menu
225 */
226     void mapJumpToGroup(QAction *action);
227 /*!
228 * @brief called by ParStore::mapJumpToGroup(). Configures the location
229 * behavior at pattern end
230 *
231 * The choices are -2 for "Stay here" (no jumps at pattern end), -1 for
232 * returning to the previous location (ParStore::oldRestoreRequest) or (if
233 * zero or above) the location to jump to at pattern end. The choice value is
234 * copied to ParStore::jumpToList()
235 *
236 * @param location Location to be configured
237 * @param choice -2 (no jumps), -1 (return to previous),
238 * >=0 (next location to jump to)
239 */
240     void updateRunOnce(int location, int choice);
241 /*!
242 * @brief adds all storage location GUI elements to the widget
243 *
244 * It also adds a new element to the ParStore::jumpToList
245 */
246     void addLocation();
247 /*!
248 * @brief removes and deletes all storage location GUI elements
249 *
250 * It also removes the parameter storage structure from ParStore::list and
251 * the element from ParStore::jumpToList
252 *
253 * @param ix Location index to be removed
254 */
255     void removeLocation(int ix);
256 /*!
257 * @brief slot for each location's global restore button
258 *
259 * Sets the location index to restore from the caller widget "index" property and
260 * calls ParStore::setRestoreRequest() with that location.
261 */
262     void mapRestoreSignal();
263 /*!
264 * @brief slot for each location's global store button
265 *
266 * Sets the location index to restore from the caller widget "index" property and
267 * emits the ParStore::store() signal to the parent module widget.
268 */
269     void mapStoreSignal();
270 /*!
271 * @brief handles the ParStore button colors as a function
272 * of selection state.
273 *
274 * It attributes blueish color to all buttons at index ix if selected is 2
275 * and green color if selected is 1. It will remove color attributes from
276 * the remaining buttons.
277 *
278 * @param ix Storage index of the storage button to act on
279 * @param selected Color state to attribute to the button, 1 = green, 2 = blueish
280 */
281     void setDispState(int ix, int selected);
282 /*!
283 * @brief will cause a flag to be set, which causes ParStore::updateDisplay()
284 *  to call ParStore::setDispState() at the next occasion.
285 *
286 * This function is used by ParStore::handleController(), since setDispState()
287 * cannot be called directly from the realtime thread which sends the controller.
288 *
289 * @param ix Storage index of the storage button to act on
290 * @param selected Color state to attribute to the button, 1 = green, 2 = blueish
291 */
292     void requestDispState(int ix, int selected);
293 /*!
294 * @brief configures and shows the context menu for individual storage locations
295 *
296 * This is the slot for context menu call of each individual storage button.
297 * As part of the context menu, the ParStore::jumpToGroup QAction group is
298 * configured with the ParStore::jumpToList state of that location at each
299 * time this function is called.
300 *
301 * @param &pos mouse position transferred by the caller widget in widget
302 * coordinates
303 */
304     void showLocContextMenu(const QPoint &pos);
305     void updateOnlyPattern(bool on);
306 };
307 #endif
308