drumstick  1.1.1
qwrk.cpp
Go to the documentation of this file.
1 /*
2  WRK File component
3  Copyright (C) 2010-2018, 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 "qwrk.h"
20 #include <cmath>
21 #include <QDataStream>
22 #include <QFile>
23 #include <QIODevice>
24 #include <QTextStream>
25 #include <QTextCodec>
26 #include <QStringList>
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; ++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);
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;
733  quint16 dur = 0;
734  int value = 0, type = 0, channel = 0, len = 0;
735  QString text;
736  QByteArray data;
737  for ( int i = 0; i < events; ++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  Q_EMIT signalWRKStreamEnd(time + dur);
807 }
808 
809 void QWrk::processStreamChunk()
810 {
811  long time = 0;
812  int dur = 0, value = 0, type = 0, channel = 0;
813  quint8 status = 0, data1 = 0, data2 = 0;
814  quint16 track = read16bit();
815  int events = read16bit();
816  for ( int i = 0; i < events; ++i ) {
817  time = read24bit();
818  status = readByte();
819  data1 = readByte();
820  data2 = readByte();
821  dur = read16bit();
822  type = status & 0xf0;
823  channel = status & 0x0f;
824  switch (type) {
825  case 0x90:
826  Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur);
827  break;
828  case 0xA0:
829  Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2);
830  break;
831  case 0xB0:
832  Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2);
833  break;
834  case 0xC0:
835  Q_EMIT signalWRKProgram(track, time, channel, data1);
836  break;
837  case 0xD0:
838  Q_EMIT signalWRKChanPress(track, time, channel, data1);
839  break;
840  case 0xE0:
841  value = (data2 << 7) + data1 - 8192;
842  Q_EMIT signalWRKPitchBend(track, time, channel, value);
843  break;
844  case 0xF0:
845  Q_EMIT signalWRKSysexEvent(track, time, data1);
846  break;
847  }
848  }
849  Q_EMIT signalWRKStreamEnd(time + dur);
850 }
851 
852 void QWrk::processMeterChunk()
853 {
854  int count = read16bit();
855  for (int i = 0; i < count; ++i) {
856  readGap(4);
857  int measure = read16bit();
858  int num = readByte();
859  int den = pow(2.0, readByte());
860  readGap(4);
861  Q_EMIT signalWRKTimeSig(measure, num, den);
862  }
863 }
864 
865 void QWrk::processMeterKeyChunk()
866 {
867  int count = read16bit();
868  for (int i = 0; i < count; ++i) {
869  int measure = read16bit();
870  int num = readByte();
871  int den = pow(2.0, readByte());
872  qint8 alt = readByte();
873  Q_EMIT signalWRKTimeSig(measure, num, den);
874  Q_EMIT signalWRKKeySig(measure, alt);
875  }
876 }
877 
878 double QWrk::getRealTime(long ticks) const
879 {
880  double division = 1.0 * d->m_division;
881  RecTempo last;
882  last.time = 0;
883  last.tempo = 100.0;
884  last.seconds = 0.0;
885  if (!d->m_tempos.isEmpty()) {
886  foreach(const RecTempo& rec, d->m_tempos) {
887  if (rec.time >= ticks)
888  break;
889  last = rec;
890  }
891  }
892  return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo));
893 }
894 
895 void QWrk::processTempoChunk(int factor)
896 {
897  double division = 1.0 * d->m_division;
898  int count = read16bit();
899  RecTempo last, next;
900  for (int i = 0; i < count; ++i) {
901 
902  long time = read32bit();
903  readGap(4);
904  long tempo = read16bit() * factor;
905  readGap(8);
906 
907  next.time = time;
908  next.tempo = tempo / 100.0;
909  next.seconds = 0.0;
910  last.time = 0;
911  last.tempo = next.tempo;
912  last.seconds = 0.0;
913  if (! d->m_tempos.isEmpty()) {
914  foreach(const RecTempo& rec, d->m_tempos) {
915  if (rec.time >= time)
916  break;
917  last = rec;
918  }
919  next.seconds = last.seconds +
920  (((time - last.time) / division) * (60.0 / last.tempo));
921  }
922  d->m_tempos.append(next);
923 
924  Q_EMIT signalWRKTempo(time, tempo);
925  }
926 }
927 
928 void QWrk::processSysexChunk()
929 {
930  int j;
931  QString name;
932  QByteArray data;
933  int bank = readByte();
934  int length = read16bit();
935  bool autosend = (readByte() != 0);
936  int namelen = readByte();
937  name = readString(namelen);
938  for(j=0; j<length; ++j) {
939  int byte = readByte();
940  data += byte;
941  }
942  Q_EMIT signalWRKSysex(bank, name, autosend, 0, data);
943 }
944 
945 void QWrk::processSysex2Chunk()
946 {
947  int j;
948  QString name;
949  QByteArray data;
950  int bank = read16bit();
951  int length = read32bit();
952  quint8 b = readByte();
953  int port = ( b & 0xf0 ) >> 4;
954  bool autosend = ( (b & 0x0f) != 0);
955  int namelen = readByte();
956  name = readString(namelen);
957  for(j=0; j<length; ++j) {
958  int byte = readByte();
959  data += byte;
960  }
961  Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
962 }
963 
964 void QWrk::processNewSysexChunk()
965 {
966  int j;
967  QString name;
968  QByteArray data;
969  int bank = read16bit();
970  int length = read32bit();
971  int port = read16bit();
972  bool autosend = (readByte() != 0);
973  int namelen = readByte();
974  name = readString(namelen);
975  for(j=0; j<length; ++j) {
976  int byte = readByte();
977  data += byte;
978  }
979  Q_EMIT signalWRKSysex(bank, name, autosend, port, data);
980 }
981 
982 void QWrk::processThruChunk()
983 {
984  readGap(2);
985  qint8 port = readByte(); // 0->127
986  qint8 channel = readByte(); // -1, 0->15
987  qint8 keyPlus = readByte(); // 0->127
988  qint8 velPlus = readByte(); // 0->127
989  qint8 localPort = readByte();
990  qint8 mode = readByte();
991  Q_EMIT signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort);
992 }
993 
994 void QWrk::processTrackOffset()
995 {
996  quint16 track = read16bit();
997  qint16 offset = read16bit();
998  Q_EMIT signalWRKTrackOffset(track, offset);
999 }
1000 
1001 void QWrk::processTrackReps()
1002 {
1003  quint16 track = read16bit();
1004  quint16 reps = read16bit();
1005  Q_EMIT signalWRKTrackReps(track, reps);
1006 }
1007 
1008 void QWrk::processTrackPatch()
1009 {
1010  quint16 track = read16bit();
1011  qint8 patch = readByte();
1012  Q_EMIT signalWRKTrackPatch(track, patch);
1013 }
1014 
1015 void QWrk::processTimeFormat()
1016 {
1017  quint16 fmt = read16bit();
1018  quint16 ofs = read16bit();
1019  Q_EMIT signalWRKTimeFormat(fmt, ofs);
1020 }
1021 
1022 void QWrk::processComments()
1023 {
1024  int len = read16bit();
1025  QString text = readString(len);
1026  Q_EMIT signalWRKComments(text);
1027 }
1028 
1029 void QWrk::processVariableRecord(int max)
1030 {
1031  int datalen = max - 32;
1032  QByteArray data;
1033  QString name = readVarString();
1034  readGap(31 - name.length());
1035  for ( int i = 0; i < datalen; ++i )
1036  data += readByte();
1037  Q_EMIT signalWRKVariableRecord(name, data);
1038 }
1039 
1040 void QWrk::processUnknown(int id)
1041 {
1042  Q_EMIT signalWRKUnknownChunk(id, d->m_lastChunkData);
1043 }
1044 
1045 void QWrk::processNewTrack()
1046 {
1047  qint16 bank = -1;
1048  qint16 patch = -1;
1049  //qint16 vol = -1;
1050  //qint16 pan = -1;
1051  qint8 key = -1;
1052  qint8 vel = 0;
1053  quint8 port = 0;
1054  qint8 channel = 0;
1055  bool selected = false;
1056  bool muted = false;
1057  bool loop = false;
1058  quint16 track = read16bit();
1059  quint8 len = readByte();
1060  QString name = readString(len);
1061  bank = read16bit();
1062  patch = read16bit();
1063  /*vol =*/ read16bit();
1064  /*pan =*/ read16bit();
1065  key = readByte();
1066  vel = readByte();
1067  readGap(7);
1068  port = readByte();
1069  channel = readByte();
1070  muted = (readByte() != 0);
1071  Q_EMIT signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop);
1072  if (bank > -1)
1073  Q_EMIT signalWRKTrackBank(track, bank);
1074  if (patch > -1) {
1075  if (channel > -1)
1076  Q_EMIT signalWRKProgram(track, 0, channel, patch);
1077  else
1078  Q_EMIT signalWRKTrackPatch(track, patch);
1079  }
1080 }
1081 
1082 void QWrk::processSoftVer()
1083 {
1084  int len = readByte();
1085  QString vers = readString(len);
1086  Q_EMIT signalWRKSoftVer(vers);
1087 }
1088 
1089 void QWrk::processTrackName()
1090 {
1091  int track = read16bit();
1092  int len = readByte();
1093  QString name = readString(len);
1094  Q_EMIT signalWRKTrackName(track, name);
1095 }
1096 
1097 void QWrk::processStringTable()
1098 {
1099  QStringList table;
1100  int rows = read16bit();
1101  for (int i = 0; i < rows; ++i) {
1102  int len = readByte();
1103  QString name = readString(len);
1104  int idx = readByte();
1105  table.insert(idx, name);
1106  }
1107  Q_EMIT signalWRKStringTable(table);
1108 }
1109 
1110 void QWrk::processLyricsStream()
1111 {
1112  quint16 track = read16bit();
1113  int events = read32bit();
1114  processNoteArray(track, events);
1115 }
1116 
1117 void QWrk::processTrackVol()
1118 {
1119  quint16 track = read16bit();
1120  int vol = read16bit();
1121  Q_EMIT signalWRKTrackVol(track, vol);
1122 }
1123 
1124 void QWrk::processNewTrackOffset()
1125 {
1126  quint16 track = read16bit();
1127  int offset = read32bit();
1128  Q_EMIT signalWRKTrackOffset(track, offset);
1129 }
1130 
1131 void QWrk::processTrackBank()
1132 {
1133  quint16 track = read16bit();
1134  int bank = read16bit();
1135  Q_EMIT signalWRKTrackBank(track, bank);
1136 }
1137 
1138 void QWrk::processSegmentChunk()
1139 {
1140  QString name;
1141  int track = read16bit();
1142  int offset = read32bit();
1143  readGap(8);
1144  int len = readByte();
1145  name = readString(len);
1146  readGap(20);
1147  Q_EMIT signalWRKSegment(track, offset, name);
1148  int events = read32bit();
1149  processNoteArray(track, events);
1150 }
1151 
1152 void QWrk::processNewStream()
1153 {
1154  QString name;
1155  int track = read16bit();
1156  int len = readByte();
1157  name = readString(len);
1158  Q_EMIT signalWRKSegment(track, 0, name);
1159  int events = read32bit();
1160  processNoteArray(track, events);
1161 }
1162 
1163 void QWrk::processEndChunk()
1164 {
1165  emit signalWRKEnd();
1166 }
1167 
1168 int QWrk::readChunk()
1169 {
1170  long start_pos, final_pos;
1171  int ck_len, ck = readByte();
1172  if (ck != END_CHUNK) {
1173  ck_len = read32bit();
1174  start_pos = getFilePos();
1175  final_pos = start_pos + ck_len;
1176  readRawData(ck_len);
1177  seek(start_pos);
1178  switch (ck) {
1179  case TRACK_CHUNK:
1180  processTrackChunk();
1181  break;
1182  case VARS_CHUNK:
1183  processVarsChunk();
1184  break;
1185  case TIMEBASE_CHUNK:
1186  processTimebaseChunk();
1187  break;
1188  case STREAM_CHUNK:
1189  processStreamChunk();
1190  break;
1191  case METER_CHUNK:
1192  processMeterChunk();
1193  break;
1194  case TEMPO_CHUNK:
1195  processTempoChunk(100);
1196  break;
1197  case NTEMPO_CHUNK:
1198  processTempoChunk();
1199  break;
1200  case SYSEX_CHUNK:
1201  processSysexChunk();
1202  break;
1203  case THRU_CHUNK:
1204  processThruChunk();
1205  break;
1206  case TRKOFFS_CHUNK:
1207  processTrackOffset();
1208  break;
1209  case TRKREPS_CHUNK:
1210  processTrackReps();
1211  break;
1212  case TRKPATCH_CHUNK:
1213  processTrackPatch();
1214  break;
1215  case TIMEFMT_CHUNK:
1216  processTimeFormat();
1217  break;
1218  case COMMENTS_CHUNK:
1219  processComments();
1220  break;
1221  case VARIABLE_CHUNK:
1222  processVariableRecord(ck_len);
1223  break;
1224  case NTRACK_CHUNK:
1225  processNewTrack();
1226  break;
1227  case SOFTVER_CHUNK:
1228  processSoftVer();
1229  break;
1230  case TRKNAME_CHUNK:
1231  processTrackName();
1232  break;
1233  case STRTAB_CHUNK:
1234  processStringTable();
1235  break;
1236  case LYRICS_CHUNK:
1237  processLyricsStream();
1238  break;
1239  case TRKVOL_CHUNK:
1240  processTrackVol();
1241  break;
1242  case NTRKOFS_CHUNK:
1243  processNewTrackOffset();
1244  break;
1245  case TRKBANK_CHUNK:
1246  processTrackBank();
1247  break;
1248  case METERKEY_CHUNK:
1249  processMeterKeyChunk();
1250  break;
1251  case SYSEX2_CHUNK:
1252  processSysex2Chunk();
1253  break;
1254  case NSYSEX_CHUNK:
1255  processNewSysexChunk();
1256  break;
1257  case SGMNT_CHUNK:
1258  processSegmentChunk();
1259  break;
1260  case NSTREAM_CHUNK:
1261  processNewStream();
1262  break;
1263  default:
1264  processUnknown(ck);
1265  }
1266  seek(final_pos);
1267  }
1268  return ck;
1269 }
1270 
1271 void QWrk::wrkRead()
1272 {
1273  int vma, vme;
1274  int ck_id;
1275  QByteArray hdr(HEADER.length(), ' ');
1276  d->m_tempos.clear();
1277  d->m_IOStream->device()->read(hdr.data(), HEADER.length());
1278  if (hdr == HEADER) {
1279  readGap(1);
1280  vme = readByte();
1281  vma = readByte();
1282  Q_EMIT signalWRKHeader(vma, vme);
1283  do {
1284  ck_id = readChunk();
1285  } while (ck_id != END_CHUNK);
1286  if (!atEnd())
1287  Q_EMIT signalWRKError("Corrupted file");
1288  else
1289  processEndChunk();
1290  } else
1291  Q_EMIT signalWRKError("Invalid file format");
1292 }
1293 
1294 } // 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