drumstick 2.0.0
qwrk.cpp
Go to the documentation of this file.
1/*
2 WRK File component
3 Copyright (C) 2010-2020, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <QDataStream>
20#include <QFile>
21#include <QIODevice>
22#include <QStringList>
23#include <QTextCodec>
24#include <QTextStream>
25#include <cmath>
26#include <drumstick/qwrk.h>
27
32
33namespace drumstick { namespace File {
34
46
47class QWrk::QWrkPrivate {
48public:
49 QWrkPrivate():
50 m_Now(0),
51 m_From(0),
52 m_Thru(11930),
53 m_KeySig(0),
54 m_Clock(0),
55 m_AutoSave(0),
56 m_PlayDelay(0),
57 m_ZeroCtrls(false),
58 m_SendSPP(true),
59 m_SendCont(true),
60 m_PatchSearch(false),
61 m_AutoStop(false),
62 m_StopTime(4294967295U),
63 m_AutoRewind(false),
64 m_RewindTime(0),
65 m_MetroPlay(false),
66 m_MetroRecord(true),
67 m_MetroAccent(false),
68 m_CountIn(1),
69 m_ThruOn(true),
70 m_AutoRestart(false),
71 m_CurTempoOfs(1),
72 m_TempoOfs1(32),
73 m_TempoOfs2(64),
74 m_TempoOfs3(128),
75 m_PunchEnabled(false),
76 m_PunchInTime(0),
77 m_PunchOutTime(0),
78 m_EndAllTime(0),
79 m_division(120),
80 m_codec(nullptr),
81 m_IOStream(nullptr)
82 { }
83
84 quint32 m_Now;
85 quint32 m_From;
86 quint32 m_Thru;
87 quint8 m_KeySig;
88 quint8 m_Clock;
89 quint8 m_AutoSave;
90 quint8 m_PlayDelay;
91 bool m_ZeroCtrls;
92 bool m_SendSPP;
93 bool m_SendCont;
94 bool m_PatchSearch;
95 bool m_AutoStop;
96 quint32 m_StopTime;
97 bool m_AutoRewind;
98 quint32 m_RewindTime;
99 bool m_MetroPlay;
100 bool m_MetroRecord;
101 bool m_MetroAccent;
102 quint8 m_CountIn;
103 bool m_ThruOn;
104 bool m_AutoRestart;
105 quint8 m_CurTempoOfs;
106 quint8 m_TempoOfs1;
107 quint8 m_TempoOfs2;
108 quint8 m_TempoOfs3;
109 bool m_PunchEnabled;
110 quint32 m_PunchInTime;
111 quint32 m_PunchOutTime;
112 quint32 m_EndAllTime;
113
114 int m_division;
115 QTextCodec *m_codec;
116 QDataStream *m_IOStream;
117 QByteArray m_lastChunkData;
118 QList<RecTempo> m_tempos;
119};
120
126 QObject(parent),
127 d(new QWrkPrivate)
128{ }
129
134{ }
135
141{
142 return d->m_codec;
143}
144
151void QWrk::setTextCodec(QTextCodec *codec)
152{
153 d->m_codec = codec;
154}
155
162{
163 return d->m_lastChunkData;
164}
165
169void QWrk::readRawData(int size)
170{
171 d->m_lastChunkData = d->m_IOStream->device()->read(size);
172}
173
178int QWrk::getNow() const
179{
180 return d->m_Now;
181}
182
187int QWrk::getFrom() const
188{
189 return d->m_From;
190}
191
196int QWrk::getThru() const
197{
198 return d->m_Thru;
199}
200
206{
207 return d->m_KeySig;
208}
209
214int QWrk::getClock() const
215{
216 return d->m_Clock;
217}
218
224{
225 return d->m_AutoSave;
226}
227
233{
234 return d->m_PlayDelay;
235}
236
242{
243 return d->m_ZeroCtrls;
244}
245
251{
252 return d->m_SendSPP;
253}
254
260{
261 return d->m_SendCont;
262}
263
269{
270 return d->m_PatchSearch;
271}
272
278{
279 return d->m_AutoStop;
280}
281
286unsigned int QWrk::getStopTime() const
287{
288 return d->m_StopTime;
289}
290
296{
297 return d->m_AutoRewind;
298}
299
305{
306 return d->m_RewindTime;
307}
308
314{
315 return d->m_MetroPlay;
316}
317
323{
324 return d->m_MetroRecord;
325}
326
332{
333 return d->m_MetroAccent;
334}
335
341{
342 return d->m_CountIn;
343}
344
349bool QWrk::getThruOn() const
350{
351 return d->m_ThruOn;
352}
353
359{
360 return d->m_AutoRestart;
361}
362
368{
369 return d->m_CurTempoOfs;
370}
371
387{
388 return d->m_TempoOfs1;
389}
390
406{
407 return d->m_TempoOfs2;
408}
409
425{
426 return d->m_TempoOfs3;
427}
428
434{
435 return d->m_PunchEnabled;
436}
437
443{
444 return d->m_PunchInTime;
445}
446
452{
453 return d->m_PunchOutTime;
454}
455
461{
462 return d->m_EndAllTime;
463}
464
469quint8 QWrk::readByte()
470{
471 quint8 b = 0xff;
472 if (!d->m_IOStream->atEnd())
473 *d->m_IOStream >> b;
474 return b;
475}
476
483quint16 QWrk::to16bit(quint8 c1, quint8 c2)
484{
485 quint16 value = (c1 << 8);
486 value += c2;
487 return value;
488}
489
498quint32 QWrk::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
499{
500 quint32 value = (c1 << 24);
501 value += (c2 << 16);
502 value += (c3 << 8);
503 value += c4;
504 return value;
505}
506
511quint16 QWrk::read16bit()
512{
513 quint8 c1, c2;
514 c1 = readByte();
515 c2 = readByte();
516 return to16bit(c2, c1);
517}
518
523quint32 QWrk::read24bit()
524{
525 quint8 c1, c2, c3;
526 c1 = readByte();
527 c2 = readByte();
528 c3 = readByte();
529 return to32bit(0, c3, c2, c1);
530}
531
536quint32 QWrk::read32bit()
537{
538 quint8 c1, c2, c3, c4;
539 c1 = readByte();
540 c2 = readByte();
541 c3 = readByte();
542 c4 = readByte();
543 return to32bit(c4, c3, c2, c1);
544}
545
550QString QWrk::readString(int len)
551{
552 QString s;
553 if ( len > 0 ) {
554 quint8 c = 0xff;
555 QByteArray data;
556 for ( int i = 0; i < len && c != 0 && !atEnd(); ++i ) {
557 c = readByte();
558 if ( c != 0)
559 data += c;
560 }
561 if (d->m_codec == nullptr)
562 s = QString(data);
563 else
564 s = d->m_codec->toUnicode(data);
565 }
566 return s;
567}
568
573QString QWrk::readVarString()
574{
575 QString s;
576 QByteArray data;
577 quint8 b;
578 do {
579 b = readByte();
580 if (b != 0)
581 data += b;
582 } while (b != 0 && !atEnd());
583 if (d->m_codec == nullptr)
584 s = QString(data);
585 else
586 s = d->m_codec->toUnicode(data);
587 return s;
588}
589
595{
596 return d->m_IOStream->device()->pos();
597}
598
603void QWrk::seek(qint64 pos)
604{
605 d->m_IOStream->device()->seek(pos);
606}
607
612bool QWrk::atEnd()
613{
614 return d->m_IOStream->atEnd();
615}
616
621void QWrk::readGap(int size)
622{
623 if ( size > 0)
624 seek( getFilePos() + size );
625}
626
631void QWrk::readFromStream(QDataStream *stream)
632{
633 d->m_IOStream = stream;
634 wrkRead();
635}
636
641void QWrk::readFromFile(const QString& fileName)
642{
643 QFile file(fileName);
644 file.open(QIODevice::ReadOnly);
645 QDataStream ds(&file);
646 readFromStream(&ds);
647 file.close();
648}
649
650void QWrk::processTrackChunk()
651{
652 int namelen;
653 QString name[2];
654 int trackno;
655 int channel;
656 int pitch;
657 int velocity;
658 int port;
659 bool selected;
660 bool muted;
661 bool loop;
662
663 trackno = read16bit();
664 for(int i=0; i<2; ++i) {
665 namelen = readByte();
666 name[i] = readString(namelen);
667 }
668 channel = readByte() & 0x0f;
669 pitch = readByte();
670 velocity = readByte();
671 port = readByte();
672 quint8 flags = readByte();
673 selected = ((flags & 1) != 0);
674 muted = ((flags & 2) != 0);
675 loop = ((flags & 4) != 0);
676 Q_EMIT signalWRKTrack( name[0], name[1],
677 trackno, channel, pitch,
678 velocity, port, selected,
679 muted, loop );
680}
681
682void QWrk::processVarsChunk()
683{
684 d->m_Now = read32bit();
685 d->m_From = read32bit();
686 d->m_Thru = read32bit();
687 d->m_KeySig = readByte();
688 d->m_Clock = readByte();
689 d->m_AutoSave = readByte();
690 d->m_PlayDelay = readByte();
691 readGap(1);
692 d->m_ZeroCtrls = (readByte() != 0);
693 d->m_SendSPP = (readByte() != 0);
694 d->m_SendCont = (readByte() != 0);
695 d->m_PatchSearch = (readByte() != 0);
696 d->m_AutoStop = (readByte() != 0);
697 d->m_StopTime = read32bit();
698 d->m_AutoRewind = (readByte() != 0);
699 d->m_RewindTime = read32bit();
700 d->m_MetroPlay = (readByte() != 0);
701 d->m_MetroRecord = (readByte() != 0);
702 d->m_MetroAccent = (readByte() != 0);
703 d->m_CountIn = readByte();
704 readGap(2);
705 d->m_ThruOn = (readByte() != 0);
706 readGap(19);
707 d->m_AutoRestart = (readByte() != 0);
708 d->m_CurTempoOfs = readByte();
709 d->m_TempoOfs1 = readByte();
710 d->m_TempoOfs2 = readByte();
711 d->m_TempoOfs3 = readByte();
712 readGap(2);
713 d->m_PunchEnabled = (readByte() != 0);
714 d->m_PunchInTime = read32bit();
715 d->m_PunchOutTime = read32bit();
716 d->m_EndAllTime = read32bit();
717
718 Q_EMIT signalWRKGlobalVars();
719}
720
721void QWrk::processTimebaseChunk()
722{
723 quint16 timebase = read16bit();
724 d->m_division = timebase;
725 Q_EMIT signalWRKTimeBase(timebase);
726}
727
728void QWrk::processNoteArray(int track, int events)
729{
730 quint32 time = 0;
731 quint8 status = 0, data1 = 0, data2 = 0, i = 0;
732 quint16 dur = 0;
733 int value = 0, type = 0, channel = 0, len = 0;
734 QString text;
735 QByteArray data;
736 for ( i = 0; (i < events) && !atEnd(); ++i ) {
737 time = read24bit();
738 status = readByte();
739 dur = 0;
740 if (status >= 0x90) {
741 type = status & 0xf0;
742 channel = status & 0x0f;
743 data1 = readByte();
744 if (type == 0x90 || type == 0xA0 || type == 0xB0 || type == 0xE0)
745 data2 = readByte();
746 if (type == 0x90)
747 dur = read16bit();
748 switch (type) {
749 case 0x90:
750 Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur);
751 break;
752 case 0xA0:
753 Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2);
754 break;
755 case 0xB0:
756 Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2);
757 break;
758 case 0xC0:
759 Q_EMIT signalWRKProgram(track, time, channel, data1);
760 break;
761 case 0xD0:
762 Q_EMIT signalWRKChanPress(track, time, channel, data1);
763 break;
764 case 0xE0:
765 value = (data2 << 7) + data1 - 8192;
766 Q_EMIT signalWRKPitchBend(track, time, channel, value);
767 break;
768 case 0xF0:
769 Q_EMIT signalWRKSysexEvent(track, time, data1);
770 break;
771 }
772 } else if (status == 5) {
773 int code = read16bit();
774 len = read32bit();
775 text = readString(len);
776 Q_EMIT signalWRKExpression(track, time, code, text);
777 } else if (status == 6) {
778 int code = read16bit();
779 dur = read16bit();
780 readGap(4);
781 Q_EMIT signalWRKHairpin(track, time, code, dur);
782 } else if (status == 7) {
783 len = read32bit();
784 text = readString(len);
785 data.clear();
786 for(int j=0; j<13; ++j) {
787 int byte = readByte();
788 data += byte;
789 }
790 Q_EMIT signalWRKChord(track, time, text, data);
791 } else if (status == 8) {
792 len = read16bit();
793 data.clear();
794 for(int j=0; j<len; ++j) {
795 int byte = readByte();
796 data += byte;
797 }
798 Q_EMIT signalWRKSysex(0, QString(), false, 0, data);
799 } else {
800 len = read32bit();
801 text = readString(len);
802 Q_EMIT signalWRKText(track, time, status, text);
803 }
804 }
805 if ((i < events) && atEnd()) {
806 Q_EMIT signalWRKError("Corrupted file");
807 }
808 Q_EMIT signalWRKStreamEnd(time + dur);
809}
810
811void QWrk::processStreamChunk()
812{
813 long time = 0;
814 int dur = 0, value = 0, type = 0, channel = 0, i = 0;
815 quint8 status = 0, data1 = 0, data2 = 0;
816 quint16 track = read16bit();
817 int events = read16bit();
818 for ( i = 0; (i < events) && !atEnd(); ++i ) {
819 time = read24bit();
820 status = readByte();
821 data1 = readByte();
822 data2 = readByte();
823 dur = read16bit();
824 type = status & 0xf0;
825 channel = status & 0x0f;
826 switch (type) {
827 case 0x90:
828 Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur);
829 break;
830 case 0xA0:
831 Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2);
832 break;
833 case 0xB0:
834 Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2);
835 break;
836 case 0xC0:
837 Q_EMIT signalWRKProgram(track, time, channel, data1);
838 break;
839 case 0xD0:
840 Q_EMIT signalWRKChanPress(track, time, channel, data1);
841 break;
842 case 0xE0:
843 value = (data2 << 7) + data1 - 8192;
844 Q_EMIT signalWRKPitchBend(track, time, channel, value);
845 break;
846 case 0xF0:
847 Q_EMIT signalWRKSysexEvent(track, time, data1);
848 break;
849 }
850 }
851 if ((i < events) && atEnd()) {
852 Q_EMIT signalWRKError("Corrupted file");
853 }
854 Q_EMIT signalWRKStreamEnd(time + dur);
855}
856
857void QWrk::processMeterChunk()
858{
859 int count = read16bit();
860 for (int i = 0; i < count; ++i) {
861 readGap(4);
862 int measure = read16bit();
863 int num = readByte();
864 int den = pow(2.0, readByte());
865 readGap(4);
866 Q_EMIT signalWRKTimeSig(measure, num, den);
867 }
868}
869
870void QWrk::processMeterKeyChunk()
871{
872 int count = read16bit();
873 for (int i = 0; i < count; ++i) {
874 int measure = read16bit();
875 int num = readByte();
876 int den = pow(2.0, readByte());
877 qint8 alt = readByte();
878 Q_EMIT signalWRKTimeSig(measure, num, den);
879 Q_EMIT signalWRKKeySig(measure, alt);
880 }
881}
882
883double QWrk::getRealTime(long ticks) const
884{
885 double division = 1.0 * d->m_division;
886 RecTempo last;
887 last.time = 0;
888 last.tempo = 100.0;
889 last.seconds = 0.0;
890 if (!d->m_tempos.isEmpty()) {
891 foreach(const RecTempo& rec, d->m_tempos) {
892 if (rec.time >= ticks)
893 break;
894 last = rec;
895 }
896 }
897 return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo));
898}
899
900void QWrk::processTempoChunk(int factor)
901{
902 double division = 1.0 * d->m_division;
903 int count = read16bit();
904 RecTempo last, next;
905 for (int i = 0; i < count; ++i) {
906
907 long time = read32bit();
908 readGap(4);
909 long tempo = read16bit() * factor;
910 readGap(8);
911
912 next.time = time;
913 next.tempo = tempo / 100.0;
914 next.seconds = 0.0;
915 last.time = 0;
916 last.tempo = next.tempo;
917 last.seconds = 0.0;
918 if (! d->m_tempos.isEmpty()) {
919 foreach(const RecTempo& rec, d->m_tempos) {
920 if (rec.time >= time)
921 break;
922 last = rec;
923 }
924 next.seconds = last.seconds +
925 (((time - last.time) / division) * (60.0 / last.tempo));
926 }
927 d->m_tempos.append(next);
928
929 Q_EMIT signalWRKTempo(time, tempo);
930 }
931}
932
933void QWrk::processSysexChunk()
934{
935 int j;
936 QString name;
937 QByteArray data;
938 int bank = readByte();
939 int length = read16bit();
940 bool autosend = (readByte() != 0);
941 int namelen = readByte();
942 name = readString(namelen);
943 for(j=0; j<length; ++j) {
944 int byte = readByte();
945 data += byte;
946 }
947 Q_EMIT signalWRKSysex(bank, name, autosend, 0, data);
948}
949
950void QWrk::processSysex2Chunk()
951{
952 int j;
953 QString name;
954 QByteArray data;
955 int bank = read16bit();
956 int length = read32bit();
957 quint8 b = readByte();
958 int port = ( b & 0xf0 ) >> 4;
959 bool autosend = ( (b & 0x0f) != 0);
960 int namelen = readByte();
961 name = readString(namelen);
962 for(j=0; j<length; ++j) {
963 int byte = readByte();
964 data += byte;
965 }
966 Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
967}
968
969void QWrk::processNewSysexChunk()
970{
971 int j;
972 QString name;
973 QByteArray data;
974 int bank = read16bit();
975 int length = read32bit();
976 int port = read16bit();
977 bool autosend = (readByte() != 0);
978 int namelen = readByte();
979 name = readString(namelen);
980 for(j=0; j<length; ++j) {
981 int byte = readByte();
982 data += byte;
983 }
984 Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
985}
986
987void QWrk::processThruChunk()
988{
989 readGap(2);
990 qint8 port = readByte(); // 0->127
991 qint8 channel = readByte(); // -1, 0->15
992 qint8 keyPlus = readByte(); // 0->127
993 qint8 velPlus = readByte(); // 0->127
994 qint8 localPort = readByte();
995 qint8 mode = readByte();
996 Q_EMIT signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort);
997}
998
999void QWrk::processTrackOffset()
1000{
1001 quint16 track = read16bit();
1002 qint16 offset = read16bit();
1003 Q_EMIT signalWRKTrackOffset(track, offset);
1004}
1005
1006void QWrk::processTrackReps()
1007{
1008 quint16 track = read16bit();
1009 quint16 reps = read16bit();
1010 Q_EMIT signalWRKTrackReps(track, reps);
1011}
1012
1013void QWrk::processTrackPatch()
1014{
1015 quint16 track = read16bit();
1016 qint8 patch = readByte();
1017 Q_EMIT signalWRKTrackPatch(track, patch);
1018}
1019
1020void QWrk::processTimeFormat()
1021{
1022 quint16 fmt = read16bit();
1023 quint16 ofs = read16bit();
1024 Q_EMIT signalWRKTimeFormat(fmt, ofs);
1025}
1026
1027void QWrk::processComments()
1028{
1029 int len = read16bit();
1030 QString text = readString(len);
1031 Q_EMIT signalWRKComments(text);
1032}
1033
1034void QWrk::processVariableRecord(int max)
1035{
1036 int datalen = max - 32;
1037 QByteArray data;
1038 QString name = readVarString();
1039 readGap(31 - name.length());
1040 for ( int i = 0; i < datalen; ++i )
1041 data += readByte();
1042 Q_EMIT signalWRKVariableRecord(name, data);
1043}
1044
1045void QWrk::processUnknown(int id)
1046{
1047 Q_EMIT signalWRKUnknownChunk(id, d->m_lastChunkData);
1048}
1049
1050void QWrk::processNewTrack()
1051{
1052 qint16 bank = -1;
1053 qint16 patch = -1;
1054 //qint16 vol = -1;
1055 //qint16 pan = -1;
1056 qint8 key = -1;
1057 qint8 vel = 0;
1058 quint8 port = 0;
1059 qint8 channel = 0;
1060 bool selected = false;
1061 bool muted = false;
1062 bool loop = false;
1063 quint16 track = read16bit();
1064 quint8 len = readByte();
1065 QString name = readString(len);
1066 bank = read16bit();
1067 patch = read16bit();
1068 /*vol =*/ read16bit();
1069 /*pan =*/ read16bit();
1070 key = readByte();
1071 vel = readByte();
1072 readGap(7);
1073 port = readByte();
1074 channel = readByte();
1075 muted = (readByte() != 0);
1076 Q_EMIT signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop);
1077 if (bank > -1)
1078 Q_EMIT signalWRKTrackBank(track, bank);
1079 if (patch > -1) {
1080 if (channel > -1)
1081 Q_EMIT signalWRKProgram(track, 0, channel, patch);
1082 else
1083 Q_EMIT signalWRKTrackPatch(track, patch);
1084 }
1085}
1086
1087void QWrk::processSoftVer()
1088{
1089 int len = readByte();
1090 QString vers = readString(len);
1091 Q_EMIT signalWRKSoftVer(vers);
1092}
1093
1094void QWrk::processTrackName()
1095{
1096 int track = read16bit();
1097 int len = readByte();
1098 QString name = readString(len);
1099 Q_EMIT signalWRKTrackName(track, name);
1100}
1101
1102void QWrk::processStringTable()
1103{
1104 QStringList table;
1105 int rows = read16bit();
1106 for (int i = 0; i < rows; ++i) {
1107 int len = readByte();
1108 QString name = readString(len);
1109 int idx = readByte();
1110 table.insert(idx, name);
1111 }
1112 Q_EMIT signalWRKStringTable(table);
1113}
1114
1115void QWrk::processLyricsStream()
1116{
1117 quint16 track = read16bit();
1118 int events = read32bit();
1119 processNoteArray(track, events);
1120}
1121
1122void QWrk::processTrackVol()
1123{
1124 quint16 track = read16bit();
1125 int vol = read16bit();
1126 Q_EMIT signalWRKTrackVol(track, vol);
1127}
1128
1129void QWrk::processNewTrackOffset()
1130{
1131 quint16 track = read16bit();
1132 int offset = read32bit();
1133 Q_EMIT signalWRKTrackOffset(track, offset);
1134}
1135
1136void QWrk::processTrackBank()
1137{
1138 quint16 track = read16bit();
1139 int bank = read16bit();
1140 Q_EMIT signalWRKTrackBank(track, bank);
1141}
1142
1143void QWrk::processSegmentChunk()
1144{
1145 QString name;
1146 int track = read16bit();
1147 int offset = read32bit();
1148 readGap(8);
1149 int len = readByte();
1150 name = readString(len);
1151 readGap(20);
1152 Q_EMIT signalWRKSegment(track, offset, name);
1153 int events = read32bit();
1154 processNoteArray(track, events);
1155}
1156
1157void QWrk::processNewStream()
1158{
1159 QString name;
1160 int track = read16bit();
1161 int len = readByte();
1162 name = readString(len);
1163 Q_EMIT signalWRKSegment(track, 0, name);
1164 int events = read32bit();
1165 processNoteArray(track, events);
1166}
1167
1168void QWrk::processEndChunk()
1169{
1170 emit signalWRKEnd();
1171}
1172
1173int QWrk::readChunk()
1174{
1175 long start_pos, final_pos;
1176 int ck_len, ck = readByte();
1177 if (ck != END_CHUNK) {
1178 ck_len = read32bit();
1179 start_pos = getFilePos();
1180 final_pos = start_pos + ck_len;
1181 readRawData(ck_len);
1182 seek(start_pos);
1183 switch (ck) {
1184 case TRACK_CHUNK:
1185 processTrackChunk();
1186 break;
1187 case VARS_CHUNK:
1188 processVarsChunk();
1189 break;
1190 case TIMEBASE_CHUNK:
1191 processTimebaseChunk();
1192 break;
1193 case STREAM_CHUNK:
1194 processStreamChunk();
1195 break;
1196 case METER_CHUNK:
1197 processMeterChunk();
1198 break;
1199 case TEMPO_CHUNK:
1200 processTempoChunk(100);
1201 break;
1202 case NTEMPO_CHUNK:
1203 processTempoChunk();
1204 break;
1205 case SYSEX_CHUNK:
1206 processSysexChunk();
1207 break;
1208 case THRU_CHUNK:
1209 processThruChunk();
1210 break;
1211 case TRKOFFS_CHUNK:
1212 processTrackOffset();
1213 break;
1214 case TRKREPS_CHUNK:
1215 processTrackReps();
1216 break;
1217 case TRKPATCH_CHUNK:
1218 processTrackPatch();
1219 break;
1220 case TIMEFMT_CHUNK:
1221 processTimeFormat();
1222 break;
1223 case COMMENTS_CHUNK:
1224 processComments();
1225 break;
1226 case VARIABLE_CHUNK:
1227 processVariableRecord(ck_len);
1228 break;
1229 case NTRACK_CHUNK:
1230 processNewTrack();
1231 break;
1232 case SOFTVER_CHUNK:
1233 processSoftVer();
1234 break;
1235 case TRKNAME_CHUNK:
1236 processTrackName();
1237 break;
1238 case STRTAB_CHUNK:
1239 processStringTable();
1240 break;
1241 case LYRICS_CHUNK:
1242 processLyricsStream();
1243 break;
1244 case TRKVOL_CHUNK:
1245 processTrackVol();
1246 break;
1247 case NTRKOFS_CHUNK:
1248 processNewTrackOffset();
1249 break;
1250 case TRKBANK_CHUNK:
1251 processTrackBank();
1252 break;
1253 case METERKEY_CHUNK:
1254 processMeterKeyChunk();
1255 break;
1256 case SYSEX2_CHUNK:
1257 processSysex2Chunk();
1258 break;
1259 case NSYSEX_CHUNK:
1260 processNewSysexChunk();
1261 break;
1262 case SGMNT_CHUNK:
1263 processSegmentChunk();
1264 break;
1265 case NSTREAM_CHUNK:
1266 processNewStream();
1267 break;
1268 default:
1269 processUnknown(ck);
1270 }
1271 seek(final_pos);
1272 }
1273 return ck;
1274}
1275
1276void QWrk::wrkRead()
1277{
1278 QByteArray hdr(HEADER.length(), ' ');
1279 d->m_tempos.clear();
1280 d->m_IOStream->device()->read(hdr.data(), HEADER.length());
1281 if (hdr == HEADER) {
1282 int vma, vme;
1283 int ck_id;
1284 readGap(1);
1285 vme = readByte();
1286 vma = readByte();
1287 Q_EMIT signalWRKHeader(vma, vme);
1288 do {
1289 ck_id = readChunk();
1290 } while (ck_id != END_CHUNK);
1291 if (!atEnd())
1292 Q_EMIT signalWRKError("Corrupted file");
1293 else
1294 processEndChunk();
1295 } else
1296 Q_EMIT signalWRKError("Invalid file format");
1297}
1298
1299const QByteArray QWrk::HEADER = QByteArrayLiteral("CAKEWALK");
1300
1301} // namespace File
1302} // namespace drumstick
The QObject class is the base class of all Qt objects.
void signalWRKTrackPatch(int track, int patch)
Emitted after reading a track patch chunk.
bool getMetroRecord() const
Metronome on during recording?
Definition qwrk.cpp:322
bool getPunchEnabled() const
Auto-Punch enabled?
Definition qwrk.cpp:433
void signalWRKText(int track, long time, int type, const QString &data)
Emitted after reading a text message.
int getRewindTime() const
Auto-rewind time.
Definition qwrk.cpp:304
bool getZeroCtrls() const
Zero continuous controllers?
Definition qwrk.cpp:241
void signalWRKTrack(const QString &name1, const QString &name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a track prefix chunk.
QWrk(QObject *parent=nullptr)
Constructor.
Definition qwrk.cpp:125
void signalWRKProgram(int track, long time, int chan, int patch)
Emitted after reading a Program change message.
void signalWRKChord(int track, long time, const QString &name, const QByteArray &data)
Emitted after reading a chord diagram chunk.
static const QByteArray HEADER
Cakewalk WRK file format header string id.
Definition qwrk.h:131
void setTextCodec(QTextCodec *codec)
Sets the text codec for text meta-events.
Definition qwrk.cpp:151
void signalWRKHeader(int verh, int verl)
Emitted after reading a WRK header.
void signalWRKSysexEvent(int track, long time, int bank)
Emitted after reading a System Exclusive event.
int getAutoSave() const
Auto save (0=disabled, 1..256=minutes).
Definition qwrk.cpp:223
long getFilePos()
Current position in the data stream.
Definition qwrk.cpp:594
bool getThruOn() const
MIDI Thru enabled?
Definition qwrk.cpp:349
void signalWRKGlobalVars()
Emitted after reading the global variables chunk.
void signalWRKSoftVer(const QString &version)
Emitted after reading a software version chunk.
int getNow() const
Now marker time.
Definition qwrk.cpp:178
int getPunchOutTime() const
Punch-out time.
Definition qwrk.cpp:451
void signalWRKComments(const QString &data)
Emitted after reading a comments chunk.
void signalWRKTrackOffset(int track, int offset)
Emitted after reading a track offset chunk.
void signalWRKChanPress(int track, long time, int chan, int press)
Emitted after reading a Channel Aftertouch message.
void signalWRKStreamEnd(long time)
Emitted after reading the last event of a event stream.
bool getAutoStop() const
Auto-stop?
Definition qwrk.cpp:277
int getEndAllTime() const
Time of latest event (incl.
Definition qwrk.cpp:460
void signalWRKKeyPress(int track, long time, int chan, int pitch, int press)
Emitted after reading a Polyphonic Aftertouch message.
void signalWRKVariableRecord(const QString &name, const QByteArray &data)
Emitted after reading a variable chunk.
void signalWRKTrackVol(int track, int vol)
Emitted after reading a track volume chunk.
void signalWRKStringTable(const QStringList &strs)
Emitted after reading a string event types chunk.
int getPlayDelay() const
Play Delay.
Definition qwrk.cpp:232
bool getSendSPP() const
Send Song Position Pointer?
Definition qwrk.cpp:250
void signalWRKError(const QString &errorStr)
Emitted for a WRK file read error.
virtual ~QWrk()
Destructor.
Definition qwrk.cpp:133
void signalWRKSegment(int track, long time, const QString &name)
Emitted after reading a segment prefix chunk.
void signalWRKTempo(long time, int tempo)
Emitted after reading a Tempo Change message.
void signalWRKExpression(int track, long time, int code, const QString &text)
Emitted after reading an expression indication (notation) chunk.
void signalWRKTimeSig(int bar, int num, int den)
Emitted after reading a WRK Time signature.
void signalWRKHairpin(int track, long time, int code, int dur)
Emitted after reading a hairpin symbol (notation) chunk.
void signalWRKPitchBend(int track, long time, int chan, int value)
Emitted after reading a Bender message.
void signalWRKEnd()
Emitted after reading the last chunk of a WRK file.
int getTempoOfs3() const
Fixed-point ratio value of tempo offset 3.
Definition qwrk.cpp:424
int getThru() const
Thru marker time.
Definition qwrk.cpp:196
bool getSendCont() const
Send MIDI Continue?
Definition qwrk.cpp:259
int getTempoOfs2() const
Fixed-point ratio value of tempo offset 2.
Definition qwrk.cpp:405
bool getPatchSearch() const
Patch/controller search-back?
Definition qwrk.cpp:268
void readFromStream(QDataStream *stream)
Reads a stream.
Definition qwrk.cpp:631
void signalWRKThru(int mode, int port, int channel, int keyPlus, int velPlus, int localPort)
Emitted after reading an Extended Thru parameters chunk.
int getPunchInTime() const
Punch-in time.
Definition qwrk.cpp:442
void signalWRKNote(int track, long time, int chan, int pitch, int vol, int dur)
Emitted after reading a Note message.
unsigned int getStopTime() const
Auto-stop time.
Definition qwrk.cpp:286
void signalWRKUnknownChunk(int type, const QByteArray &data)
Emitted after reading an unknown chunk.
void signalWRKTrackBank(int track, int bank)
Emitted after reading a track bank chunk.
void signalWRKTrackName(int track, const QString &name)
Emitted after reading a track name chunk.
void signalWRKTimeBase(int timebase)
Emitted after reading the timebase chunk.
QByteArray getLastChunkRawData() const
Gets the last chunk raw data (undecoded).
Definition qwrk.cpp:161
bool getAutoRewind() const
Auto-rewind?
Definition qwrk.cpp:295
bool getMetroPlay() const
Metronome on during playback?
Definition qwrk.cpp:313
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
Definition qwrk.cpp:140
int getFrom() const
From marker time.
Definition qwrk.cpp:187
void signalWRKTimeFormat(int frames, int offset)
Emitted after reading a SMPTE time format chunk.
void signalWRKSysex(int bank, const QString &name, bool autosend, int port, const QByteArray &data)
Emitted after reading a System Exclusive Bank.
void readFromFile(const QString &fileName)
Reads a stream from a disk file.
Definition qwrk.cpp:641
int getCountIn() const
Measures of count-in (0=no count-in).
Definition qwrk.cpp:340
int getCurTempoOfs() const
Which of the 3 tempo offsets is used: 0..2.
Definition qwrk.cpp:367
void signalWRKCtlChange(int track, long time, int chan, int ctl, int value)
Emitted after reading a Control Change message.
void signalWRKTrackReps(int track, int reps)
Emitted after reading a track offset chunk.
void signalWRKNewTrack(const QString &name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop)
Emitted after reading a new track prefix.
void signalWRKKeySig(int bar, int alt)
Emitted after reading a WRK Key Signature.
bool getAutoRestart() const
Auto-restart?
Definition qwrk.cpp:358
int getClock() const
Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE).
Definition qwrk.cpp:214
int getKeySig() const
Key signature (0=C, 1=C#, ... 11=B).
Definition qwrk.cpp:205
bool getMetroAccent() const
Metronome accents primary beats?
Definition qwrk.cpp:331
int getTempoOfs1() const
Fixed-point ratio value of tempo offset 1.
Definition qwrk.cpp:386
@ NTRKOFS_CHUNK
Track offset.
Definition qwrk.h:65
@ NTRACK_CHUNK
Track prefix.
Definition qwrk.h:67
@ TRKPATCH_CHUNK
Track patch.
Definition qwrk.h:55
@ STRTAB_CHUNK
Table of text event types.
Definition qwrk.h:61
@ NTEMPO_CHUNK
New Tempo map.
Definition qwrk.h:56
@ VARS_CHUNK
Global variables.
Definition qwrk.h:45
@ TRKBANK_CHUNK
Track bank.
Definition qwrk.h:66
@ COMMENTS_CHUNK
Comments.
Definition qwrk.h:50
@ SGMNT_CHUNK
Segment prefix.
Definition qwrk.h:70
@ SOFTVER_CHUNK
Software version which saved the file.
Definition qwrk.h:71
@ TRKNAME_CHUNK
Track name.
Definition qwrk.h:63
@ TIMEFMT_CHUNK
SMPTE time format.
Definition qwrk.h:53
@ END_CHUNK
Last chunk, end of file.
Definition qwrk.h:72
@ STREAM_CHUNK
Events stream.
Definition qwrk.h:44
@ TRACK_CHUNK
Track prefix.
Definition qwrk.h:43
@ TIMEBASE_CHUNK
Timebase. If present is the first chunk in the file.
Definition qwrk.h:52
@ TRKOFFS_CHUNK
Track offset.
Definition qwrk.h:51
@ NSYSEX_CHUNK
System exclusive bank.
Definition qwrk.h:68
@ THRU_CHUNK
Extended thru parameters.
Definition qwrk.h:57
@ SYSEX2_CHUNK
System exclusive bank.
Definition qwrk.h:60
@ NSTREAM_CHUNK
Events stream.
Definition qwrk.h:69
@ TEMPO_CHUNK
Tempo map.
Definition qwrk.h:46
@ VARIABLE_CHUNK
Variable record chunk.
Definition qwrk.h:64
@ METER_CHUNK
Meter map.
Definition qwrk.h:47
@ METERKEY_CHUNK
Meter/Key map.
Definition qwrk.h:62
@ TRKREPS_CHUNK
Track repetitions.
Definition qwrk.h:54
@ TRKVOL_CHUNK
Track volume.
Definition qwrk.h:59
@ SYSEX_CHUNK
System exclusive bank.
Definition qwrk.h:48
@ LYRICS_CHUNK
Events stream with lyrics.
Definition qwrk.h:58
Drumstick File library.
Definition qsmf.cpp:35
Drumstick common.
Cakewalk WRK Files Input.