[xiph-commits] r10587 - trunk/xiph-qt/OggImport/src
arek at svn.xiph.org
arek at svn.xiph.org
Tue Dec 13 15:13:29 PST 2005
Author: arek
Date: 2005-12-13 15:13:20 -0800 (Tue, 13 Dec 2005)
New Revision: 10587
Modified:
trunk/xiph-qt/OggImport/src/OggImport.c
trunk/xiph-qt/OggImport/src/importer_types.h
trunk/xiph-qt/OggImport/src/stream_speex.c
trunk/xiph-qt/OggImport/src/stream_vorbis.c
Log:
XiphQT ogg demuxer improvements:
* handling of multi-logical-stream ("non-degenrate"?) ogg bitstreams:
* inserting tracks with appropriate offsets now;
* proper demultiplexing of interleaved streams.
Modified: trunk/xiph-qt/OggImport/src/OggImport.c
===================================================================
--- trunk/xiph-qt/OggImport/src/OggImport.c 2005-12-13 13:51:58 UTC (rev 10586)
+++ trunk/xiph-qt/OggImport/src/OggImport.c 2005-12-13 23:13:20 UTC (rev 10587)
@@ -297,7 +297,6 @@
{
StreamInfo *si = &(*globals->streamInfoHandle)[globals->streamCount - 1];
si->serialno = serialno;
- si->timeLoaded = 0;
ogg_stream_init(&si->os,serialno);
@@ -306,7 +305,6 @@
if (ff->initialize != NULL)
(*ff->initialize)(si); // check for error here and clean-up if not OK
- si->startTime = globals->startTime;
si->soundDescExtension = NewHandle(0);
si->MDmapping = NULL;
@@ -335,7 +333,7 @@
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-static void CloseStream(OggImportGlobalsPtr globals, StreamInfoPtr si)
+static void _close_stream(OggImportGlobalsPtr globals, StreamInfoPtr si)
{
ogg_stream_clear(&si->os);
@@ -360,13 +358,33 @@
for (i = 0; i < globals->streamCount; i++)
{
StreamInfoPtr si = &(*globals->streamInfoHandle)[i];
- CloseStream(globals, si);
+ _close_stream(globals, si);
}
globals->streamCount = 0;
SetHandleSize((Handle) globals->streamInfoHandle, 0);
}
+static void CloseStream(OggImportGlobalsPtr globals, StreamInfoPtr si)
+{
+ int i;
+ for (i = 0; i < globals->streamCount; i++)
+ {
+ if (si == &(*globals->streamInfoHandle)[i]) {
+ _close_stream(globals, si);
+
+ if (i < globals->streamCount - 1) {
+ HLock((Handle) globals->streamInfoHandle);
+ BlockMove(&(*globals->streamInfoHandle)[i+1], &(*globals->streamInfoHandle)[i], sizeof(StreamInfo) * (globals->streamCount - 1 - i));
+ HUnlock((Handle) globals->streamInfoHandle);
+ }
+ globals->streamCount--;
+ SetHandleSize((Handle) globals->streamInfoHandle, sizeof(StreamInfo) * globals->streamCount);
+ break;
+ }
+ }
+}
+
static int InitialiseMetaDataMappings(OggImportGlobalsPtr globals, StreamInfoPtr si) {
SInt32 ret = 0;
CFDictionaryRef props = NULL;
@@ -715,7 +733,7 @@
OSErr err = noErr;
if (!globals->usingIdle) {
- dbg_printf(" -- NotifyMovieChanged() = using idles, skipping\n");
+ dbg_printf(" -- NotifyMovieChanged() = not using idles, skipping\n");
return err;
}
@@ -775,38 +793,65 @@
static ComponentResult ProcessPage(OggImportGlobalsPtr globals, ogg_page *op) {
ComponentResult ret = noErr;
long serialno;
- StreamInfoPtr si;
+ StreamInfoPtr si = NULL;
+ Boolean process_page = true;
serialno = ogg_page_serialno(op);
dbg_printf(" - = page found, nr: %08lx\n", ogg_page_pageno(op));
- if (ogg_page_bos(op)) {
- stream_format_handle_funcs *ff = NULL;
- dbg_printf(" - = new stream found: %lx\n" , serialno);
- ff = find_stream_support(op);
- if (ff != NULL) {
- dbg_printf(" - == And a supported one!\n");
- ret = OpenStream(globals, serialno, op, ff);
+ if (!globals->groupStreamsFound) {
+ if (ogg_page_bos(op)) {
+ stream_format_handle_funcs *ff = NULL;
+ dbg_printf(" - = new stream found: %08lx\n" , serialno);
+ //si = FindStream(globals, serialno);
+ //if (si != NULL)
+ // ; // !?!?
+ ff = find_stream_support(op);
+ if (ff != NULL) {
+ dbg_printf(" - == And a supported one!\n");
+ ret = OpenStream(globals, serialno, op, ff);
+ if (ret == noErr) {
+ ogg_packet opckt;
- if (ret == noErr) {
- ogg_packet opckt;
- StreamInfoPtr si = FindStream(globals, serialno);
+ si = FindStream(globals, serialno);
+ if (si != NULL) {
+ ogg_stream_pagein(&si->os, op); //check errors?
+ ogg_stream_packetout(&si->os, &opckt); //check errors?
- if (si != NULL) {
- ogg_stream_pagein(&si->os, op); //check errors?
- ogg_stream_packetout(&si->os, &opckt); //check errors?
+ if (si->sfhf->first_packet != NULL)
+ (*si->sfhf->first_packet)(si, op, &opckt); //check errors?
- if (si->sfhf->first_packet != NULL)
- (*si->sfhf->first_packet)(si, op, &opckt); //check errors?
+ if (globals->currentGroupOffset == -1)
+ globals->currentGroupOffset = globals->timeLoaded;
+
+ process_page = false;
+ }
}
}
+ } else {
+ si = FindStream(globals, serialno);
+ if (si != NULL) {
+ globals->groupStreamsFound = true;
+ }
}
} else {
- si = FindStream(globals, serialno);
+ if (!ogg_page_bos(op))
+ si = FindStream(globals, serialno);
+ }
- if (si != NULL) {
+ if (si != NULL) {
+ if (process_page) {
ret = ProcessStreamPage(globals, si, op);
}
+
+ if (ogg_page_eos(op)) {
+ dbg_printf(" x = closing stream: %08lx\n" , serialno);
+ CloseStream(globals, si);
+ if (globals->streamCount == 0) {
+ globals->groupStreamsFound = false;
+ globals->currentGroupOffset = -1;
+ }
+ }
}
globals->dataOffset = S64Add(globals->dataOffset, S64Set(globals->currentData - globals->dataRB.b_start));
@@ -836,6 +881,9 @@
globals->dataRequested = false;
globals->startTickCount = TickCount();
+ globals->currentGroupOffset = globals->startTime;
+ globals->groupStreamsFound = false;
+
if (S64Compare(globals->dataEndOffset, S64Set(-1)) == 0) {
globals->sizeInitialised = false;
globals->state = kStateGettingSize;
@@ -869,10 +917,13 @@
while (result == noErr && FindPage(&globals->currentData, globals->validDataEnd, &og)) {
result = ProcessPage(globals, &og);
+ dbg_printf(" - << (:kStateReadingPages:) :: ProcessPage() = %ld\n", (long) result);
}
- if (result != noErr)
+ if (result != noErr) {
+ process = false;
break;
+ }
result = FillBuffer(globals);
if (result == eofErr) {
@@ -888,11 +939,16 @@
globals->validDataEnd = globals->currentData + rb_data_available(&globals->dataRB);
dbg_printf(" + (:kStateReadingLastPages:)\n");
- while (FindPage(&globals->currentData, globals->validDataEnd, &og)) {
+ while (result == noErr && FindPage(&globals->currentData, globals->validDataEnd, &og)) {
result = ProcessPage(globals, &og);
- dbg_printf(" <- (:kStateReadingLastPages:) = %ld\n", (long)result);
+ dbg_printf(" - << (:kStateReadingLastPages:) :: ProcessPage() = %ld\n", (long) result);
}
+ if (result != noErr) {
+ process = false;
+ break;
+ }
+
globals->state = kStateImportComplete;
break;
@@ -1408,7 +1464,9 @@
*outFlags = 0;
globals->theMovie = theMovie;
- globals->startTime = atTime;
+ globals->startTime = 0;
+ if (atTime >= 0)
+ globals->startTime = atTime;
dbg_printf("-- DataRef(at:%ld) called\n", atTime);
if (GetHandleSize(dataRef) < 256) {
Modified: trunk/xiph-qt/OggImport/src/importer_types.h
===================================================================
--- trunk/xiph-qt/OggImport/src/importer_types.h 2005-12-13 13:51:58 UTC (rev 10586)
+++ trunk/xiph-qt/OggImport/src/importer_types.h 2005-12-13 23:13:20 UTC (rev 10587)
@@ -67,6 +67,7 @@
#include "stream_types_vorbis.h"
#include "stream_types_speex.h"
+#define INCOMPLETE_PAGE_DURATION 1
typedef enum ImportStates {
kStateInitial,
@@ -87,7 +88,6 @@
typedef struct {
long serialno;
- TimeValue timeLoaded;
ogg_stream_state os;
@@ -100,12 +100,11 @@
SampleDescriptionHandle sampleDesc;
ogg_int64_t lastGranulePos;
- SInt64 prevPageOffset;
- ogg_int64_t lastSeenGranulePos;
- SInt64 lastSeenEndOffset;
+ TimeValue incompleteCompensation;
- TimeValue startTime;
+ TimeValue insertTime;
+ TimeValue streamOffset;
CFDictionaryRef MDmapping;
CFDictionaryRef UDmapping;
@@ -144,6 +143,10 @@
IdleManager idleManager;
IdleManager dataIdleManager;
+ // ogg grouped and chained streams support variables
+ Boolean groupStreamsFound;
+ TimeValue currentGroupOffset;
+
long newMovieFlags;
ComponentInstance dataReader;
@@ -205,16 +208,16 @@
typedef struct stream_format_handle_funcs {
- process_stream_page process_page;
+ process_stream_page process_page;
- recognize_header recognize;
- verify_header verify;
+ recognize_header recognize;
+ verify_header verify;
- process_first_packet first_packet;
- create_sample_description sample_description;
+ process_first_packet first_packet;
+ create_sample_description sample_description;
- initialize_stream initialize;
- clear_stream clear;
+ initialize_stream initialize;
+ clear_stream clear;
} stream_format_handle_funcs;
#define HANDLE_FUNCTIONS__NULL { NULL, NULL, NULL, NULL, NULL, NULL, NULL }
Modified: trunk/xiph-qt/OggImport/src/stream_speex.c
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_speex.c 2005-12-13 13:51:58 UTC (rev 10586)
+++ trunk/xiph-qt/OggImport/src/stream_speex.c 2005-12-13 23:13:20 UTC (rev 10587)
@@ -207,9 +207,9 @@
//dbg_printf("??? -- Hmm, something went wrong: %ld\n", ret);
}
- si->startTime = 0;
- si->prevPageOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
-
+ si->insertTime = 0;
+ si->streamOffset = globals->currentGroupOffset;
+ si->incompleteCompensation = 0;
si->si_speex.state = kSStateReadingFirstPacket;
loop = false; // ??!
@@ -236,7 +236,6 @@
case kSStateReadingFirstPacket:
if (ogg_page_pageno(opg) > 2) {
si->lastGranulePos = ogg_page_granulepos(opg);
- si->prevPageOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
loop = false;
@@ -249,43 +248,71 @@
case kVStateReadingPackets:
{
ogg_int64_t pos = ogg_page_granulepos(opg);
- SInt64 endOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
- int len = S64Subtract(endOffset, si->prevPageOffset);
- int duration = pos - si->lastGranulePos;
+ int len = opg->header_len + opg->body_len;
+ TimeValue duration = pos - si->lastGranulePos;
TimeValue inserted = 0;
+ short smp_flags = 0;
- if (pos < 0) {
- //dbg_printf(" - :XX: not added page %ld (single, looooong packet)\n", ogg_page_pageno(opg));
- } else {
- dbg_printf(" - :++: adding sampleRef: %lld, len: %d, dur: %d\n", si->prevPageOffset, len, duration);
- ret = AddMediaSampleReference(si->theMedia, si->prevPageOffset,
- len, duration, si->sampleDesc, 1, 0, &inserted); //@@@@ 64-bit enable
- if (ret == noErr) {
- dbg_printf(" - :><: added page %04ld at %14ld (size: %5ld, tsize: %6d), f: %d\n",
- ogg_page_pageno(opg), inserted,
- opg->header_len + opg->body_len, len, !logg_page_last_packet_incomplete(opg));
- dbg_printf(" - :/>: inserting media: %ld, mt: %lld, dur: %d\n", si->startTime, si->lastGranulePos, duration);
- ret = InsertMediaIntoTrack(si->theTrack, si->startTime /*inserted*/, /* si->lastGranulePos */ inserted,
- duration, fixed1);
- si->startTime = -1;
- si->timeLoaded = GetTrackOffset(si->theTrack) + GetTrackDuration(si->theTrack);
- //if (globals->dataIsStream)
- // si->timeLoaded = (duration + inserted) * GetMovieTimeScale(globals->theMovie) / GetMediaTimeScale(si->theMedia);
+ if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
+ smp_flags |= mediaSampleNotSync;
- dbg_printf(" - :><: added page %04ld at %14ld; offset: %ld, duration: %ld (%ld, %ld), mediats: %ld; moviets: %ld, ret = %ld\n",
- ogg_page_pageno(opg), inserted,
- GetTrackOffset(si->theTrack), GetTrackDuration(si->theTrack), si->timeLoaded,
- (duration * GetMovieTimeScale(globals->theMovie)) / GetMediaTimeScale(si->theMedia),
- GetMediaTimeScale(si->theMedia), GetMovieTimeScale(globals->theMovie), ret);
- if (globals->timeLoaded < si->timeLoaded)
- globals->timeLoaded = si->timeLoaded;
+ if (duration <= 0) {
+ duration = INCOMPLETE_PAGE_DURATION;
+ si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
+ } else if (si->incompleteCompensation != 0) {
+ duration += si->incompleteCompensation;
+ si->incompleteCompensation = 0;
+ if (duration <= 0) {
+ ret = badFileFormat;
+ loop = false;
+ break;
+ }
+ }
- movie_changed = true;
+ dbg_printf(" - :++: adding sampleRef: %lld, len: %d, dur: %d\n", globals->dataOffset, len, duration);
+ ret = AddMediaSampleReference(si->theMedia, S32Set(globals->dataOffset),
+ len, duration, si->sampleDesc, 1, smp_flags, &inserted); //@@@@ 64-bit enable
+ if (ret == noErr) {
+ TimeValue timeLoaded;
+
+ dbg_printf(" - :><: added page %04ld at %14ld (size: %5ld, tsize: %6d), f: %d\n",
+ ogg_page_pageno(opg), inserted,
+ opg->header_len + opg->body_len, len, !logg_page_last_packet_incomplete(opg));
+ dbg_printf(" - :/>: inserting media: %ld, mt: %lld, dur: %d\n", si->insertTime, si->lastGranulePos, duration);
+ ret = InsertMediaIntoTrack(si->theTrack, si->insertTime /*inserted*/, /* si->lastGranulePos */ inserted,
+ duration, fixed1);
+ if (si->insertTime == 0) {
+ if (si->streamOffset != 0) {
+ SetTrackOffset(si->theTrack, si->streamOffset);
+ dbg_printf(" # -- SetTrackOffset(%ld) = %ld --> %ld\n",
+ si->streamOffset, GetMoviesError(),
+ GetTrackOffset(si->theTrack));
+ if (globals->dataIsStream) {
+ SetTrackEnabled(si->theTrack, false);
+ SetTrackEnabled(si->theTrack, true);
+ }
+ }
+ if (GetMovieTimeScale(globals->theMovie) < GetMediaTimeScale(si->theMedia)) {
+ dbg_printf(" # - changing movie time scale: %ld --> %ld\n",
+ GetMovieTimeScale(globals->theMovie), GetMediaTimeScale(si->theMedia));
+ SetMovieTimeScale(globals->theMovie, GetMediaTimeScale(si->theMedia));
+ }
}
+ si->insertTime = -1;
+ timeLoaded = GetTrackOffset(si->theTrack) + GetTrackDuration(si->theTrack);
- si->prevPageOffset = endOffset;
- si->lastGranulePos = pos;
+ dbg_printf(" - :><: added page %04ld at %14ld; offset: %ld, duration: %ld (%ld, %ld), mediats: %ld; moviets: %ld, ret = %ld\n",
+ ogg_page_pageno(opg), inserted,
+ GetTrackOffset(si->theTrack), GetTrackDuration(si->theTrack), timeLoaded,
+ (duration * GetMovieTimeScale(globals->theMovie)) / GetMediaTimeScale(si->theMedia),
+ GetMediaTimeScale(si->theMedia), GetMovieTimeScale(globals->theMovie), ret);
+ if (globals->timeLoaded < timeLoaded)
+ globals->timeLoaded = timeLoaded;
+
+ movie_changed = true;
}
+
+ si->lastGranulePos = pos;
}
loop = false;
break;
Modified: trunk/xiph-qt/OggImport/src/stream_vorbis.c
===================================================================
--- trunk/xiph-qt/OggImport/src/stream_vorbis.c 2005-12-13 13:51:58 UTC (rev 10586)
+++ trunk/xiph-qt/OggImport/src/stream_vorbis.c 2005-12-13 23:13:20 UTC (rev 10587)
@@ -227,8 +227,9 @@
}
si->si_vorbis.state = kVStateReadingFirstPacket;
- si->startTime = 0;
- si->prevPageOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
+ si->insertTime = 0;
+ si->streamOffset = globals->currentGroupOffset;
+ si->incompleteCompensation = 0;
loop = false; //there should be an end of page here according to specs...
}
break;
@@ -236,7 +237,6 @@
case kVStateReadingFirstPacket:
if (ogg_page_pageno(opg) > 3) {
si->lastGranulePos = ogg_page_granulepos(opg);
- si->prevPageOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
dbg_printf("----==< skipping: %llx, %lx\n", si->lastGranulePos, ogg_page_pageno(opg));
loop = false;
@@ -249,45 +249,71 @@
case kVStateReadingPackets:
{
ogg_int64_t pos = ogg_page_granulepos(opg);
- SInt64 endOffset = S64Add(globals->dataOffset, opg->header_len + opg->body_len);
- int len = S64Subtract(endOffset, si->prevPageOffset);
- int duration = pos - si->lastGranulePos;
+ int len = opg->header_len + opg->body_len;
+ TimeValue duration = pos - si->lastGranulePos;
TimeValue inserted = 0;
+ short smp_flags = 0;
- if (pos < 0) {
- //dbg_printf(" - :XX: not added page %ld (single, looooong packet)\n", ogg_page_pageno(opg));
- } else {
- dbg_printf(" - :++: adding sampleRef: %lld, len: %d, dur: %d\n", si->prevPageOffset, len, duration);
- ret = AddMediaSampleReference(si->theMedia, si->prevPageOffset,
- len, duration, si->sampleDesc, 1, 0, &inserted); //@@@@ 64-bit enable
- if (ret == noErr)
- {
- dbg_printf(" - :><: added page %04ld at %14ld (size: %5ld, tsize: %6d), f: %d\n",
- ogg_page_pageno(opg), inserted,
- opg->header_len + opg->body_len, len, !logg_page_last_packet_incomplete(opg));
- dbg_printf(" - :/>: inserting media: %ld, mt: %lld, dur: %d\n", si->startTime, si->lastGranulePos, duration);
- ret = InsertMediaIntoTrack(si->theTrack, si->startTime /*inserted*/, /* si->lastGranulePos */ inserted,
- duration, fixed1);
- si->startTime = -1;
- si->timeLoaded = GetTrackOffset(si->theTrack) + GetTrackDuration(si->theTrack);
- //if (globals->dataIsStream)
- // si->timeLoaded = (duration + inserted) * GetMovieTimeScale(globals->theMovie) / GetMediaTimeScale(si->theMedia);
+ if (ogg_page_continued(opg) || si->incompleteCompensation != 0)
+ smp_flags |= mediaSampleNotSync;
- dbg_printf(" - :><: added page %04ld at %14ld; offset: %ld, duration: %ld (%ld, %ld), mediats: %ld; moviets: %ld, ret = %ld\n",
- ogg_page_pageno(opg), inserted,
- GetTrackOffset(si->theTrack), GetTrackDuration(si->theTrack), si->timeLoaded,
- (duration * GetMovieTimeScale(globals->theMovie)) / GetMediaTimeScale(si->theMedia),
- GetMediaTimeScale(si->theMedia), GetMovieTimeScale(globals->theMovie), ret);
- if (globals->timeLoaded < si->timeLoaded)
- globals->timeLoaded = si->timeLoaded;
+ if (duration <= 0) {
+ duration = INCOMPLETE_PAGE_DURATION;
+ si->incompleteCompensation -= INCOMPLETE_PAGE_DURATION;
+ } else if (si->incompleteCompensation != 0) {
+ duration += si->incompleteCompensation;
+ si->incompleteCompensation = 0;
+ if (duration <= 0) {
+ ret = badFileFormat;
+ loop = false;
+ break;
+ }
+ }
- movie_changed = true;
+ dbg_printf(" - :++: adding sampleRef: %lld, len: %d, dur: %d\n", globals->dataOffset, len, duration);
+ ret = AddMediaSampleReference(si->theMedia, S32Set(globals->dataOffset),
+ len, duration, si->sampleDesc, 1, smp_flags, &inserted); //@@@@ 64-bit enable
+ if (ret == noErr) {
+ TimeValue timeLoaded;
+ dbg_printf(" - :><: added page %04ld at %14ld (size: %5ld, tsize: %6d), f: %d\n",
+ ogg_page_pageno(opg), inserted,
+ opg->header_len + opg->body_len, len, !logg_page_last_packet_incomplete(opg));
+ dbg_printf(" - :/>: inserting media: %ld, mt: %lld, dur: %d\n", si->insertTime, si->lastGranulePos, duration);
+ ret = InsertMediaIntoTrack(si->theTrack, si->insertTime /*inserted*/, /* si->lastGranulePos */ inserted,
+ duration, fixed1);
+ if (si->insertTime == 0) {
+ if (si->streamOffset != 0) {
+ SetTrackOffset(si->theTrack, si->streamOffset);
+ dbg_printf(" # -- SetTrackOffset(%ld) = %ld --> %ld\n",
+ si->streamOffset, GetMoviesError(),
+ GetTrackOffset(si->theTrack));
+ if (globals->dataIsStream) {
+ SetTrackEnabled(si->theTrack, false);
+ SetTrackEnabled(si->theTrack, true);
+ }
+ }
+ if (GetMovieTimeScale(globals->theMovie) < GetMediaTimeScale(si->theMedia)) {
+ dbg_printf(" # - changing movie time scale: %ld --> %ld\n",
+ GetMovieTimeScale(globals->theMovie), GetMediaTimeScale(si->theMedia));
+ SetMovieTimeScale(globals->theMovie, GetMediaTimeScale(si->theMedia));
+ }
}
+ si->insertTime = -1;
+ timeLoaded = GetTrackDuration(si->theTrack);
- si->prevPageOffset = endOffset;
- si->lastGranulePos = pos;
+ dbg_printf(" - :><: added page %04ld at %14ld; offset: %ld, duration: %ld (%ld, %ld), mediats: %ld; moviets: %ld, ret = %ld\n",
+ ogg_page_pageno(opg), inserted,
+ GetTrackOffset(si->theTrack), GetTrackDuration(si->theTrack), timeLoaded,
+ (duration * GetMovieTimeScale(globals->theMovie)) / GetMediaTimeScale(si->theMedia),
+ GetMediaTimeScale(si->theMedia), GetMovieTimeScale(globals->theMovie), ret);
+ if (globals->timeLoaded < timeLoaded)
+ globals->timeLoaded = timeLoaded;
+
+ movie_changed = true;
}
+
+ si->lastGranulePos = pos;
}
loop = false;
break;
More information about the commits
mailing list