コード例 #1
0
CDialogItemTemplate CDialogItemTemplate::GetNextItem() const
{
	// Get a pointer to the data
	const WORD* pw = GetDataPtr();
	// Skip all three data fields
	SkipData(pw); SkipData(pw); SkipExtraData(pw, m_bIsItemEx);

	// The next item template starts on the next DWORD boundary.
	const DLGITEMTEMPLATE* pItem = (const DLGITEMTEMPLATE*) AlignToDWORD(pw);
	return CDialogItemTemplate( m_rParent, pItem, m_bIsItemEx );
}
コード例 #2
0
void wxArchive::FindCurrentEnterLevel()
{
	// the next read should be the begin marker. If not, we search for the
	// begin marker

	if(m_haveBoundary && m_lastBoundary == wxARCHIVE_HDR_ENTER)
	{
		m_haveBoundary = false;
		return;
	}

	wxUint8 hdr = LoadChar();	// we do not care about the header
	while(IsOk() && hdr != wxARCHIVE_HDR_ENTER)
	{
		// here we have data loss, as we need to look for our marker
		m_status.SetNewDataLoss();

		// we should find the enter level, not leave
		if(hdr == wxARCHIVE_HDR_LEAVE)
			LogError(wxARCHIVE_ERR_ILL, wxARCHIVE_ERR_STR_ILL_LEAVE);

		SkipData(hdr);
		hdr = LoadChar();
	}
}
コード例 #3
0
ファイル: device.c プロジェクト: suborb/reelvdr
bool cSatipDevice::GetTSPacket(uchar *&dataP)
{
  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
  if (tsBufferM) {
#if defined(APIVERSNUM) && APIVERSNUM >= 20104
     if (cCamSlot *cs = CamSlot()) {
        if (cs->WantsTsData()) {
           int available;
           dataP = GetData(&available);
           if (dataP) {
              dataP = cs->Decrypt(dataP, available);
              SkipData(available);
              }
           return true;
           }
        }
#endif
     dataP = GetData();
     return true;
     }
  // Reduce cpu load by preventing busylooping
  cCondWait::SleepMs(10);
  dataP = NULL;
  return true;
}
コード例 #4
0
ファイル: device.c プロジェクト: suborb/reelvdr
uchar *cSatipDevice::GetData(int *availableP)
{
  //debug("cSatipDevice::%s(%u)", __FUNCTION__, deviceIndexM);
  if (isOpenDvrM && tsBufferM) {
     int count = 0;
     if (isPacketDeliveredM)
        SkipData(TS_SIZE);
     uchar *p = tsBufferM->Get(count);
     if (p && count >= TS_SIZE) {
        if (*p != TS_SYNC_BYTE) {
           for (int i = 1; i < count; i++) {
               if (p[i] == TS_SYNC_BYTE) {
                  count = i;
                  break;
                  }
               }
           tsBufferM->Del(count);
           info("Skipped %d bytes to sync on TS packet", count);
           return NULL;
           }
        isPacketDeliveredM = true;
        if (availableP)
           *availableP = count;
        // Update pid statistics
        AddPidStatistic(ts_pid(p), payload(p));
        return p;
        }
     }
  return NULL;
}
コード例 #5
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
{
  for (;;)
  {
    if (ReadID() == NID::kEnd)
      break;
    SkipData();
  }
}
コード例 #6
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInArchive::WaitAttribute(UInt64 attribute)
{
  for (;;)
  {
    UInt64 type = ReadID();
    if (type == attribute)
      return;
    if (type == NID::kEnd)
      ThrowIncorrect();
    SkipData();
  }
}
コード例 #7
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInArchive::ReadUnpackInfo(
    const CObjectVector<CByteBuffer> *dataVector,
    CObjectVector<CFolder> &folders)
{
  WaitAttribute(NID::kFolder);
  CNum numFolders = ReadNum();

  {
    CStreamSwitch streamSwitch;
    streamSwitch.Set(this, dataVector);
    folders.Clear();
    folders.Reserve(numFolders);
    for (CNum i = 0; i < numFolders; i++)
    {
      folders.Add(CFolder());
      GetNextFolderItem(folders.Back());
    }
  }

  WaitAttribute(NID::kCodersUnpackSize);

  CNum i;
  for (i = 0; i < numFolders; i++)
  {
    CFolder &folder = folders[i];
    CNum numOutStreams = folder.GetNumOutStreams();
    folder.UnpackSizes.Reserve(numOutStreams);
    for (CNum j = 0; j < numOutStreams; j++)
      folder.UnpackSizes.Add(ReadNumber());
  }

  for (;;)
  {
    UInt64 type = ReadID();
    if (type == NID::kEnd)
      return;
    if (type == NID::kCRC)
    {
      CBoolVector crcsDefined;
      CRecordVector<UInt32> crcs;
      ReadHashDigests(numFolders, crcsDefined, crcs);
      for (i = 0; i < numFolders; i++)
      {
        CFolder &folder = folders[i];
        folder.UnpackCRCDefined = crcsDefined[i];
        folder.UnpackCRC = crcs[i];
      }
      continue;
    }
    SkipData();
  }
}
コード例 #8
0
ファイル: 7zArcIn.c プロジェクト: 670232921/pfm_archive
static SRes WaitId(CSzData *sd, UInt32 id)
{
  for (;;)
  {
    UInt64 type;
    RINOK(ReadID(sd, &type));
    if (type == id)
      return SZ_OK;
    if (type == k7zIdEnd)
      return SZ_ERROR_ARCHIVE;
    RINOK(SkipData(sd));
  }
}
コード例 #9
0
void wxArchive::FindCurrentLeaveLevel()
{
	bool firstHdr = true;
	unsigned char hdr = 0;
	// the next read should be the leave marker. If not, we search for the
	// leave marker that belongs to our current state (this means skipping
	// data that we cannot read, and potential enter and leave markers
	// that we do not read anyway

	int foundLevel = 1;
	if(m_haveBoundary)
	{
		// reset the boundary scan
		m_haveBoundary = false;

		// determine what to do
		if(m_lastBoundary == wxARCHIVE_HDR_ENTER)
			foundLevel++;
		else if(m_lastBoundary == wxARCHIVE_HDR_LEAVE)
			return;
	}

	while(IsOk() && foundLevel > 0)
	{
		if(hdr == wxARCHIVE_HDR_ENTER)
			foundLevel++;
		else if(hdr == wxARCHIVE_HDR_LEAVE)
		{
			foundLevel--;
			if(foundLevel < 0)
			{
				LogError(wxARCHIVE_ERR_ILL, wxARCHIVE_ERR_STR_ILL_LEAVE);
				return;
			}
		}

		if(foundLevel > 0)
		{
			hdr = LoadChar();

			// here we have data loss, as we need to look for our marker
			// the first header should have been the proper marker (if in sync)
			if(!firstHdr)
				m_status.SetNewDataLoss();

			SkipData(hdr);
		}

		firstHdr = false;
	}
}
コード例 #10
0
LPCWSTR CDialogItemTemplate::GetTitle() const
{
	// Get a pointer to the data
	const WORD* pw = GetDataPtr();
	// Skip the window class string
	SkipData(pw);

	// This is either a null-terminated string or a resource identifer.
	// (See documentation of DLGITEMTEMPLATE)
	if ( *pw == 0xFFFF )
		return (LPCWSTR) MAKEINTRESOURCEW(pw[1]);
	else
		return (LPCWSTR) pw;		
}
コード例 #11
0
ファイル: device.c プロジェクト: nafets227/vdr-plugin-satip
bool cSatipDevice::GetTSPacket(uchar *&dataP)
{
  debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
  if (tsBufferM) {
     if (cCamSlot *cs = CamSlot()) {
        if (cs->WantsTsData()) {
           int available;
           dataP = GetData(&available);
           if (dataP) {
              dataP = cs->Decrypt(dataP, available);
              SkipData(available);
              }
           return true;
           }
        }
     dataP = GetData();
     return true;
     }
  dataP = NULL;
  return true;
}
コード例 #12
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInArchive::ReadPackInfo(
    UInt64 &dataOffset,
    CRecordVector<UInt64> &packSizes,
    CBoolVector &packCRCsDefined,
    CRecordVector<UInt32> &packCRCs)
{
  dataOffset = ReadNumber();
  CNum numPackStreams = ReadNum();

  WaitAttribute(NID::kSize);
  packSizes.Clear();
  packSizes.Reserve(numPackStreams);
  for (CNum i = 0; i < numPackStreams; i++)
    packSizes.Add(ReadNumber());

  UInt64 type;
  for (;;)
  {
    type = ReadID();
    if (type == NID::kEnd)
      break;
    if (type == NID::kCRC)
    {
      ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
      continue;
    }
    SkipData();
  }
  if (packCRCsDefined.IsEmpty())
  {
    BoolVector_Fill_False(packCRCsDefined, numPackStreams);
    packCRCs.Reserve(numPackStreams);
    packCRCs.Clear();
    for (CNum i = 0; i < numPackStreams; i++)
      packCRCs.Add(0);
  }
}
コード例 #13
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
HRESULT CInArchive::ReadHeader(
    DECL_EXTERNAL_CODECS_LOC_VARS
    CArchiveDatabaseEx &db
    #ifndef _NO_CRYPTO
    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
    #endif
    )
{
  UInt64 type = ReadID();

  if (type == NID::kArchiveProperties)
  {
    ReadArchiveProperties(db.ArchiveInfo);
    type = ReadID();
  }
 
  CObjectVector<CByteBuffer> dataVector;
  
  if (type == NID::kAdditionalStreamsInfo)
  {
    HRESULT result = ReadAndDecodePackedStreams(
        EXTERNAL_CODECS_LOC_VARS
        db.ArchiveInfo.StartPositionAfterHeader,
        db.ArchiveInfo.DataStartPosition2,
        dataVector
        #ifndef _NO_CRYPTO
        , getTextPassword, passwordIsDefined
        #endif
        );
    RINOK(result);
    db.ArchiveInfo.DataStartPosition2 += db.ArchiveInfo.StartPositionAfterHeader;
    type = ReadID();
  }

  CRecordVector<UInt64> unpackSizes;
  CBoolVector digestsDefined;
  CRecordVector<UInt32> digests;
  
  if (type == NID::kMainStreamsInfo)
  {
    ReadStreamsInfo(&dataVector,
        db.ArchiveInfo.DataStartPosition,
        db.PackSizes,
        db.PackCRCsDefined,
        db.PackCRCs,
        db.Folders,
        db.NumUnpackStreamsVector,
        unpackSizes,
        digestsDefined,
        digests);
    db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader;
    type = ReadID();
  }
  else
  {
    for (int i = 0; i < db.Folders.Size(); i++)
    {
      db.NumUnpackStreamsVector.Add(1);
      CFolder &folder = db.Folders[i];
      unpackSizes.Add(folder.GetUnpackSize());
      digestsDefined.Add(folder.UnpackCRCDefined);
      digests.Add(folder.UnpackCRC);
    }
  }

  db.Files.Clear();

  if (type == NID::kEnd)
    return S_OK;
  if (type != NID::kFilesInfo)
    ThrowIncorrect();
  
  CNum numFiles = ReadNum();
  db.Files.Reserve(numFiles);
  CNum i;
  for (i = 0; i < numFiles; i++)
    db.Files.Add(CFileItem());

  db.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);
  if (!db.PackSizes.IsEmpty())
    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);
  if (numFiles > 0  && !digests.IsEmpty())
    db.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);

  CBoolVector emptyStreamVector;
  BoolVector_Fill_False(emptyStreamVector, (int)numFiles);
  CBoolVector emptyFileVector;
  CBoolVector antiFileVector;
  CNum numEmptyStreams = 0;

  for (;;)
  {
    UInt64 type = ReadID();
    if (type == NID::kEnd)
      break;
    UInt64 size = ReadNumber();
    size_t ppp = _inByteBack->_pos;
    bool addPropIdToList = true;
    bool isKnownType = true;
    if (type > ((UInt32)1 << 30))
      isKnownType = false;
    else switch((UInt32)type)
    {
      case NID::kName:
      {
        CStreamSwitch streamSwitch;
        streamSwitch.Set(this, &dataVector);
        for (int i = 0; i < db.Files.Size(); i++)
          _inByteBack->ReadString(db.Files[i].Name);
        break;
      }
      case NID::kWinAttributes:
      {
        CBoolVector boolVector;
        ReadBoolVector2(db.Files.Size(), boolVector);
        CStreamSwitch streamSwitch;
        streamSwitch.Set(this, &dataVector);
        for (i = 0; i < numFiles; i++)
        {
          CFileItem &file = db.Files[i];
          file.AttribDefined = boolVector[i];
          if (file.AttribDefined)
            file.Attrib = ReadUInt32();
        }
        break;
      }
      case NID::kEmptyStream:
      {
        ReadBoolVector(numFiles, emptyStreamVector);
        for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
          if (emptyStreamVector[i])
            numEmptyStreams++;

        BoolVector_Fill_False(emptyFileVector, numEmptyStreams);
        BoolVector_Fill_False(antiFileVector, numEmptyStreams);

        break;
      }
      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;
      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;
      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (int)numFiles); break;
      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (int)numFiles); break;
      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (int)numFiles); break;
      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (int)numFiles); break;
      case NID::kDummy:
      {
        for (UInt64 j = 0; j < size; j++)
          if (ReadByte() != 0)
            ThrowIncorrect();
        addPropIdToList = false;
        break;
      }
      default:
        addPropIdToList = isKnownType = false;
    }
    if (isKnownType)
    {
      if(addPropIdToList)
        db.ArchiveInfo.FileInfoPopIDs.Add(type);
    }
    else
      SkipData(size);
    bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||
        db.ArchiveInfo.Version.Minor > 2);
    if (checkRecordsSize && _inByteBack->_pos - ppp != size)
      ThrowIncorrect();
  }

  CNum emptyFileIndex = 0;
  CNum sizeIndex = 0;

  CNum numAntiItems = 0;
  for (i = 0; i < numEmptyStreams; i++)
    if (antiFileVector[i])
      numAntiItems++;
    
  for (i = 0; i < numFiles; i++)
  {
    CFileItem &file = db.Files[i];
    bool isAnti;
    file.HasStream = !emptyStreamVector[i];
    if (file.HasStream)
    {
      file.IsDir = false;
      isAnti = false;
      file.Size = unpackSizes[sizeIndex];
      file.Crc = digests[sizeIndex];
      file.CrcDefined = digestsDefined[sizeIndex];
      sizeIndex++;
    }
    else
    {
      file.IsDir = !emptyFileVector[emptyFileIndex];
      isAnti = antiFileVector[emptyFileIndex];
      emptyFileIndex++;
      file.Size = 0;
      file.CrcDefined = false;
    }
    if (numAntiItems != 0)
      db.IsAnti.Add(isAnti);
  }
  return S_OK;
}
コード例 #14
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInArchive::ReadSubStreamsInfo(
    const CObjectVector<CFolder> &folders,
    CRecordVector<CNum> &numUnpackStreamsInFolders,
    CRecordVector<UInt64> &unpackSizes,
    CBoolVector &digestsDefined,
    CRecordVector<UInt32> &digests)
{
  numUnpackStreamsInFolders.Clear();
  numUnpackStreamsInFolders.Reserve(folders.Size());
  UInt64 type;
  for (;;)
  {
    type = ReadID();
    if (type == NID::kNumUnpackStream)
    {
      for (int i = 0; i < folders.Size(); i++)
        numUnpackStreamsInFolders.Add(ReadNum());
      continue;
    }
    if (type == NID::kCRC || type == NID::kSize)
      break;
    if (type == NID::kEnd)
      break;
    SkipData();
  }

  if (numUnpackStreamsInFolders.IsEmpty())
    for (int i = 0; i < folders.Size(); i++)
      numUnpackStreamsInFolders.Add(1);

  int i;
  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)
  {
    // v3.13 incorrectly worked with empty folders
    // v4.07: we check that folder is empty
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams == 0)
      continue;
    UInt64 sum = 0;
    for (CNum j = 1; j < numSubstreams; j++)
      if (type == NID::kSize)
      {
        UInt64 size = ReadNumber();
        unpackSizes.Add(size);
        sum += size;
      }
    unpackSizes.Add(folders[i].GetUnpackSize() - sum);
  }
  if (type == NID::kSize)
    type = ReadID();

  int numDigests = 0;
  int numDigestsTotal = 0;
  for (i = 0; i < folders.Size(); i++)
  {
    CNum numSubstreams = numUnpackStreamsInFolders[i];
    if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
      numDigests += numSubstreams;
    numDigestsTotal += numSubstreams;
  }

  for (;;)
  {
    if (type == NID::kCRC)
    {
      CBoolVector digestsDefined2;
      CRecordVector<UInt32> digests2;
      ReadHashDigests(numDigests, digestsDefined2, digests2);
      int digestIndex = 0;
      for (i = 0; i < folders.Size(); i++)
      {
        CNum numSubstreams = numUnpackStreamsInFolders[i];
        const CFolder &folder = folders[i];
        if (numSubstreams == 1 && folder.UnpackCRCDefined)
        {
          digestsDefined.Add(true);
          digests.Add(folder.UnpackCRC);
        }
        else
          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
          {
            digestsDefined.Add(digestsDefined2[digestIndex]);
            digests.Add(digests2[digestIndex]);
          }
      }
    }
    else if (type == NID::kEnd)
    {
      if (digestsDefined.IsEmpty())
      {
        BoolVector_Fill_False(digestsDefined, numDigestsTotal);
        digests.Clear();
        for (int i = 0; i < numDigestsTotal; i++)
          digests.Add(0);
      }
      return;
    }
    else
      SkipData();
    type = ReadID();
  }
}
コード例 #15
0
ファイル: 7zIn.cpp プロジェクト: 0963682490/omaha
void CInByte2::SkipData()
{
  SkipData(ReadNumber());
}
コード例 #16
0
ファイル: CapsLoader.cpp プロジェクト: FrodeSolheim/capsimg
// read caps chunk
int CCapsLoader::ReadChunk(int idbrk)
{
	// handle file error
	if (!file.IsOpen())
		return ccidErrFile;

	// skip data area if any
	SkipData();

	// check EOF
	int pos=file.GetPosition();
	if (pos == flen)
		return ccidEof;

	// check for ID chunk size
	if (flen-pos < sizeof(CapsID))
		return ccidErrShort;

	// read ID chunk
	if (file.Read((PUBYTE)&xchunk.file, sizeof(CapsID)) != sizeof(CapsID))
		return ccidErrShort;
	chunk.cg.file=xchunk.file;

	// identify chunk type if possible
	int type=GetChunkType(&chunk);

	// stop if break on unknown types
	if (idbrk && type==ccidUnknown)
		return ccidUnknown;

	// set ID to host format
	Swap(PUDWORD((PUBYTE)&chunk.cg.file+sizeof(chunk.cg.file.name)), sizeof(CapsID)-sizeof(chunk.cg.file.name));

	// load modifier for known chunk types, skip for unknown types
	int modsize=chunk.cg.file.size-sizeof(CapsID);
	if (modsize > 0) {
		// check for valid modifier size
		pos=file.GetPosition();
		if (flen-pos < modsize)
			return ccidErrShort;

		// read mod chunk if buffer has enough space or skip it
		if (modsize <= sizeof(CapsMod)) {
			// read mod chunk
			if (file.Read((PUBYTE)&xchunk.mod, modsize) != modsize)
				return ccidErrShort;

			// set header to host format
			chunk.cg.mod=xchunk.mod;
			Swap(PUDWORD((PUBYTE)&chunk.cg.mod), modsize);
		} else {
			// seek to new chunk
			file.Seek(modsize, 0);
		}
	}

	// check CRC value for completely read headers
	if (modsize>=0 && modsize<=sizeof(CapsMod)) {
		xchunk.file.hcrc=0;
		if (chunk.cg.file.hcrc != CalcCRC((PUBYTE)&xchunk.file, chunk.cg.file.size))
			return ccidErrHeader;
	}

	return type;
}
コード例 #17
0
ファイル: smf.c プロジェクト: keoni29/osc
/* Poll MIDI event.
 * Returns 1 on succes, SFM_event contains event and dt contains interval in ms.
 * Returns SMF_STOPPED on playback end.
 */
int SMF_PollEvent(struct SMF_event *e, uint32_t *dt)
{
	int result = SMF_NO_EVENTS;
	//int i;
	int a = 0; /* Todo implement for multiple tracks */
	uint32_t length;
	uint8_t type;

	uint8_t status = track[a].status;

	if (track->head >= track->length)
	{
		return SMF_STOPPED;
	}

	if (!(Peek(&track[a]) & 0x80))
	{
		/* Running byte! Do not change the state. */
	}
	else
	{
		status = Data(&track[a]);
		track[a].status = status;
	}

	if (status == 0xF0 || status == 0xF7)
	{
		/* System exclusive event */
		while (Data(&track[a]) != 0xF7)
		{
			;
		}
	}
	else if (status == 0xFF)
	{
		/* Meta event */
		type = Data(&track[a]);
		length = VData(&track[a]);

		if (type == 0x51 && length == 3)
		{
			usPerBeat = (Data(&track[a]) << 16) | (Data(&track[a]) << 8) | (Data(&track[a]) << 0);
			tick = usPerBeat / ticksPerBeat;
		}
		else
		{
			/* Unknown message */
			SkipData(&track[a], length);
		}
	}
	else
	{
		e->channel = (status & 0x0F) + 1;
		e->status = (status & 0x70) >> 4;
		/* MIDI event */
		switch (status & 0xF0)
		{
		case 0x80:
		case 0x90:
		case 0xA0:
		case 0xB0:
		case 0xE0:
			/* 2 parameters */
			e->p1 = Data(&track[a]);
			e->p2 = Data(&track[a]);
			result = SMF_EVENT_READY;
			break;
		case 0xC0:
		case 0xD0:
			/* 1 parameter */
			e->p1 = Data(&track[a]);
			result = SMF_EVENT_READY;
			break;
		case 0xF0:
		default:
			/* Todo: handle these unhandled events */
			break;
		}
	}

	/* Calculate delta time in us */
	track[a].dt = (VData(&track[a]) * tick) / 1000;

	/* Todo determine smallest dt */
	/* Whose first up? (Smallest delta time.) */
	/*uint32_t min = track[0];
	for (i = 0; i < trackCount; i++)
	{
		if (track[i] < min)
		{
			min = track[i];
		}
	}*/

	/* Calculate delta time in ms */
	//*dt = min / 1000;
	*dt = track[a].dt;

	return result;
}
コード例 #18
0
ファイル: smf.c プロジェクト: keoni29/osc
/** Verify the track
 * 	Returns negative error code on failure, 1 when last event in track was not Meta "End of Track", 0 on success. */
static int VerifyTrack(struct SMF_track* t)
{
	uint8_t status, type;

	if (!_strcmpl("MTrk", t->str, 4))
	{
		return -1;
	}

	while (t->head < t->length)
	{
		uint32_t length;

		/* Skip over delta time field */
		VData(t);

		if (!(Peek(t) & 0x80))
		{
			/* Running byte! Do not change the state. */
		}
		else
		{
			status = Data(t);
		}

		if (status == 0xF0 || status == 0xF7)
		{
			/* System exclusive event */
			while (Data(t) != 0xF7)
			{
				;
			}
		}
		else if (status == 0xFF)
		{
			/* Meta event */
			type = Data(t);
			length = VData(t);
			SkipData(t, length);
		}
		else
		{
			/* MIDI event */
			switch (status & 0xF0)
			{
			case 0x80:
			case 0x90:
			case 0xA0:
			case 0xB0:
			case 0xE0:
				/* 2 parameters */
				SkipData(t, 2);
				break;
			case 0xC0:
			case 0xD0:
				/* 1 parameter */
				SkipData(t, 1);
				break;
			case 0xF0:
			default:
				/* Unhandled event */
				return -1;
				break;
			}
		}
	}

	if (!(status == 0xFF && type == 0x2F))
	{
		/* Last message was not META 0x2F (End of track) */
		return 1;
	}
	return 0;
}