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