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
New Tempo map.
Definition: qwrk.h:53
const QByteArray HEADER("CAKEWALK")
Cakewalk WRK File header id.
Track volume.
Definition: qwrk.h:56
bool getSendCont() const
Send MIDI Continue?
Definition: qwrk.cpp:260
int getPunchOutTime() const
Punch-out time.
Definition: qwrk.cpp:452
Extended thru parameters.
Definition: qwrk.h:54
void signalWRKTrackOffset(int track, int offset)
Emitted after reading a track offset chunk.
void signalWRKError(const QString &errorStr)
Emitted for a WRK file read error.
void signalWRKStringTable(const QStringList &strs)
Emitted after reading a string event types chunk.
void signalWRKText(int track, long time, int type, const QString &data)
Emitted after reading a text message.
Track patch.
Definition: qwrk.h:52
int getEndAllTime() const
Time of latest event (incl.
Definition: qwrk.cpp:461
void signalWRKSegment(int track, long time, const QString &name)
Emitted after reading a segment prefix chunk.
int getPunchInTime() const
Punch-in time.
Definition: qwrk.cpp:443
void signalWRKStreamEnd(long time)
Emitted after reading the last event of a event stream.
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:642
void setTextCodec(QTextCodec *codec)
Sets the text codec for text meta-events.
Definition: qwrk.cpp:152
int getPlayDelay() const
Play Delay.
Definition: qwrk.cpp:233
int getClock() const
Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE)
Definition: qwrk.cpp:215
void signalWRKHairpin(int track, long time, int code, int dur)
Emitted after reading a hairpin symbol (notation) chunk.
void signalWRKHeader(int verh, int verl)
Emitted after reading a WRK header.
void signalWRKTrackVol(int track, int vol)
Emitted after reading a track volume chunk.
int getFrom() const
From marker time.
Definition: qwrk.cpp:188
bool getAutoStop() const
Auto-stop?
Definition: qwrk.cpp:278
void signalWRKTrackName(int track, const QString &name)
Emitted after reading a track name chunk.
System exclusive bank.
Definition: qwrk.h:57
The QObject class is the base class of all Qt objects.
int getCountIn() const
Measures of count-in (0=no count-in)
Definition: qwrk.cpp:341
QByteArray getLastChunkRawData() const
Gets the last chunk raw data (undecoded)
Definition: qwrk.cpp:162
bool getAutoRestart() const
Auto-restart?
Definition: qwrk.cpp:359
Events stream.
Definition: qwrk.h:41
Global variables.
Definition: qwrk.h:42
int getThru() const
Thru marker time.
Definition: qwrk.cpp:197
void signalWRKTrackPatch(int track, int patch)
Emitted after reading a track patch chunk.
Tempo map.
Definition: qwrk.h:43
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.
Track name.
Definition: qwrk.h:60
void signalWRKGlobalVars()
Emitted after reading the global variables chunk.
void signalWRKChord(int track, long time, const QString &name, const QByteArray &data)
Emitted after reading a chord diagram chunk.
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.
Cakewalk WRK Files Input.
int getAutoSave() const
Auto save (0=disabled, 1..256=minutes)
Definition: qwrk.cpp:224
unsigned int getStopTime() const
Auto-stop time.
Definition: qwrk.cpp:287
bool getMetroAccent() const
Metronome accents primary beats?
Definition: qwrk.cpp:332
bool getSendSPP() const
Send Song Position Pointer?
Definition: qwrk.cpp:251
void signalWRKKeySig(int bar, int alt)
Emitted after reading a WRK Key Signature.
void signalWRKThru(int mode, int port, int channel, int keyPlus, int velPlus, int localPort)
Emitted after reading an Extended Thru parameters chunk.
bool getZeroCtrls() const
Zero continuous controllers?
Definition: qwrk.cpp:242
void signalWRKCtlChange(int track, long time, int chan, int ctl, int value)
Emitted after reading a Control Change message.
void signalWRKChanPress(int track, long time, int chan, int press)
Emitted after reading a Channel Aftertouch message.
long getFilePos()
Current position in the data stream.
Definition: qwrk.cpp:595
bool getMetroPlay() const
Metronome on during playback?
Definition: qwrk.cpp:314
bool getThruOn() const
MIDI Thru enabled? (only used if no THRU rec)
Definition: qwrk.cpp:350
int getTempoOfs3() const
Fixed-point ratio value of tempo offset 3.
Definition: qwrk.cpp:425
void signalWRKExpression(int track, long time, int code, const QString &text)
Emitted after reading an expression indication (notation) chunk.
void signalWRKVariableRecord(const QString &name, const QByteArray &data)
Emitted after reading a variable chunk.
SMPTE time format.
Definition: qwrk.h:50
Track offset.
Definition: qwrk.h:48
void signalWRKEnd()
Emitted after reading the last chunk of a WRK file.
System exclusive bank.
Definition: qwrk.h:65
Track prefix.
Definition: qwrk.h:64
Variable record chunk.
Definition: qwrk.h:61
bool getMetroRecord() const
Metronome on during recording?
Definition: qwrk.cpp:323
int getRewindTime() const
Auto-rewind time.
Definition: qwrk.cpp:305
QTextCodec * getTextCodec()
Gets the text codec used for text meta-events I/O.
Definition: qwrk.cpp:141
System exclusive bank.
Definition: qwrk.h:45
Events stream with lyrics.
Definition: qwrk.h:55
void signalWRKTimeBase(int timebase)
Emitted after reading the timebase chunk.
Meter/Key map.
Definition: qwrk.h:59
Track repetitions.
Definition: qwrk.h:51
void signalWRKUnknownChunk(int type, const QByteArray &data)
Emitted after reading an unknown 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.
virtual ~QWrk()
Destructor.
Definition: qwrk.cpp:132
bool getPatchSearch() const
Patch/controller search-back?
Definition: qwrk.cpp:269
void signalWRKTrackReps(int track, int reps)
Emitted after reading a track offset chunk.
Track bank.
Definition: qwrk.h:63
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 signalWRKTempo(long time, int tempo)
Emitted after reading a Tempo Change message.
Table of text event types.
Definition: qwrk.h:58
bool getPunchEnabled() const
Auto-Punch enabled?
Definition: qwrk.cpp:434
void signalWRKSysexEvent(int track, long time, int bank)
Emitted after reading a System Exclusive event.
void readFromStream(QDataStream *stream)
Reads a stream.
Definition: qwrk.cpp:632
int getKeySig() const
Key signature (0=C, 1=C#, ...
Definition: qwrk.cpp:206
Meter map.
Definition: qwrk.h:44
int getCurTempoOfs() const
Which of the 3 tempo offsets is used: 0..2.
Definition: qwrk.cpp:368
bool getAutoRewind() const
Auto-rewind?
Definition: qwrk.cpp:296
Segment prefix.
Definition: qwrk.h:67
void signalWRKSoftVer(const QString &version)
Emitted after reading a software version chunk.
QWrk(QObject *parent=0)
Constructor.
Definition: qwrk.cpp:124
void signalWRKPitchBend(int track, long time, int chan, int value)
Emitted after reading a Bender message.
void signalWRKTimeSig(int bar, int num, int den)
Emitted after reading a WRK Time signature.
void signalWRKProgram(int track, long time, int chan, int patch)
Emitted after reading a Program change message.
Software version which saved the file.
Definition: qwrk.h:68
void signalWRKTrackBank(int track, int bank)
Emitted after reading a track bank chunk.
Timebase. If present is the first chunk in the file.
Definition: qwrk.h:49
Events stream.
Definition: qwrk.h:66
Track prefix.
Definition: qwrk.h:40
int getTempoOfs2() const
Fixed-point ratio value of tempo offset 2.
Definition: qwrk.cpp:406
int getNow() const
Now marker time.
Definition: qwrk.cpp:179
Track offset.
Definition: qwrk.h:62
int getTempoOfs1() const
Fixed-point ratio value of tempo offset 1.
Definition: qwrk.cpp:387