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 
33 namespace drumstick { namespace File {
34 
47 class QWrk::QWrkPrivate {
48 public:
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 
125 QWrk::QWrk(QObject * parent) :
126  QObject(parent),
127  d(new QWrkPrivate)
128 { }
129 
134 { }
135 
140 QTextCodec* QWrk::getTextCodec()
141 {
142  return d->m_codec;
143 }
144 
151 void QWrk::setTextCodec(QTextCodec *codec)
152 {
153  d->m_codec = codec;
154 }
155 
161 QByteArray QWrk::getLastChunkRawData() const
162 {
163  return d->m_lastChunkData;
164 }
165 
169 void QWrk::readRawData(int size)
170 {
171  d->m_lastChunkData = d->m_IOStream->device()->read(size);
172 }
173 
178 int QWrk::getNow() const
179 {
180  return d->m_Now;
181 }
182 
187 int QWrk::getFrom() const
188 {
189  return d->m_From;
190 }
191 
196 int QWrk::getThru() const
197 {
198  return d->m_Thru;
199 }
200 
205 int QWrk::getKeySig() const
206 {
207  return d->m_KeySig;
208 }
209 
214 int QWrk::getClock() const
215 {
216  return d->m_Clock;
217 }
218 
223 int QWrk::getAutoSave() const
224 {
225  return d->m_AutoSave;
226 }
227 
233 {
234  return d->m_PlayDelay;
235 }
236 
241 bool QWrk::getZeroCtrls() const
242 {
243  return d->m_ZeroCtrls;
244 }
245 
250 bool QWrk::getSendSPP() const
251 {
252  return d->m_SendSPP;
253 }
254 
259 bool QWrk::getSendCont() const
260 {
261  return d->m_SendCont;
262 }
263 
269 {
270  return d->m_PatchSearch;
271 }
272 
277 bool QWrk::getAutoStop() const
278 {
279  return d->m_AutoStop;
280 }
281 
286 unsigned 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 
313 bool QWrk::getMetroPlay() const
314 {
315  return d->m_MetroPlay;
316 }
317 
323 {
324  return d->m_MetroRecord;
325 }
326 
332 {
333  return d->m_MetroAccent;
334 }
335 
340 int QWrk::getCountIn() const
341 {
342  return d->m_CountIn;
343 }
344 
349 bool 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 
469 quint8 QWrk::readByte()
470 {
471  quint8 b = 0xff;
472  if (!d->m_IOStream->atEnd())
473  *d->m_IOStream >> b;
474  return b;
475 }
476 
483 quint16 QWrk::to16bit(quint8 c1, quint8 c2)
484 {
485  quint16 value = (c1 << 8);
486  value += c2;
487  return value;
488 }
489 
498 quint32 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 
511 quint16 QWrk::read16bit()
512 {
513  quint8 c1, c2;
514  c1 = readByte();
515  c2 = readByte();
516  return to16bit(c2, c1);
517 }
518 
523 quint32 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 
536 quint32 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 
550 QString 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 
573 QString 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 
603 void QWrk::seek(qint64 pos)
604 {
605  d->m_IOStream->device()->seek(pos);
606 }
607 
612 bool QWrk::atEnd()
613 {
614  return d->m_IOStream->atEnd();
615 }
616 
621 void QWrk::readGap(int size)
622 {
623  if ( size > 0)
624  seek( getFilePos() + size );
625 }
626 
631 void QWrk::readFromStream(QDataStream *stream)
632 {
633  d->m_IOStream = stream;
634  wrkRead();
635 }
636 
641 void 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 
650 void 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 
682 void 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 
721 void QWrk::processTimebaseChunk()
722 {
723  quint16 timebase = read16bit();
724  d->m_division = timebase;
725  Q_EMIT signalWRKTimeBase(timebase);
726 }
727 
728 void 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 
811 void 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 
857 void 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 
870 void 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 
883 double 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 
900 void 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 
933 void 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 
950 void 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 
969 void 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 
987 void 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 
999 void QWrk::processTrackOffset()
1000 {
1001  quint16 track = read16bit();
1002  qint16 offset = read16bit();
1003  Q_EMIT signalWRKTrackOffset(track, offset);
1004 }
1005 
1006 void QWrk::processTrackReps()
1007 {
1008  quint16 track = read16bit();
1009  quint16 reps = read16bit();
1010  Q_EMIT signalWRKTrackReps(track, reps);
1011 }
1012 
1013 void QWrk::processTrackPatch()
1014 {
1015  quint16 track = read16bit();
1016  qint8 patch = readByte();
1017  Q_EMIT signalWRKTrackPatch(track, patch);
1018 }
1019 
1020 void QWrk::processTimeFormat()
1021 {
1022  quint16 fmt = read16bit();
1023  quint16 ofs = read16bit();
1024  Q_EMIT signalWRKTimeFormat(fmt, ofs);
1025 }
1026 
1027 void QWrk::processComments()
1028 {
1029  int len = read16bit();
1030  QString text = readString(len);
1031  Q_EMIT signalWRKComments(text);
1032 }
1033 
1034 void 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 
1045 void QWrk::processUnknown(int id)
1046 {
1047  Q_EMIT signalWRKUnknownChunk(id, d->m_lastChunkData);
1048 }
1049 
1050 void 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 
1087 void QWrk::processSoftVer()
1088 {
1089  int len = readByte();
1090  QString vers = readString(len);
1091  Q_EMIT signalWRKSoftVer(vers);
1092 }
1093 
1094 void QWrk::processTrackName()
1095 {
1096  int track = read16bit();
1097  int len = readByte();
1098  QString name = readString(len);
1099  Q_EMIT signalWRKTrackName(track, name);
1100 }
1101 
1102 void 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 
1115 void QWrk::processLyricsStream()
1116 {
1117  quint16 track = read16bit();
1118  int events = read32bit();
1119  processNoteArray(track, events);
1120 }
1121 
1122 void QWrk::processTrackVol()
1123 {
1124  quint16 track = read16bit();
1125  int vol = read16bit();
1126  Q_EMIT signalWRKTrackVol(track, vol);
1127 }
1128 
1129 void QWrk::processNewTrackOffset()
1130 {
1131  quint16 track = read16bit();
1132  int offset = read32bit();
1133  Q_EMIT signalWRKTrackOffset(track, offset);
1134 }
1135 
1136 void QWrk::processTrackBank()
1137 {
1138  quint16 track = read16bit();
1139  int bank = read16bit();
1140  Q_EMIT signalWRKTrackBank(track, bank);
1141 }
1142 
1143 void 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 
1157 void 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 
1168 void QWrk::processEndChunk()
1169 {
1170  emit signalWRKEnd();
1171 }
1172 
1173 int 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 
1276 void 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 
1299 const QByteArray QWrk::HEADER = QByteArrayLiteral("CAKEWALK");
1300 
1301 } // namespace File
1302 } // namespace drumstick
void signalWRKVariableRecord(const QString &name, const QByteArray &data)
Emitted after reading a variable chunk.
void signalWRKTrackReps(int track, int reps)
Emitted after reading a track offset chunk.
Events stream.
Definition: qwrk.h:44
void setTextCodec(QTextCodec *codec)
Sets the text codec for text meta-events.
Definition: qwrk.cpp:151
int getEndAllTime() const
Time of latest event (incl.
Definition: qwrk.cpp:460
void signalWRKTrackName(int track, const QString &name)
Emitted after reading a track name chunk.
int getClock() const
Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE)
Definition: qwrk.cpp:214
void signalWRKChord(int track, long time, const QString &name, const QByteArray &data)
Emitted after reading a chord diagram chunk.
void signalWRKGlobalVars()
Emitted after reading the global variables chunk.
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
Definition: qwrk.cpp:140
bool getMetroAccent() const
Metronome accents primary beats?
Definition: qwrk.cpp:331
void signalWRKSysex(int bank, const QString &name, bool autosend, int port, const QByteArray &data)
Emitted after reading a System Exclusive Bank.
int getTempoOfs1() const
Fixed-point ratio value of tempo offset 1.
Definition: qwrk.cpp:386
long getFilePos()
Current position in the data stream.
Definition: qwrk.cpp:594
int getKeySig() const
Key signature (0=C, 1=C#, ...
Definition: qwrk.cpp:205
void signalWRKExpression(int track, long time, int code, const QString &text)
Emitted after reading an expression indication (notation) chunk.
System exclusive bank.
Definition: qwrk.h:68
int getFrom() const
From marker time.
Definition: qwrk.cpp:187
void signalWRKTimeFormat(int frames, int offset)
Emitted after reading a SMPTE time format chunk.
Track repetitions.
Definition: qwrk.h:54
void signalWRKKeyPress(int track, long time, int chan, int pitch, int press)
Emitted after reading a Polyphonic Aftertouch message.
void signalWRKComments(const QString &data)
Emitted after reading a comments chunk.
void signalWRKThru(int mode, int port, int channel, int keyPlus, int velPlus, int localPort)
Emitted after reading an Extended Thru parameters chunk.
Track prefix.
Definition: qwrk.h:43
void signalWRKStreamEnd(long time)
Emitted after reading the last event of a event stream.
Meter/Key map.
Definition: qwrk.h:62
QByteArray getLastChunkRawData() const
Gets the last chunk raw data (undecoded)
Definition: qwrk.cpp:161
int getPunchOutTime() const
Punch-out time.
Definition: qwrk.cpp:451
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.
void signalWRKStringTable(const QStringList &strs)
Emitted after reading a string event types chunk.
static const QByteArray HEADER
Cakewalk WRK file format header string id.
Definition: qwrk.h:131
void signalWRKKeySig(int bar, int alt)
Emitted after reading a WRK Key Signature.
Track prefix.
Definition: qwrk.h:67
bool getMetroPlay() const
Metronome on during playback?
Definition: qwrk.cpp:313
void signalWRKUnknownChunk(int type, const QByteArray &data)
Emitted after reading an unknown chunk.
The QObject class is the base class of all Qt objects.
Events stream.
Definition: qwrk.h:69
void signalWRKTimeSig(int bar, int num, int den)
Emitted after reading a WRK Time signature.
Track offset.
Definition: qwrk.h:65
bool getThruOn() const
MIDI Thru enabled? (only used if no THRU rec)
Definition: qwrk.cpp:349
int getTempoOfs3() const
Fixed-point ratio value of tempo offset 3.
Definition: qwrk.cpp:424
void signalWRKSysexEvent(int track, long time, int bank)
Emitted after reading a System Exclusive event.
int getThru() const
Thru marker time.
Definition: qwrk.cpp:196
SMPTE time format.
Definition: qwrk.h:53
System exclusive bank.
Definition: qwrk.h:60
void signalWRKCtlChange(int track, long time, int chan, int ctl, int value)
Emitted after reading a Control Change message.
System exclusive bank.
Definition: qwrk.h:48
Timebase. If present is the first chunk in the file.
Definition: qwrk.h:52
int getAutoSave() const
Auto save (0=disabled, 1..256=minutes)
Definition: qwrk.cpp:223
Drumstick common.
Definition: alsaclient.cpp:68
Global variables.
Definition: qwrk.h:45
void signalWRKTrackVol(int track, int vol)
Emitted after reading a track volume chunk.
Cakewalk WRK Files Input.
bool getZeroCtrls() const
Zero continuous controllers?
Definition: qwrk.cpp:241
QWrk(QObject *parent=nullptr)
Constructor.
Definition: qwrk.cpp:125
void signalWRKHeader(int verh, int verl)
Emitted after reading a WRK header.
void readFromStream(QDataStream *stream)
Reads a stream.
Definition: qwrk.cpp:631
Events stream with lyrics.
Definition: qwrk.h:58
New Tempo map.
Definition: qwrk.h:56
Software version which saved the file.
Definition: qwrk.h:71
void signalWRKSegment(int track, long time, const QString &name)
Emitted after reading a segment prefix chunk.
bool getAutoRestart() const
Auto-restart?
Definition: qwrk.cpp:358
Track offset.
Definition: qwrk.h:51
void signalWRKPitchBend(int track, long time, int chan, int value)
Emitted after reading a Bender message.
Track volume.
Definition: qwrk.h:59
bool getSendSPP() const
Send Song Position Pointer?
Definition: qwrk.cpp:250
Last chunk, end of file.
Definition: qwrk.h:72
bool getAutoRewind() const
Auto-rewind?
Definition: qwrk.cpp:295
void signalWRKChanPress(int track, long time, int chan, int press)
Emitted after reading a Channel Aftertouch message.
int getCountIn() const
Measures of count-in (0=no count-in)
Definition: qwrk.cpp:340
void signalWRKTrackPatch(int track, int patch)
Emitted after reading a track patch chunk.
bool getSendCont() const
Send MIDI Continue?
Definition: qwrk.cpp:259
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.
bool getPunchEnabled() const
Auto-Punch enabled?
Definition: qwrk.cpp:433
void signalWRKTrackBank(int track, int bank)
Emitted after reading a track bank chunk.
void signalWRKSoftVer(const QString &version)
Emitted after reading a software version chunk.
bool getMetroRecord() const
Metronome on during recording?
Definition: qwrk.cpp:322
void signalWRKNote(int track, long time, int chan, int pitch, int vol, int dur)
Emitted after reading a Note message.
void readFromFile(const QString &fileName)
Reads a stream from a disk file.
Definition: qwrk.cpp:641
int getCurTempoOfs() const
Which of the 3 tempo offsets is used: 0..2.
Definition: qwrk.cpp:367
int getNow() const
Now marker time.
Definition: qwrk.cpp:178
bool getAutoStop() const
Auto-stop?
Definition: qwrk.cpp:277
void signalWRKError(const QString &errorStr)
Emitted for a WRK file read error.
void signalWRKEnd()
Emitted after reading the last chunk of a WRK file.
int getRewindTime() const
Auto-rewind time.
Definition: qwrk.cpp:304
void signalWRKText(int track, long time, int type, const QString &data)
Emitted after reading a text message.
void signalWRKTrackOffset(int track, int offset)
Emitted after reading a track offset chunk.
unsigned int getStopTime() const
Auto-stop time.
Definition: qwrk.cpp:286
Table of text event types.
Definition: qwrk.h:61
Segment prefix.
Definition: qwrk.h:70
Extended thru parameters.
Definition: qwrk.h:57
int getPunchInTime() const
Punch-in time.
Definition: qwrk.cpp:442
Variable record chunk.
Definition: qwrk.h:64
void signalWRKHairpin(int track, long time, int code, int dur)
Emitted after reading a hairpin symbol (notation) chunk.
void signalWRKProgram(int track, long time, int chan, int patch)
Emitted after reading a Program change message.
virtual ~QWrk()
Destructor.
Definition: qwrk.cpp:133
int getPlayDelay() const
Play Delay.
Definition: qwrk.cpp:232
void signalWRKTimeBase(int timebase)
Emitted after reading the timebase chunk.
int getTempoOfs2() const
Fixed-point ratio value of tempo offset 2.
Definition: qwrk.cpp:405
void signalWRKTempo(long time, int tempo)
Emitted after reading a Tempo Change message.
bool getPatchSearch() const
Patch/controller search-back?
Definition: qwrk.cpp:268