2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2019 by Christian Schoenebeck * |
* Copyright (C) 2003-2021 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
189 |
pArticulations = NULL; |
pArticulations = NULL; |
190 |
} |
} |
191 |
|
|
192 |
|
/** |
193 |
|
* Returns Articulation at supplied @a pos position within the articulation |
194 |
|
* list. If supplied @a pos is out of bounds then @c NULL is returned. |
195 |
|
* |
196 |
|
* @param pos - position of sought Articulation in articulation list |
197 |
|
* @returns pointer address to requested articulation or @c NULL if @a pos |
198 |
|
* is out of bounds |
199 |
|
*/ |
200 |
|
Articulation* Articulator::GetArticulation(size_t pos) { |
201 |
|
if (!pArticulations) LoadArticulations(); |
202 |
|
if (!pArticulations) return NULL; |
203 |
|
if (pos >= pArticulations->size()) return NULL; |
204 |
|
return (*pArticulations)[pos]; |
205 |
|
} |
206 |
|
|
207 |
|
/** |
208 |
|
* Returns the first Articulation in the list of articulations. You have to |
209 |
|
* call this method once before you can use GetNextArticulation(). |
210 |
|
* |
211 |
|
* @returns pointer address to first Articulation or NULL if there is none |
212 |
|
* @see GetNextArticulation() |
213 |
|
* @deprecated This method is not reentrant-safe, use GetArticulation() |
214 |
|
* instead. |
215 |
|
*/ |
216 |
Articulation* Articulator::GetFirstArticulation() { |
Articulation* Articulator::GetFirstArticulation() { |
217 |
if (!pArticulations) LoadArticulations(); |
if (!pArticulations) LoadArticulations(); |
218 |
if (!pArticulations) return NULL; |
if (!pArticulations) return NULL; |
220 |
return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL; |
return (ArticulationsIterator != pArticulations->end()) ? *ArticulationsIterator : NULL; |
221 |
} |
} |
222 |
|
|
223 |
|
/** |
224 |
|
* Returns the next Articulation from the list of articulations. You have |
225 |
|
* to call GetFirstArticulation() once before you can use this method. By |
226 |
|
* calling this method multiple times it iterates through the available |
227 |
|
* articulations. |
228 |
|
* |
229 |
|
* @returns pointer address to the next Articulation or NULL if end reached |
230 |
|
* @see GetFirstArticulation() |
231 |
|
* @deprecated This method is not reentrant-safe, use GetArticulation() |
232 |
|
* instead. |
233 |
|
*/ |
234 |
Articulation* Articulator::GetNextArticulation() { |
Articulation* Articulator::GetNextArticulation() { |
235 |
if (!pArticulations) return NULL; |
if (!pArticulations) return NULL; |
236 |
ArticulationsIterator++; |
ArticulationsIterator++; |
244 |
if (lart) { |
if (lart) { |
245 |
uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2 |
uint32_t artCkType = (lart->GetListType() == LIST_TYPE_LAR2) ? CHUNK_ID_ART2 |
246 |
: CHUNK_ID_ARTL; |
: CHUNK_ID_ARTL; |
247 |
RIFF::Chunk* art = lart->GetFirstSubChunk(); |
size_t i = 0; |
248 |
while (art) { |
for (RIFF::Chunk* art = lart->GetSubChunkAt(i); art; |
249 |
|
art = lart->GetSubChunkAt(++i)) |
250 |
|
{ |
251 |
if (art->GetChunkID() == artCkType) { |
if (art->GetChunkID() == artCkType) { |
252 |
if (!pArticulations) pArticulations = new ArticulationList; |
if (!pArticulations) pArticulations = new ArticulationList; |
253 |
pArticulations->push_back(new Articulation(art)); |
pArticulations->push_back(new Articulation(art)); |
254 |
} |
} |
|
art = lart->GetNextSubChunk(); |
|
255 |
} |
} |
256 |
} |
} |
257 |
} |
} |
592 |
} |
} |
593 |
|
|
594 |
void Resource::GenerateDLSID(dlsid_t* pDLSID) { |
void Resource::GenerateDLSID(dlsid_t* pDLSID) { |
|
#if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE) |
|
595 |
#ifdef WIN32 |
#ifdef WIN32 |
596 |
UUID uuid; |
UUID uuid; |
597 |
UuidCreate(&uuid); |
UuidCreate(&uuid); |
616 |
pDLSID->abData[5] = uuid.byte13; |
pDLSID->abData[5] = uuid.byte13; |
617 |
pDLSID->abData[6] = uuid.byte14; |
pDLSID->abData[6] = uuid.byte14; |
618 |
pDLSID->abData[7] = uuid.byte15; |
pDLSID->abData[7] = uuid.byte15; |
619 |
#else |
#elif defined(HAVE_UUID_GENERATE) |
620 |
uuid_t uuid; |
uuid_t uuid; |
621 |
uuid_generate(uuid); |
uuid_generate(uuid); |
622 |
pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24; |
pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24; |
623 |
pDLSID->usData2 = uuid[4] | uuid[5] << 8; |
pDLSID->usData2 = uuid[4] | uuid[5] << 8; |
624 |
pDLSID->usData3 = uuid[6] | uuid[7] << 8; |
pDLSID->usData3 = uuid[6] | uuid[7] << 8; |
625 |
memcpy(pDLSID->abData, &uuid[8], 8); |
memcpy(pDLSID->abData, &uuid[8], 8); |
626 |
#endif |
#else |
627 |
|
# error "Missing support for uuid generation" |
628 |
#endif |
#endif |
629 |
} |
} |
630 |
|
|
1199 |
if (pSample) return pSample; |
if (pSample) return pSample; |
1200 |
File* file = (File*) GetParent()->GetParent(); |
File* file = (File*) GetParent()->GetParent(); |
1201 |
uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
uint64_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex]; |
1202 |
Sample* sample = file->GetFirstSample(); |
size_t i = 0; |
1203 |
while (sample) { |
for (Sample* sample = file->GetSample(i); sample; |
1204 |
|
sample = file->GetSample(++i)) |
1205 |
|
{ |
1206 |
if (sample->ullWavePoolOffset == soughtoffset) return (pSample = sample); |
if (sample->ullWavePoolOffset == soughtoffset) return (pSample = sample); |
|
sample = file->GetNextSample(); |
|
1207 |
} |
} |
1208 |
return NULL; |
return NULL; |
1209 |
} |
} |
1394 |
pRegions = NULL; |
pRegions = NULL; |
1395 |
} |
} |
1396 |
|
|
1397 |
|
/** |
1398 |
|
* Returns the amount of regions of this instrument. |
1399 |
|
* |
1400 |
|
* @see GetRegionAt() |
1401 |
|
*/ |
1402 |
|
size_t Instrument::CountRegions() { |
1403 |
|
if (!pRegions) LoadRegions(); |
1404 |
|
if (!pRegions) return 0; |
1405 |
|
return pRegions->size(); |
1406 |
|
} |
1407 |
|
|
1408 |
|
/** |
1409 |
|
* Returns Region at supplied @a pos position within the region list of |
1410 |
|
* this instrument. If supplied @a pos is out of bounds then @c NULL is |
1411 |
|
* returned. |
1412 |
|
* |
1413 |
|
* @param pos - position of sought Region in region list |
1414 |
|
* @returns pointer address to requested region or @c NULL if @a pos is |
1415 |
|
* out of bounds |
1416 |
|
* @see CountRegions() |
1417 |
|
*/ |
1418 |
|
Region* Instrument::GetRegionAt(size_t pos) { |
1419 |
|
if (!pRegions) LoadRegions(); |
1420 |
|
if (!pRegions) return NULL; |
1421 |
|
if (pos >= pRegions->size()) return NULL; |
1422 |
|
return (*pRegions)[pos]; |
1423 |
|
} |
1424 |
|
|
1425 |
|
/** |
1426 |
|
* Returns the first Region of the instrument. You have to call this |
1427 |
|
* method once before you use GetNextRegion(). |
1428 |
|
* |
1429 |
|
* @returns pointer address to first region or NULL if there is none |
1430 |
|
* @see GetNextRegion() |
1431 |
|
* @deprecated This method is not reentrant-safe, use GetRegionAt() |
1432 |
|
* instead. |
1433 |
|
*/ |
1434 |
Region* Instrument::GetFirstRegion() { |
Region* Instrument::GetFirstRegion() { |
1435 |
if (!pRegions) LoadRegions(); |
if (!pRegions) LoadRegions(); |
1436 |
if (!pRegions) return NULL; |
if (!pRegions) return NULL; |
1438 |
return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL; |
return (RegionsIterator != pRegions->end()) ? *RegionsIterator : NULL; |
1439 |
} |
} |
1440 |
|
|
1441 |
|
/** |
1442 |
|
* Returns the next Region of the instrument. You have to call |
1443 |
|
* GetFirstRegion() once before you can use this method. By calling this |
1444 |
|
* method multiple times it iterates through the available Regions. |
1445 |
|
* |
1446 |
|
* @returns pointer address to the next region or NULL if end reached |
1447 |
|
* @see GetFirstRegion() |
1448 |
|
* @deprecated This method is not reentrant-safe, use GetRegionAt() |
1449 |
|
* instead. |
1450 |
|
*/ |
1451 |
Region* Instrument::GetNextRegion() { |
Region* Instrument::GetNextRegion() { |
1452 |
if (!pRegions) return NULL; |
if (!pRegions) return NULL; |
1453 |
RegionsIterator++; |
RegionsIterator++; |
1459 |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
1460 |
if (lrgn) { |
if (lrgn) { |
1461 |
uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN; // prefer regions level 2 |
uint32_t regionCkType = (lrgn->GetSubList(LIST_TYPE_RGN2)) ? LIST_TYPE_RGN2 : LIST_TYPE_RGN; // prefer regions level 2 |
1462 |
RIFF::List* rgn = lrgn->GetFirstSubList(); |
size_t i = 0; |
1463 |
while (rgn) { |
for (RIFF::List* rgn = lrgn->GetSubListAt(i); rgn; |
1464 |
|
rgn = lrgn->GetSubListAt(++i)) |
1465 |
|
{ |
1466 |
if (rgn->GetListType() == regionCkType) { |
if (rgn->GetListType() == regionCkType) { |
1467 |
pRegions->push_back(new Region(this, rgn)); |
pRegions->push_back(new Region(this, rgn)); |
1468 |
} |
} |
|
rgn = lrgn->GetNextSubList(); |
|
1469 |
} |
} |
1470 |
} |
} |
1471 |
} |
} |
1476 |
if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN); |
if (!lrgn) lrgn = pCkInstrument->AddSubList(LIST_TYPE_LRGN); |
1477 |
RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN); |
RIFF::List* rgn = lrgn->AddSubList(LIST_TYPE_RGN); |
1478 |
Region* pNewRegion = new Region(this, rgn); |
Region* pNewRegion = new Region(this, rgn); |
1479 |
|
const size_t idxIt = RegionsIterator - pRegions->begin(); |
1480 |
pRegions->push_back(pNewRegion); |
pRegions->push_back(pNewRegion); |
1481 |
|
RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size()); // avoid iterator invalidation |
1482 |
Regions = (uint32_t) pRegions->size(); |
Regions = (uint32_t) pRegions->size(); |
1483 |
return pNewRegion; |
return pNewRegion; |
1484 |
} |
} |
1486 |
void Instrument::MoveRegion(Region* pSrc, Region* pDst) { |
void Instrument::MoveRegion(Region* pSrc, Region* pDst) { |
1487 |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN); |
1488 |
lrgn->MoveSubChunk(pSrc->pCkRegion, (RIFF::Chunk*) (pDst ? pDst->pCkRegion : 0)); |
lrgn->MoveSubChunk(pSrc->pCkRegion, (RIFF::Chunk*) (pDst ? pDst->pCkRegion : 0)); |
1489 |
|
for (size_t i = 0; i < pRegions->size(); ++i) { |
1490 |
pRegions->remove(pSrc); |
if ((*pRegions)[i] == pSrc) { |
1491 |
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst); |
const size_t idxIt = RegionsIterator - pRegions->begin(); |
1492 |
pRegions->insert(iter, pSrc); |
pRegions->erase(pRegions->begin() + i); |
1493 |
|
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst); |
1494 |
|
pRegions->insert(iter, pSrc); |
1495 |
|
RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size()); // avoid iterator invalidation |
1496 |
|
} |
1497 |
|
} |
1498 |
} |
} |
1499 |
|
|
1500 |
void Instrument::DeleteRegion(Region* pRegion) { |
void Instrument::DeleteRegion(Region* pRegion) { |
1501 |
if (!pRegions) return; |
if (!pRegions) return; |
1502 |
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion); |
RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion); |
1503 |
if (iter == pRegions->end()) return; |
if (iter == pRegions->end()) return; |
1504 |
|
const size_t idxIt = RegionsIterator - pRegions->begin(); |
1505 |
pRegions->erase(iter); |
pRegions->erase(iter); |
1506 |
|
RegionsIterator = pRegions->begin() + std::min(idxIt, pRegions->size()); // avoid iterator invalidation |
1507 |
Regions = (uint32_t) pRegions->size(); |
Regions = (uint32_t) pRegions->size(); |
1508 |
pRegion->DeleteChunks(); |
pRegion->DeleteChunks(); |
1509 |
delete pRegion; |
delete pRegion; |
1618 |
void Instrument::CopyAssign(const Instrument* orig) { |
void Instrument::CopyAssign(const Instrument* orig) { |
1619 |
CopyAssignCore(orig); |
CopyAssignCore(orig); |
1620 |
// delete all regions first |
// delete all regions first |
1621 |
while (Regions) DeleteRegion(GetFirstRegion()); |
while (Regions) DeleteRegion(GetRegionAt(0)); |
1622 |
// now recreate and copy regions |
// now recreate and copy regions |
1623 |
{ |
{ |
1624 |
RegionList::const_iterator it = orig->pRegions->begin(); |
RegionList::const_iterator it = orig->pRegions->begin(); |
1754 |
delete pRIFF; |
delete pRIFF; |
1755 |
} |
} |
1756 |
|
|
1757 |
|
/** |
1758 |
|
* Returns Sample object of @a index. |
1759 |
|
* |
1760 |
|
* @param index - position of sample in sample list (0..n) |
1761 |
|
* @returns sample object or NULL if index is out of bounds |
1762 |
|
*/ |
1763 |
|
Sample* File::GetSample(size_t index) { |
1764 |
|
if (!pSamples) LoadSamples(); |
1765 |
|
if (!pSamples) return NULL; |
1766 |
|
if (index >= pSamples->size()) return NULL; |
1767 |
|
return (*pSamples)[index]; |
1768 |
|
} |
1769 |
|
|
1770 |
|
/** |
1771 |
|
* Returns a pointer to the first <i>Sample</i> object of the file, |
1772 |
|
* <i>NULL</i> otherwise. |
1773 |
|
* |
1774 |
|
* @deprecated This method is not reentrant-safe, use GetSample() |
1775 |
|
* instead. |
1776 |
|
*/ |
1777 |
Sample* File::GetFirstSample() { |
Sample* File::GetFirstSample() { |
1778 |
if (!pSamples) LoadSamples(); |
if (!pSamples) LoadSamples(); |
1779 |
if (!pSamples) return NULL; |
if (!pSamples) return NULL; |
1781 |
return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL; |
return (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL; |
1782 |
} |
} |
1783 |
|
|
1784 |
|
/** |
1785 |
|
* Returns a pointer to the next <i>Sample</i> object of the file, |
1786 |
|
* <i>NULL</i> otherwise. |
1787 |
|
* |
1788 |
|
* @deprecated This method is not reentrant-safe, use GetSample() |
1789 |
|
* instead. |
1790 |
|
*/ |
1791 |
Sample* File::GetNextSample() { |
Sample* File::GetNextSample() { |
1792 |
if (!pSamples) return NULL; |
if (!pSamples) return NULL; |
1793 |
SamplesIterator++; |
SamplesIterator++; |
1800 |
if (wvpl) { |
if (wvpl) { |
1801 |
file_offset_t wvplFileOffset = wvpl->GetFilePos() - |
file_offset_t wvplFileOffset = wvpl->GetFilePos() - |
1802 |
wvpl->GetPos(); // should be zero, but just to be sure |
wvpl->GetPos(); // should be zero, but just to be sure |
1803 |
RIFF::List* wave = wvpl->GetFirstSubList(); |
size_t i = 0; |
1804 |
while (wave) { |
for (RIFF::List* wave = wvpl->GetSubListAt(i); wave; |
1805 |
|
wave = wvpl->GetSubListAt(++i)) |
1806 |
|
{ |
1807 |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
1808 |
file_offset_t waveFileOffset = wave->GetFilePos() - |
file_offset_t waveFileOffset = wave->GetFilePos() - |
1809 |
wave->GetPos(); // should be zero, but just to be sure |
wave->GetPos(); // should be zero, but just to be sure |
1810 |
pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset)); |
pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset)); |
1811 |
} |
} |
|
wave = wvpl->GetNextSubList(); |
|
1812 |
} |
} |
1813 |
} |
} |
1814 |
else { // Seen a dwpl list chunk instead of a wvpl list chunk in some file (officially not DLS compliant) |
else { // Seen a dwpl list chunk instead of a wvpl list chunk in some file (officially not DLS compliant) |
1816 |
if (dwpl) { |
if (dwpl) { |
1817 |
file_offset_t dwplFileOffset = dwpl->GetFilePos() - |
file_offset_t dwplFileOffset = dwpl->GetFilePos() - |
1818 |
dwpl->GetPos(); // should be zero, but just to be sure |
dwpl->GetPos(); // should be zero, but just to be sure |
1819 |
RIFF::List* wave = dwpl->GetFirstSubList(); |
size_t i = 0; |
1820 |
while (wave) { |
for (RIFF::List* wave = dwpl->GetSubListAt(i); wave; |
1821 |
|
wave = dwpl->GetSubListAt(++i)) |
1822 |
|
{ |
1823 |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
if (wave->GetListType() == LIST_TYPE_WAVE) { |
1824 |
file_offset_t waveFileOffset = wave->GetFilePos() - |
file_offset_t waveFileOffset = wave->GetFilePos() - |
1825 |
wave->GetPos(); // should be zero, but just to be sure |
wave->GetPos(); // should be zero, but just to be sure |
1826 |
pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset)); |
pSamples->push_back(new Sample(this, wave, waveFileOffset - dwplFileOffset)); |
1827 |
} |
} |
|
wave = dwpl->GetNextSubList(); |
|
1828 |
} |
} |
1829 |
} |
} |
1830 |
} |
} |
1844 |
// create new Sample object and its respective 'wave' list chunk |
// create new Sample object and its respective 'wave' list chunk |
1845 |
RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE); |
RIFF::List* wave = wvpl->AddSubList(LIST_TYPE_WAVE); |
1846 |
Sample* pSample = new Sample(this, wave, 0 /*arbitrary value, we update offsets when we save*/); |
Sample* pSample = new Sample(this, wave, 0 /*arbitrary value, we update offsets when we save*/); |
1847 |
|
const size_t idxIt = SamplesIterator - pSamples->begin(); |
1848 |
pSamples->push_back(pSample); |
pSamples->push_back(pSample); |
1849 |
|
SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size()); // avoid iterator invalidation |
1850 |
return pSample; |
return pSample; |
1851 |
} |
} |
1852 |
|
|
1861 |
if (!pSamples) return; |
if (!pSamples) return; |
1862 |
SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample); |
SampleList::iterator iter = find(pSamples->begin(), pSamples->end(), pSample); |
1863 |
if (iter == pSamples->end()) return; |
if (iter == pSamples->end()) return; |
1864 |
|
const size_t idxIt = SamplesIterator - pSamples->begin(); |
1865 |
pSamples->erase(iter); |
pSamples->erase(iter); |
1866 |
|
SamplesIterator = pSamples->begin() + std::min(idxIt, pSamples->size()); // avoid iterator invalidation |
1867 |
pSample->DeleteChunks(); |
pSample->DeleteChunks(); |
1868 |
delete pSample; |
delete pSample; |
1869 |
} |
} |
1870 |
|
|
1871 |
|
/** |
1872 |
|
* Returns the instrument with the given @a index from the list of |
1873 |
|
* instruments of this file. |
1874 |
|
* |
1875 |
|
* @param index - number of the sought instrument (0..n) |
1876 |
|
* @returns sought instrument or NULL if there's no such instrument |
1877 |
|
*/ |
1878 |
|
Instrument* File::GetInstrument(size_t index) { |
1879 |
|
if (!pInstruments) LoadInstruments(); |
1880 |
|
if (!pInstruments) return NULL; |
1881 |
|
if (index >= pInstruments->size()) return NULL; |
1882 |
|
return (*pInstruments)[index]; |
1883 |
|
} |
1884 |
|
|
1885 |
|
/** |
1886 |
|
* Returns a pointer to the first <i>Instrument</i> object of the file, |
1887 |
|
* <i>NULL</i> otherwise. |
1888 |
|
* |
1889 |
|
* @deprecated This method is not reentrant-safe, use GetInstrument() |
1890 |
|
* instead. |
1891 |
|
*/ |
1892 |
Instrument* File::GetFirstInstrument() { |
Instrument* File::GetFirstInstrument() { |
1893 |
if (!pInstruments) LoadInstruments(); |
if (!pInstruments) LoadInstruments(); |
1894 |
if (!pInstruments) return NULL; |
if (!pInstruments) return NULL; |
1896 |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
return (InstrumentsIterator != pInstruments->end()) ? *InstrumentsIterator : NULL; |
1897 |
} |
} |
1898 |
|
|
1899 |
|
/** |
1900 |
|
* Returns a pointer to the next <i>Instrument</i> object of the file, |
1901 |
|
* <i>NULL</i> otherwise. |
1902 |
|
* |
1903 |
|
* @deprecated This method is not reentrant-safe, use GetInstrument() |
1904 |
|
* instead. |
1905 |
|
*/ |
1906 |
Instrument* File::GetNextInstrument() { |
Instrument* File::GetNextInstrument() { |
1907 |
if (!pInstruments) return NULL; |
if (!pInstruments) return NULL; |
1908 |
InstrumentsIterator++; |
InstrumentsIterator++; |
1913 |
if (!pInstruments) pInstruments = new InstrumentList; |
if (!pInstruments) pInstruments = new InstrumentList; |
1914 |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
1915 |
if (lstInstruments) { |
if (lstInstruments) { |
1916 |
RIFF::List* lstInstr = lstInstruments->GetFirstSubList(); |
size_t i = 0; |
1917 |
while (lstInstr) { |
for (RIFF::List* lstInstr = lstInstruments->GetSubListAt(i); |
1918 |
|
lstInstr; lstInstr = lstInstruments->GetSubListAt(++i)) |
1919 |
|
{ |
1920 |
if (lstInstr->GetListType() == LIST_TYPE_INS) { |
if (lstInstr->GetListType() == LIST_TYPE_INS) { |
1921 |
pInstruments->push_back(new Instrument(this, lstInstr)); |
pInstruments->push_back(new Instrument(this, lstInstr)); |
1922 |
} |
} |
|
lstInstr = lstInstruments->GetNextSubList(); |
|
1923 |
} |
} |
1924 |
} |
} |
1925 |
} |
} |
1937 |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS); |
1938 |
RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS); |
RIFF::List* lstInstr = lstInstruments->AddSubList(LIST_TYPE_INS); |
1939 |
Instrument* pInstrument = new Instrument(this, lstInstr); |
Instrument* pInstrument = new Instrument(this, lstInstr); |
1940 |
|
const size_t idxIt = InstrumentsIterator - pInstruments->begin(); |
1941 |
pInstruments->push_back(pInstrument); |
pInstruments->push_back(pInstrument); |
1942 |
|
InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size()); // avoid iterator invalidation |
1943 |
return pInstrument; |
return pInstrument; |
1944 |
} |
} |
1945 |
|
|
1954 |
if (!pInstruments) return; |
if (!pInstruments) return; |
1955 |
InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument); |
InstrumentList::iterator iter = find(pInstruments->begin(), pInstruments->end(), pInstrument); |
1956 |
if (iter == pInstruments->end()) return; |
if (iter == pInstruments->end()) return; |
1957 |
|
const size_t idxIt = InstrumentsIterator - pInstruments->begin(); |
1958 |
pInstruments->erase(iter); |
pInstruments->erase(iter); |
1959 |
|
InstrumentsIterator = pInstruments->begin() + std::min(idxIt, pInstruments->size()); // avoid iterator invalidation |
1960 |
pInstrument->DeleteChunks(); |
pInstrument->DeleteChunks(); |
1961 |
delete pInstrument; |
delete pInstrument; |
1962 |
} |
} |