1 /*-
2  * Copyright (c) 2009-2021 Hans Petter Selasky. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #ifndef _MIDIPP_H_
27 #define	_MIDIPP_H_
28 
29 #include <stdint.h>
30 #include <sys/param.h>
31 
32 #include <err.h>
33 
34 #include <QApplication>
35 #include <QDialog>
36 #include <QPushButton>
37 #include <QGridLayout>
38 #include <QTextEdit>
39 #include <QScrollBar>
40 #include <QPlainTextEdit>
41 #include <QTabBar>
42 #include <QStackedWidget>
43 #include <QLabel>
44 #include <QSpinBox>
45 #include <QTextCursor>
46 #include <QTimer>
47 #include <QKeyEvent>
48 #include <QWheelEvent>
49 #include <QFile>
50 #include <QFileDialog>
51 #include <QLineEdit>
52 #include <QSpacerItem>
53 #include <QLCDNumber>
54 #include <QPicture>
55 #include <QColor>
56 #include <QPaintEvent>
57 #include <QPainter>
58 #include <QFont>
59 #ifdef HAVE_PRINTER
60 #include <QPrintDialog>
61 #include <QPrinter>
62 #endif
63 #include <QFontDialog>
64 #include <QFontInfo>
65 #include <QFileInfo>
66 #include <QMouseEvent>
67 #include <QSizePolicy>
68 #include <QListWidget>
69 #include <QIcon>
70 #include <QCloseEvent>
71 #include <QMenu>
72 #include <QMessageBox>
73 #include <QDir>
74 #include <QGroupBox>
75 #include <QSettings>
76 #include <QStyle>
77 #include <QSlider>
78 #include <QtNetwork>
79 #include <QUrl>
80 #include <QWheelEvent>
81 #include <QColorDialog>
82 #include <QPoint>
83 #include <QSplitter>
84 #include <QThread>
85 #include <QRegExp>
86 #include <QByteArray>
87 #include <QChar>
88 #include <QString>
89 #include <QClipboard>
90 #include <QXmlStreamReader>
91 
92 #include <umidi20.h>
93 
94 #ifdef __APPLE__
95 #include "TargetConditionals.h"
96 #endif
97 
98 #define	MPP_MAX_KEYS (128 * 128 * 128 * 128)	/* maximum number of keys */
99 #define	MPP_MAX_BANDS (12 * 128 * 128 * 128)	/* number of divisions per octave */
100 #define	MPP_MAX_CHORD_BANDS	192
101 #define	MPP_MAX_CHORD_MAP	(3 * 12 + 2)
102 #define	MPP_MAX_CHORD_FUTURE	12
103 #define	MPP_MAX_BUTTON_MAP	16
104 #define	MPP_MAX_VIEWS	2
105 #define	MPP_MAX_TRACKS		(MPP_TRACKS_PER_VIEW * MPP_MAX_VIEWS)
106 #define	MPP_MAX_LINES	8192
107 #define	MPP_MAX_SCORES	32
108 #define	MPP_MAX_LABELS	32
109 #define	MPP_MAX_DEVS	8
110 #define	MPP_MAX_BPM	32
111 #define	MPP_MAX_LBUTTON	16
112 #define	MPP_MIN_POS	4	/* ticks */
113 #define	MPP_WHEEL_STEP	(8 * 15)
114 #define	MPP_PRESSED_MAX	128
115 #define	MPP_MAX_DURATION 255	/* inclusive */
116 #define	MPP_MAGIC_DEVNO	(UMIDI20_N_DEVICES - MPP_MAX_TRACKS)
117 #define	MPP_DEFAULT_URL "http://home.selasky.org/midipp/database.tar.gz"
118 #define	MPP_DEFAULT_HPSJAM "127.0.0.1:12345"
119 #define	MPP_DEFAULT_CMD_KEY C3
120 #define	MPP_DEFAULT_BASE_KEY ((MPP_C0 + 12 * 5) * MPP_BAND_STEP_12)
121 #define	MPP_VISUAL_MARGIN	8
122 #define	MPP_VISUAL_R_MAX	8
123 #define	MPP_VISUAL_C_MAX	20
124 #define	MPP_VOLUME_UNIT		127
125 #define	MPP_VOLUME_MAX		511	/* inclusivly */
126 #define	MPP_CUSTOM_MAX		10
127 #define	MPP_LOOP_MAX		16
128 #define	MPP_MAX_TABS		32
129 #define	MPP_MAX_WIDGETS		32
130 #define	MPP_PIANO_TAB_LABELS	10	/* hard coded */
131 #define	MPP_POPUP_DELAY		2000	/* ms */
132 
133 #define	MPP_CHAN_NONE_MASK	(1 << 1)
134 #define	MPP_CHAN_ANY_MASK	(1 << 2)
135 #define	MPP_CHAN_MPE_MASK	(1 << 3)
136 #define	MPP_CHAN_NONE		-1
137 #define	MPP_CHAN_ANY		-2
138 #define	MPP_CHAN_MPE 		-3	/* multi polyphonic expression */
139 #define	MPP_DEV_ALL		1
140 #define	MPP_DEV_NONE		2
141 
142 /* list of tracks supported */
143 #define	MPP_DEFAULT_TRACK(n) ((n) * MPP_TRACKS_PER_VIEW + 0)
144 #define	MPP_TREBLE_TRACK(n) ((n) * MPP_TRACKS_PER_VIEW + 1)
145 #define	MPP_BASS_TRACK(n) ((n) * MPP_TRACKS_PER_VIEW + 2)
146 
147 #define	MPP_BLOCKED(obj, what) do {		\
148     (obj)->blockSignals(1);			\
149     (obj)->what;				\
150     (obj)->blockSignals(0);			\
151 } while (0)
152 
153 #define	MPP_TRACKS_PER_VIEW 3
154 
155 #if (MPP_MAGIC_DEVNO < MPP_MAX_DEVS)
156 #error "UMIDI20_N_DEVICES is too small."
157 #endif
158 
159 /* list of supported band steps */
160 #define	MPP_BAND_STEP_12 (MPP_MAX_BANDS / 12)
161 #define	MPP_BAND_STEP_24 (MPP_MAX_BANDS / 24)
162 #define	MPP_BAND_STEP_48 (MPP_MAX_BANDS / 48)
163 #define	MPP_BAND_STEP_96 (MPP_MAX_BANDS / 96)
164 #define	MPP_BAND_STEP_192 (MPP_MAX_BANDS / 192)
165 #define	MPP_BAND_STEP_CHORD (MPP_MAX_BANDS / MPP_MAX_CHORD_BANDS)
166 
167 static inline int
MPP_BAND_REM(int x,int y)168 MPP_BAND_REM(int x, int y)
169 {
170 	x = (MPP_MAX_BANDS + (x % MPP_MAX_BANDS)) % MPP_MAX_BANDS;
171 	return (x / (MPP_MAX_BANDS / y));
172 }
173 
174 static inline int
MPP_SUBDIV_REM_BITREV(int x)175 MPP_SUBDIV_REM_BITREV(int x)
176 {
177 	int x_mask = MPP_BAND_STEP_12 / 2;
178 	int r_mask = 1;
179 	int retval = 0;
180 
181 	while (r_mask != MPP_BAND_STEP_12) {
182 		if (x & x_mask)
183 			retval |= r_mask;
184 		r_mask <<= 1;
185 		x_mask >>= 1;
186 	}
187 	return (retval);
188 }
189 
190 static inline int
MPP_BAND_REM_TO_KEY(int x)191 MPP_BAND_REM_TO_KEY(int x)
192 {
193 	int x_mask = 4 * MPP_BAND_STEP_12 / 2;
194 	int r_mask = 1;
195 	int retval = 0;
196 
197 	while (r_mask != (4 * MPP_BAND_STEP_12)) {
198 		if (x & x_mask)
199 			retval |= r_mask;
200 		r_mask <<= 1;
201 		x_mask >>= 1;
202 	}
203 
204 	retval *= 3;
205 
206 	if (x & (4 * MPP_BAND_STEP_12))
207 		retval += 1;
208 	if (x & (8 * MPP_BAND_STEP_12))
209 		retval += 2;
210 
211 	return (retval);
212 }
213 
214 static inline int
MPP_KEY_TO_BAND_REM(int x)215 MPP_KEY_TO_BAND_REM(int x)
216 {
217 	int x_mask = 4 * MPP_BAND_STEP_12 / 2;
218 	int r_mask = 1;
219 	int retval;
220 
221 	retval = (x % 3) * (MPP_MAX_BANDS / 3);
222 
223 	x /= 3;
224 
225 	while (r_mask != (4 * MPP_BAND_STEP_12)) {
226 		if (x & x_mask)
227 			retval += r_mask;
228 		r_mask <<= 1;
229 		x_mask >>= 1;
230 	}
231 	return (retval);
232 }
233 
234 #define	MPP_KEY_MIN (1 << 31)
235 
236 /* list of basic 12-step score values */
237 #define	MPP_C0 0
238 #define	MPP_D0B 1
239 #define	MPP_D0 2
240 #define	MPP_E0B 3
241 #define	MPP_E0 4
242 #define	MPP_F0 5
243 #define	MPP_G0B 6
244 #define	MPP_G0 7
245 #define	MPP_A0B 8
246 #define	MPP_A0 9
247 #define	MPP_H0B 10
248 #define	MPP_H0 11
249 
250 #define	STRLCPY(a,b,c) do { \
251     strncpy(a,b,c); ((char *)(a))[(c)-1] = 0; \
252 } while (0)
253 
254 class MppBpm;
255 class MppButton;
256 class MppButtonMap;
257 class MppChanSel;
258 class MppChanSelDiag;
259 class MppCheckBox;
260 class MppCustomTab;
261 class MppDataBase;
262 class MppDecodeTab;
263 class MppDevices;
264 class MppDevSel;
265 class MppDevSelDiag;
266 class MppElement;
267 class MppGPro;
268 class MppGridLayout;
269 class MppGroupBox;
270 class MppHead;
271 class MppImportTab;
272 class MppInstrumentTab;
273 class MppLoopTab;
274 class MppMainWindow;
275 class MppMidi;
276 class MppMetronome;
277 class MppMode;
278 class MppPianoTab;
279 class MppReplace;
280 class MppReplayTab;
281 class MppScoreHighLighter;
282 class MppScoreMain;
283 class MppScoreView;
284 class MppSettings;
285 class MppSettingsWhat;
286 class MppSheet;
287 class MppShortcutTab;
288 class MppShowControl;
289 class MppShowWidget;
290 class MppSpinBox;
291 class MppTabBar;
292 class MppVolume;
293 
294 struct MppChord;
295 struct MppChordElement;
296 
297 typedef struct MppChord MppChord_t;
298 
299 class QPrinter;
300 
301 struct MppScoreEntry {
302 	int key;
303 	int dur;
304 	int8_t track;
305 	int8_t trackSec;
306 	int8_t channel;
307 	int8_t channelSec;
308 };
309 
310 struct MppInstr {
311 	uint16_t bank;
312 	uint8_t prog;
313 	uint8_t muted;
314 	uint8_t updated;
315 };
316 
317 struct MppVisualDot {
318 	qreal x_off;
319 	qreal y_off;
320 };
321 
322 struct MppVisualScore {
323 	QPicture *pic;
324 	QString *str;
325 	QString *str_chord;
326 	struct MppVisualDot *pdot;
327 	MppElement *start;
328 	MppElement *stop;
329 	int newpage;
330 	int ndot;
331 };
332 
333 class Mpp {
334 public:
335 	Mpp();
336 	~Mpp();
337 
338 	QColor ColorBlack;
339 	QColor ColorWhite;
340 	QColor ColorGrey;
341 	QColor ColorLogo;
342 	QColor ColorGreen;
343 	QColor ColorLight;
344 	QColor ColorYellow;
345 
346 	QString VariantList;
347 	QString HomeDirTxt;
348 	QString HomeDirMid;
349 	QString HomeDirGp3;
350 	QString HomeDirMXML;
351 	QString HomeDirBackground;
352 
353 	int KeyAdjust[12];
354 };
355 
356 class MppSleep : public QThread
357 {
358 public:
usleep(unsigned long usecs)359     static void usleep(unsigned long usecs) { QThread::usleep(usecs); }
msleep(unsigned long msecs)360     static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
sleep(unsigned long secs)361     static void sleep(unsigned long secs) { QThread::sleep(secs); }
362 };
363 
364 extern Mpp Mpp;
365 
366 extern const QString MppChanName(int);
367 extern const QString MppDevName(int, int = 0);
368 extern QString MppBaseName(const QString &);
369 extern char *MppQStringToAscii(const QString &);
370 extern QString MppReadFile(const QString &);
371 extern void MppWriteFile(const QString &, QString text);
372 extern uint8_t MppReadRawFile(const QString &, QByteArray *pdata);
373 extern uint8_t MppWriteRawFile(const QString &, QByteArray *pdata);
374 extern const char *MppBaseKeyToString(int key, int sharp);
375 extern void MppScoreVariantInit(void);
376 extern uint8_t MppIsLabel(const QString &);
377 extern void MppSplitBaseTreble(const int *, uint8_t, int *, uint8_t *, int *, uint8_t *);
378 extern const QString MppChordModChars;
379 extern const QString MppVersion;
380 extern const QString MppIconFile;
381 
382 typedef int (MppCmp_t)(void *, const void *, const void *);
383 extern void MppSort(void *, size_t, size_t, MppCmp_t *, void *);
384 extern void MppSort(int *, size_t);
385 extern void MppTrans(int *ptr, size_t num, int ntrans);
386 
387 #ifdef HAVE_SCREENSHOT
388 extern void MppScreenShot(QWidget *, QApplication &);
389 #endif
390 
391 #endif	/* _MIDIPP_H_ */
392