drumstick  2.1.0
qwrk.cpp
Go to the documentation of this file.
1 /*
2  WRK File component
3  Copyright (C) 2010-2021, 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 <QDebug>
20 #include <QDataStream>
21 #include <QFile>
22 #include <QIODevice>
23 #include <QStringList>
24 #include <QTextCodec>
25 #include <QTextStream>
26 #include <cmath>
27 #include <drumstick/qwrk.h>
28 
34 namespace drumstick { namespace File {
35 
48 class QWrk::QWrkPrivate {
49 public:
50  QWrkPrivate():
51  m_Now(0),
52  m_From(0),
53  m_Thru(11930),
54  m_KeySig(0),
55  m_Clock(0),
56  m_AutoSave(0),
57  m_PlayDelay(0),
58  m_ZeroCtrls(false),
59  m_SendSPP(true),
60  m_SendCont(true),
61  m_PatchSearch(false),
62  m_AutoStop(false),
63  m_StopTime(4294967295U),
64  m_AutoRewind(false),
65  m_RewindTime(0),
66  m_MetroPlay(false),
67  m_MetroRecord(true),
68  m_MetroAccent(false),
69  m_CountIn(1),
70  m_ThruOn(true),
71  m_AutoRestart(false),
72  m_CurTempoOfs(1),
73  m_TempoOfs1(32),
74  m_TempoOfs2(64),
75  m_TempoOfs3(128),
76  m_PunchEnabled(false),
77  m_PunchInTime(0),
78  m_PunchOutTime(0),
79  m_EndAllTime(0),
80  m_division(120),
81  m_codec(nullptr),
82  m_IOStream(nullptr)
83  { }
84 
85  quint32 m_Now;
86  quint32 m_From;
87  quint32 m_Thru;
88  quint8 m_KeySig;
89  quint8 m_Clock;
90  quint8 m_AutoSave;
91  quint8 m_PlayDelay;
92  bool m_ZeroCtrls;
93  bool m_SendSPP;
94  bool m_SendCont;
95  bool m_PatchSearch;
96  bool m_AutoStop;
97  quint32 m_StopTime;
98  bool m_AutoRewind;
99  quint32 m_RewindTime;
100  bool m_MetroPlay;
101  bool m_MetroRecord;
102  bool m_MetroAccent;
103  quint8 m_CountIn;
104  bool m_ThruOn;
105  bool m_AutoRestart;
106  quint8 m_CurTempoOfs;
107  quint8 m_TempoOfs1;
108  quint8 m_TempoOfs2;
109  quint8 m_TempoOfs3;
110  bool m_PunchEnabled;
111  quint32 m_PunchInTime;
112  quint32 m_PunchOutTime;
113  quint32 m_EndAllTime;
114 
115  int m_division;
116  QTextCodec *m_codec;
117  QDataStream *m_IOStream;
118  QByteArray m_lastChunkData;
119  QList<RecTempo> m_tempos;
120 
121  qint64 m_lastChunkPos;
122  qint64 internalFilePos();
123 };
124 
129 QWrk::QWrk(QObject * parent) :
130  QObject(parent),
131  d(new QWrkPrivate)
132 { }
133 
138 { }
139 
144 QTextCodec* QWrk::getTextCodec()
145 {
146  return d->m_codec;
147 }
148 
155 void QWrk::setTextCodec(QTextCodec *codec)
156 {
157  d->m_codec = codec;
158 }
159 
165 QByteArray QWrk::getLastChunkRawData() const
166 {
167  return d->m_lastChunkData;
168 }
169 
173 void QWrk::readRawData(int size)
174 {
175  if (size > 0) {
176  d->m_lastChunkData = d->m_IOStream->device()->read(size);
177  } else {
178  d->m_lastChunkData.clear();
179  //qDebug() << Q_FUNC_INFO << "Size error:" << size;
180  }
181 }
182 
187 int QWrk::getNow() const
188 {
189  return d->m_Now;
190 }
191 
196 int QWrk::getFrom() const
197 {
198  return d->m_From;
199 }
200 
205 int QWrk::getThru() const
206 {
207  return d->m_Thru;
208 }
209 
214 int QWrk::getKeySig() const
215 {
216  return d->m_KeySig;
217 }
218 
223 int QWrk::getClock() const
224 {
225  return d->m_Clock;
226 }
227 
232 int QWrk::getAutoSave() const
233 {
234  return d->m_AutoSave;
235 }
236 
242 {
243  return d->m_PlayDelay;
244 }
245 
250 bool QWrk::getZeroCtrls() const
251 {
252  return d->m_ZeroCtrls;
253 }
254 
259 bool QWrk::getSendSPP() const
260 {
261  return d->m_SendSPP;
262 }
263 
268 bool QWrk::getSendCont() const
269 {
270  return d->m_SendCont;
271 }
272 
278 {
279  return d->m_PatchSearch;
280 }
281 
286 bool QWrk::getAutoStop() const
287 {
288  return d->m_AutoStop;
289 }
290 
295 unsigned int QWrk::getStopTime() const
296 {
297  return d->m_StopTime;
298 }
299 
305 {
306  return d->m_AutoRewind;
307 }
308 
314 {
315  return d->m_RewindTime;
316 }
317 
322 bool QWrk::getMetroPlay() const
323 {
324  return d->m_MetroPlay;
325 }
326 
332 {
333  return d->m_MetroRecord;
334 }
335 
341 {
342  return d->m_MetroAccent;
343 }
344 
349 int QWrk::getCountIn() const
350 {
351  return d->m_CountIn;
352 }
353 
358 bool QWrk::getThruOn() const
359 {
360  return d->m_ThruOn;
361 }
362 
368 {
369  return d->m_AutoRestart;
370 }
371 
377 {
378  return d->m_CurTempoOfs;
379 }
380 
396 {
397  return d->m_TempoOfs1;
398 }
399 
415 {
416  return d->m_TempoOfs2;
417 }
418 
434 {
435  return d->m_TempoOfs3;
436 }
437 
443 {
444  return d->m_PunchEnabled;
445 }
446 
452 {
453  return d->m_PunchInTime;
454 }
455 
461 {
462  return d->m_PunchOutTime;
463 }
464 
470 {
471  return d->m_EndAllTime;
472 }
473 
478 quint8 QWrk::readByte()
479 {
480  quint8 b = 0xff;
481  if (!d->m_IOStream->atEnd())
482  *d->m_IOStream >> b;
483  return b;
484 }
485 
492 quint16 QWrk::to16bit(quint8 c1, quint8 c2)
493 {
494  quint16 value = (c1 << 8);
495  value += c2;
496  return value;
497 }
498 
507 quint32 QWrk::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4)
508 {
509  quint32 value = (c1 << 24);
510  value += (c2 << 16);
511  value += (c3 << 8);
512  value += c4;
513  return value;
514 }
515 
520 quint16 QWrk::read16bit()
521 {
522  quint8 c1, c2;
523  c1 = readByte();
524  c2 = readByte();
525  return to16bit(c2, c1);
526 }
527 
532 quint32 QWrk::read24bit()
533 {
534  quint8 c1, c2, c3;
535  c1 = readByte();
536  c2 = readByte();
537  c3 = readByte();
538  return to32bit(0, c3, c2, c1);
539 }
540 
545 quint32 QWrk::read32bit()
546 {
547  quint8 c1, c2, c3, c4;
548  c1 = readByte();
549  c2 = readByte();
550  c3 = readByte();
551  c4 = readByte();
552  return to32bit(c4, c3, c2, c1);
553 }
554 
559 QString QWrk::readString(int len)
560 {
561  QString s;
562  if ( len > 0 ) {
563  quint8 c = 0xff;
564  QByteArray data;
565  for ( int i = 0; i < len && c != 0 && !atEnd(); ++i ) {
566  c = readByte();
567  if ( c != 0)
568  data += c;
569  }
570  if (d->m_codec == nullptr)
571  s = QString(data);
572  else
573  s = d->m_codec->toUnicode(data);
574  }
575  return s;
576 }
577 
582 QString QWrk::readVarString()
583 {
584  QString s;
585  QByteArray data;
586  quint8 b;
587  do {
588  b = readByte();
589  if (b != 0)
590  data += b;
591  } while (b != 0 && !atEnd());
592  if (d->m_codec == nullptr)
593  s = QString(data);
594  else
595  s = d->m_codec->toUnicode(data);
596  return s;
597 }
598 
604 {
605  return d->internalFilePos();
606 }
607 
612 void QWrk::seek(qint64 pos)
613 {
614  if (!d->m_IOStream->device()->seek(pos)) {
615  //qDebug() << Q_FUNC_INFO << "Error, pos:" << pos;
616  }
617 }
618 
623 bool QWrk::atEnd()
624 {
625  return d->m_IOStream->atEnd();
626 }
627 
632 void QWrk::readGap(int size)
633 {
634  if ( size > 0)
635  seek( d->internalFilePos() + size );
636 }
637 
642 void QWrk::readFromStream(QDataStream *stream)
643 {
644  d->m_IOStream = stream;
645  wrkRead();
646 }
647 
652 void QWrk::readFromFile(const QString& fileName)
653 {
654  QFile file(fileName);
655  file.open(QIODevice::ReadOnly);
656  QDataStream ds(&file);
657  readFromStream(&ds);
658  file.close();
659 }
660 
661 void QWrk::processTrackChunk()
662 {
663  int namelen;
664  QString name[2];
665  int trackno;
666  int channel;
667  int pitch;
668  int velocity;
669  int port;
670  bool selected;
671  bool muted;
672  bool loop;
673 
674  trackno = read16bit();
675  for(int i=0; i<2; ++i) {
676  namelen = readByte();
677  name[i] = readString(namelen);
678  }
679  channel = readByte() & 0x0f;
680  pitch = readByte();
681  velocity = readByte();
682  port = readByte();
683  quint8 flags = readByte();
684  selected = ((flags & 1) != 0);
685  muted = ((flags & 2) != 0);
686  loop = ((flags & 4) != 0);
687  Q_EMIT signalWRKTrack( name[0], name[1],
688  trackno, channel, pitch,
689  velocity, port, selected,
690  muted, loop );
691 }
692 
693 void QWrk::processVarsChunk()
694 {
695  d->m_Now = read32bit();
696  d->m_From = read32bit();
697  d->m_Thru = read32bit();
698  d->m_KeySig = readByte();
699  d->m_Clock = readByte();
700  d->m_AutoSave = readByte();
701  d->m_PlayDelay = readByte();
702  readGap(1);
703  d->m_ZeroCtrls = (readByte() != 0);
704  d->m_SendSPP = (readByte() != 0);
705  d->m_SendCont = (readByte() != 0);
706  d->m_PatchSearch = (readByte() != 0);
707  d->m_AutoStop = (readByte() != 0);
708  d->m_StopTime = read32bit();
709  d->m_AutoRewind = (readByte() != 0);
710  d->m_RewindTime = read32bit();
711  d->m_MetroPlay = (readByte() != 0);
712  d->m_MetroRecord = (readByte() != 0);
713  d->m_MetroAccent = (readByte() != 0);
714  d->m_CountIn = readByte();
715  readGap(2);
716  d->m_ThruOn = (readByte() != 0);
717  readGap(19);
718  d->m_AutoRestart = (readByte() != 0);
719  d->m_CurTempoOfs = readByte();
720  d->m_TempoOfs1 = readByte();
721  d->m_TempoOfs2 = readByte();
722  d->m_TempoOfs3 = readByte();
723  readGap(2);
724  d->m_PunchEnabled = (readByte() != 0);
725  d->m_PunchInTime = read32bit();
726  d->m_PunchOutTime = read32bit();
727  d->m_EndAllTime = read32bit();
728 
729  Q_EMIT signalWRKGlobalVars();
730 }
731 
732 void QWrk::processTimebaseChunk()
733 {
734  quint16 timebase = read16bit();
735  d->m_division = timebase;
736  Q_EMIT signalWRKTimeBase(timebase);
737 }
738 
739 void QWrk::processNoteArray(int track, int events)
740 {
741  quint32 time = 0;
742  quint8 status = 0, data1 = 0, data2 = 0, i = 0;
743  quint16 dur = 0;
744  int value = 0, type = 0, channel = 0, len = 0;
745  QString text;
746  QByteArray data;
747  for ( i = 0; (i < events) && (d->internalFilePos() < d->m_lastChunkPos) && !atEnd(); ++i ) {
748  time = read24bit();
749  status = readByte();
750  dur = 0;
751  if (status >= 0x90) {
752  type = status & 0xf0;
753  channel = status & 0x0f;
754  data1 = readByte();
755  if (type == 0x90 || type == 0xA0 || type == 0xB0 || type == 0xE0)
756  data2 = readByte();
757  if (type == 0x90)
758  dur = read16bit();
759  switch (type) {
760  case 0x90:
761  Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur);
762  break;
763  case 0xA0:
764  Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2);
765  break;
766  case 0xB0:
767  Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2);
768  break;
769  case 0xC0:
770  Q_EMIT signalWRKProgram(track, time, channel, data1);
771  break;
772  case 0xD0:
773  Q_EMIT signalWRKChanPress(track, time, channel, data1);
774  break;
775  case 0xE0:
776  value = (data2 << 7) + data1 - 8192;
777  Q_EMIT signalWRKPitchBend(track, time, channel, value);
778  break;
779  case 0xF0:
780  Q_EMIT signalWRKSysexEvent(track, time, data1);
781  break;
782  }
783  } else if (status == 5) {
784  int code = read16bit();
785  len = read32bit();
786  text = readString(len);
787  Q_EMIT signalWRKExpression(track, time, code, text);
788  } else if (status == 6) {
789  int code = read16bit();
790  dur = read16bit();
791  readGap(4);
792  Q_EMIT signalWRKHairpin(track, time, code, dur);
793  } else if (status == 7) {
794  len = read32bit();
795  text = readString(len);
796  data.clear();
797  for(int j=0; j<13; ++j) {
798  int byte = readByte();
799  data += byte;
800  }
801  Q_EMIT signalWRKChord(track, time, text, data);
802  } else if (status == 8) {
803  len = read16bit();
804  data.clear();
805  for(int j=0; j<len; ++j) {
806  int byte = readByte();
807  data += byte;
808  }
809  Q_EMIT signalWRKSysex(0, QString(), false, 0, data);
810  } else {
811  len = read32bit();
812  text = readString(len);
813  Q_EMIT signalWRKText(track, time, status, text);
814  }
815  }
816  if ((i < events) && atEnd()) {
817  Q_EMIT signalWRKError("Corrupted file");
818  }
819  Q_EMIT signalWRKStreamEnd(time + dur);
820 }
821 
822 void QWrk::processStreamChunk()
823 {
824  long time = 0;
825  int dur = 0, value = 0, type = 0, channel = 0, i = 0;
826  quint8 status = 0, data1 = 0, data2 = 0;
827  quint16 track = read16bit();
828  int events = read16bit();
829  for ( i = 0; (i < events) && (d->internalFilePos() < d->m_lastChunkPos) && !atEnd(); ++i ) {
830  time = read24bit();
831  status = readByte();
832  data1 = readByte();
833  data2 = readByte();
834  dur = read16bit();
835  type = status & 0xf0;
836  channel = status & 0x0f;
837  switch (type) {
838  case 0x90:
839  Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur);
840  break;
841  case 0xA0:
842  Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2);
843  break;
844  case 0xB0:
845  Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2);
846  break;
847  case 0xC0:
848  Q_EMIT signalWRKProgram(track, time, channel, data1);
849  break;
850  case 0xD0:
851  Q_EMIT signalWRKChanPress(track, time, channel, data1);
852  break;
853  case 0xE0:
854  value = (data2 << 7) + data1 - 8192;
855  Q_EMIT signalWRKPitchBend(track, time, channel, value);
856  break;
857  case 0xF0:
858  Q_EMIT signalWRKSysexEvent(track, time, data1);
859  break;
860  }
861  }
862  if ((i < events) && atEnd()) {
863  Q_EMIT signalWRKError("Corrupted file");
864  }
865  Q_EMIT signalWRKStreamEnd(time + dur);
866 }
867 
868 void QWrk::processMeterChunk()
869 {
870  int count = read16bit();
871  for (int i = 0; i < count; ++i) {
872  readGap(4);
873  int measure = read16bit();
874  int num = readByte();
875  int den = pow(2.0, readByte());
876  readGap(4);
877  Q_EMIT signalWRKTimeSig(measure, num, den);
878  }
879 }
880 
881 void QWrk::processMeterKeyChunk()
882 {
883  int count = read16bit();
884  for (int i = 0; i < count; ++i) {
885  int measure = read16bit();
886  int num = readByte();
887  int den = pow(2.0, readByte());
888  qint8 alt = readByte();
889  Q_EMIT signalWRKTimeSig(measure, num, den);
890  Q_EMIT signalWRKKeySig(measure, alt);
891  }
892 }
893 
894 double QWrk::getRealTime(long ticks) const
895 {
896  double division = 1.0 * d->m_division;
897  RecTempo last;
898  last.time = 0;
899  last.tempo = 100.0;
900  last.seconds = 0.0;
901  if (!d->m_tempos.isEmpty()) {
902  foreach(const RecTempo& rec, d->m_tempos) {
903  if (rec.time >= ticks)
904  break;
905  last = rec;
906  }
907  }
908  return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo));
909 }
910 
911 void QWrk::processTempoChunk(int factor)
912 {
913  double division = 1.0 * d->m_division;
914  int count = read16bit();
915  RecTempo last, next;
916  for (int i = 0; i < count; ++i) {
917 
918  long time = read32bit();
919  readGap(4);
920  long tempo = read16bit() * factor;
921  readGap(8);
922 
923  next.time = time;
924  next.tempo = tempo / 100.0;
925  next.seconds = 0.0;
926  last.time = 0;
927  last.tempo = next.tempo;
928  last.seconds = 0.0;
929  if (! d->m_tempos.isEmpty()) {
930  foreach(const RecTempo& rec, d->m_tempos) {
931  if (rec.time >= time)
932  break;
933  last = rec;
934  }
935  next.seconds = last.seconds +
936  (((time - last.time) / division) * (60.0 / last.tempo));
937  }
938  d->m_tempos.append(next);
939 
940  Q_EMIT signalWRKTempo(time, tempo);
941  }
942 }
943 
944 void QWrk::processSysexChunk()
945 {
946  int j;
947  QString name;
948  QByteArray data;
949  int bank = readByte();
950  int length = read16bit();
951  bool autosend = (readByte() != 0);
952  int namelen = readByte();
953  name = readString(namelen);
954  for(j=0; j<length; ++j) {
955  int byte = readByte();
956  data += byte;
957  }
958  Q_EMIT signalWRKSysex(bank, name, autosend, 0, data);
959 }
960 
961 void QWrk::processSysex2Chunk()
962 {
963  int j;
964  QString name;
965  QByteArray data;
966  int bank = read16bit();
967  int length = read32bit();
968  quint8 b = readByte();
969  int port = ( b & 0xf0 ) >> 4;
970  bool autosend = ( (b & 0x0f) != 0);
971  int namelen = readByte();
972  name = readString(namelen);
973  for(j=0; j<length; ++j) {
974  int byte = readByte();
975  data += byte;
976  }
977  Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
978 }
979 
980 void QWrk::processNewSysexChunk()
981 {
982  int j;
983  QString name;
984  QByteArray data;
985  int bank = read16bit();
986  int length = read32bit();
987  int port = read16bit();
988  bool autosend = (readByte() != 0);
989  int namelen = readByte();
990  name = readString(namelen);
991  for(j=0; j<length; ++j) {
992  int byte = readByte();
993  data += byte;
994  }
995  Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
996 }
997 
998 void QWrk::processThruChunk()
999 {
1000  readGap(2);
1001  qint8 port = readByte(); // 0->127
1002  qint8 channel = readByte(); // -1, 0->15
1003  qint8 keyPlus = readByte(); // 0->127
1004  qint8 velPlus = readByte(); // 0->127
1005  qint8 localPort = readByte();
1006  qint8 mode = readByte();
1007  Q_EMIT signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort);
1008 }
1009 
1010 void QWrk::processTrackOffset()
1011 {
1012  quint16 track = read16bit();
1013  qint16 offset = read16bit();
1014  Q_EMIT signalWRKTrackOffset(track, offset);
1015 }
1016 
1017 void QWrk::processTrackReps()
1018 {
1019  quint16 track = read16bit();
1020  quint16 reps = read16bit();
1021  Q_EMIT signalWRKTrackReps(track, reps);
1022 }
1023 
1024 void QWrk::processTrackPatch()
1025 {
1026  quint16 track = read16bit();
1027  qint8 patch = readByte();
1028  Q_EMIT signalWRKTrackPatch(track, patch);
1029 }
1030 
1031 void QWrk::processTimeFormat()
1032 {
1033  quint16 fmt = read16bit();
1034  quint16 ofs = read16bit();
1035  Q_EMIT signalWRKTimeFormat(fmt, ofs);
1036 }
1037 
1038 void QWrk::processComments()
1039 {
1040  int len = read16bit();
1041  QString text = readString(len);
1042  Q_EMIT signalWRKComments(text);
1043 }
1044 
1045 void QWrk::processVariableRecord(int max)
1046 {
1047  int datalen = max - 32;
1048  QByteArray data;
1049  QString name = readVarString();
1050  readGap(31 - name.length());
1051  for ( int i = 0; i < datalen; ++i )
1052  data += readByte();
1053  Q_EMIT signalWRKVariableRecord(name, data);
1054 }
1055 
1056 void QWrk::processUnknown(int id)
1057 {
1058  Q_EMIT signalWRKUnknownChunk(id, d->m_lastChunkData);
1059 }
1060 
1061 void QWrk::processNewTrack()
1062 {
1063  qint16 bank = -1;
1064  qint16 patch = -1;
1065  //qint16 vol = -1;
1066  //qint16 pan = -1;
1067  qint8 key = -1;
1068  qint8 vel = 0;
1069  quint8 port = 0;
1070  qint8 channel = 0;
1071  bool selected = false;
1072  bool muted = false;
1073  bool loop = false;
1074  quint16 track = read16bit();
1075  quint8 len = readByte();
1076  QString name = readString(len);
1077  bank = read16bit();
1078  patch = read16bit();
1079  /*vol =*/ read16bit();
1080  /*pan =*/ read16bit();
1081  key = readByte();
1082  vel = readByte();
1083  readGap(7);
1084  port = readByte();
1085  channel = readByte();
1086  muted = (readByte() != 0);
1087  Q_EMIT signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop);
1088  if (bank > -1)
1089  Q_EMIT signalWRKTrackBank(track, bank);
1090  if (patch > -1) {
1091  if (channel > -1)
1092  Q_EMIT signalWRKProgram(track, 0, channel, patch);
1093  else
1094  Q_EMIT signalWRKTrackPatch(track, patch);
1095  }
1096 }
1097 
1098 void QWrk::processSoftVer()
1099 {
1100  int len = readByte();
1101  QString vers = readString(len);
1102  Q_EMIT signalWRKSoftVer(vers);
1103 }
1104 
1105 void QWrk::processTrackName()
1106 {
1107  int track = read16bit();
1108  int len = readByte();
1109  QString name = readString(len);
1110  Q_EMIT signalWRKTrackName(track, name);
1111 }
1112 
1113 void QWrk::processStringTable()
1114 {
1115  QStringList table;
1116  int rows = read16bit();
1117  for (int i = 0; i < rows; ++i) {
1118  int len = readByte();
1119  QString name = readString(len);
1120  int idx = readByte();
1121  table.insert(idx, name);
1122  }
1123  Q_EMIT signalWRKStringTable(table);
1124 }
1125 
1126 void QWrk::processLyricsStream()
1127 {
1128  quint16 track = read16bit();
1129  int events = read32bit();
1130  processNoteArray(track, events);
1131 }
1132 
1133 void QWrk::processTrackVol()
1134 {
1135  quint16 track = read16bit();
1136  int vol = read16bit();
1137  Q_EMIT signalWRKTrackVol(track, vol);
1138 }
1139 
1140 void QWrk::processNewTrackOffset()
1141 {
1142  quint16 track = read16bit();
1143  int offset = read32bit();
1144  Q_EMIT signalWRKTrackOffset(track, offset);
1145 }
1146 
1147 void QWrk::processTrackBank()
1148 {
1149  quint16 track = read16bit();
1150  int bank = read16bit();
1151  Q_EMIT signalWRKTrackBank(track, bank);
1152 }
1153 
1154 void QWrk::processSegmentChunk()
1155 {
1156  QString name;
1157  int track = read16bit();
1158  int offset = read32bit();
1159  readGap(8);
1160  int len = readByte();
1161  name = readString(len);
1162  readGap(20);
1163  Q_EMIT signalWRKSegment(track, offset, name);
1164  int events = read32bit();
1165  processNoteArray(track, events);
1166 }
1167 
1168 void QWrk::processNewStream()
1169 {
1170  QString name;
1171  int track = read16bit();
1172  int len = readByte();
1173  name = readString(len);
1174  Q_EMIT signalWRKSegment(track, 0, name);
1175  int events = read32bit();
1176  processNoteArray(track, events);
1177 }
1178 
1179 void QWrk::processEndChunk()
1180 {
1181  emit signalWRKEnd();
1182 }
1183 
1184 int QWrk::readChunk()
1185 {
1186  qint64 start_pos = d->internalFilePos();
1187  int ck = readByte();
1188  if (ck != END_CHUNK) {
1189  quint32 ck_len = read32bit();
1190  if (ck_len > d->m_IOStream->device()->bytesAvailable()) {
1191  Q_EMIT signalWRKError("Corrupted file");
1192  seek(start_pos);
1193  return END_CHUNK;
1194  }
1195  start_pos = d->internalFilePos();
1196  d->m_lastChunkPos = start_pos + ck_len;
1197  readRawData(ck_len);
1198  seek(start_pos);
1199  switch (ck) {
1200  case TRACK_CHUNK:
1201  processTrackChunk();
1202  break;
1203  case VARS_CHUNK:
1204  processVarsChunk();
1205  break;
1206  case TIMEBASE_CHUNK:
1207  processTimebaseChunk();
1208  break;
1209  case STREAM_CHUNK:
1210  processStreamChunk();
1211  break;
1212  case METER_CHUNK:
1213  processMeterChunk();
1214  break;
1215  case TEMPO_CHUNK:
1216  processTempoChunk(100);
1217  break;
1218  case NTEMPO_CHUNK:
1219  processTempoChunk();
1220  break;
1221  case SYSEX_CHUNK:
1222  processSysexChunk();
1223  break;
1224  case THRU_CHUNK:
1225  processThruChunk();
1226  break;
1227  case TRKOFFS_CHUNK:
1228  processTrackOffset();
1229  break;
1230  case TRKREPS_CHUNK:
1231  processTrackReps();
1232  break;
1233  case TRKPATCH_CHUNK:
1234  processTrackPatch();
1235  break;
1236  case TIMEFMT_CHUNK:
1237  processTimeFormat();
1238  break;
1239  case COMMENTS_CHUNK:
1240  processComments();
1241  break;
1242  case VARIABLE_CHUNK:
1243  processVariableRecord(ck_len);
1244  break;
1245  case NTRACK_CHUNK:
1246  processNewTrack();
1247  break;
1248  case SOFTVER_CHUNK:
1249  processSoftVer();
1250  break;
1251  case TRKNAME_CHUNK:
1252  processTrackName();
1253  break;
1254  case STRTAB_CHUNK:
1255  processStringTable();
1256  break;
1257  case LYRICS_CHUNK:
1258  processLyricsStream();
1259  break;
1260  case TRKVOL_CHUNK:
1261  processTrackVol();
1262  break;
1263  case NTRKOFS_CHUNK:
1264  processNewTrackOffset();
1265  break;
1266  case TRKBANK_CHUNK:
1267  processTrackBank();
1268  break;
1269  case METERKEY_CHUNK:
1270  processMeterKeyChunk();
1271  break;
1272  case SYSEX2_CHUNK:
1273  processSysex2Chunk();
1274  break;
1275  case NSYSEX_CHUNK:
1276  processNewSysexChunk();
1277  break;
1278  case SGMNT_CHUNK:
1279  processSegmentChunk();
1280  break;
1281  case NSTREAM_CHUNK:
1282  processNewStream();
1283  break;
1284  default:
1285  processUnknown(ck);
1286  }
1287  if (d->internalFilePos() != d->m_lastChunkPos) {
1288  //qDebug() << Q_FUNC_INFO << "Current pos:" << d->internalFilePos() << "should be:" << d->m_lastChunkPos;
1289  seek(d->m_lastChunkPos);
1290  }
1291  }
1292  return ck;
1293 }
1294 
1295 void QWrk::wrkRead()
1296 {
1297  QByteArray hdr(HEADER.length(), ' ');
1298  d->m_tempos.clear();
1299  d->m_IOStream->device()->read(hdr.data(), HEADER.length());
1300  if (hdr == HEADER) {
1301  int vma, vme;
1302  int ck_id;
1303  readGap(1);
1304  vme = readByte();
1305  vma = readByte();
1306  Q_EMIT signalWRKHeader(vma, vme);
1307  do {
1308  ck_id = readChunk();
1309  } while ((ck_id != END_CHUNK) && !atEnd());
1310  if (!atEnd()) {
1311  //qDebug() << Q_FUNC_INFO << "extra junk past the end at" << d->internalFilePos();
1312  readRawData(d->m_IOStream->device()->bytesAvailable());
1313  processUnknown(ck_id);
1314  }
1315  processEndChunk();
1316  } else
1317  Q_EMIT signalWRKError("Invalid file format");
1318 }
1319 
1320 qint64 QWrk::QWrkPrivate::internalFilePos()
1321 {
1322  return m_IOStream->device()->pos();
1323 }
1324 
1325 const QByteArray QWrk::HEADER = QByteArrayLiteral("CAKEWALK");
1326 
1327 } // namespace File
1328 } // 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:331
bool getPunchEnabled() const
Auto-Punch enabled?
Definition: qwrk.cpp:442
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:313
bool getZeroCtrls() const
Zero continuous controllers?
Definition: qwrk.cpp:250
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:129
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:155
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:232
long getFilePos()
Current position in the data stream.
Definition: qwrk.cpp:603
bool getThruOn() const
MIDI Thru enabled? (only used if no THRU rec)
Definition: qwrk.cpp:358
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:187
int getPunchOutTime() const
Punch-out time.
Definition: qwrk.cpp:460
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:286
int getEndAllTime() const
Time of latest event (incl.
Definition: qwrk.cpp:469
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:241
bool getSendSPP() const
Send Song Position Pointer?
Definition: qwrk.cpp:259
void signalWRKError(const QString &errorStr)
Emitted for a WRK file read error.
virtual ~QWrk()
Destructor.
Definition: qwrk.cpp:137
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:433
int getThru() const
Thru marker time.
Definition: qwrk.cpp:205
bool getSendCont() const
Send MIDI Continue?
Definition: qwrk.cpp:268
int getTempoOfs2() const
Fixed-point ratio value of tempo offset 2.
Definition: qwrk.cpp:414
bool getPatchSearch() const
Patch/controller search-back?
Definition: qwrk.cpp:277
void readFromStream(QDataStream *stream)
Reads a stream.
Definition: qwrk.cpp:642
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:451
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:295
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:165
bool getAutoRewind() const
Auto-rewind?
Definition: qwrk.cpp:304
bool getMetroPlay() const
Metronome on during playback?
Definition: qwrk.cpp:322
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
Definition: qwrk.cpp:144
int getFrom() const
From marker time.
Definition: qwrk.cpp:196
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:652
int getCountIn() const
Measures of count-in (0=no count-in)
Definition: qwrk.cpp:349
int getCurTempoOfs() const
Which of the 3 tempo offsets is used: 0..2.
Definition: qwrk.cpp:376
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:367
int getClock() const
Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE)
Definition: qwrk.cpp:223
int getKeySig() const
Key signature (0=C, 1=C#, ...
Definition: qwrk.cpp:214
bool getMetroAccent() const
Metronome accents primary beats?
Definition: qwrk.cpp:340
int getTempoOfs1() const
Fixed-point ratio value of tempo offset 1.
Definition: qwrk.cpp:395
@ 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 common.
Definition: alsaclient.cpp:68
Cakewalk WRK Files Input.