3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2008 Christian Schoenebeck * |
* Copyright (C) 2005 - 2022 Christian Schoenebeck * |
7 |
* Copyright (C) 2009 - 2012 Christian Schoenebeck and Grigor Iliev * |
* Copyright (C) 2009 - 2012 Grigor Iliev * |
8 |
* * |
* * |
9 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
10 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
93 |
|
|
94 |
::sfz::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) { |
::sfz::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) { |
95 |
// get sfz file from internal sfz file manager |
// get sfz file from internal sfz file manager |
96 |
::sfz::File* pSfz = Sfzs.Borrow(Key.FileName, reinterpret_cast<SfzConsumer*>(Key.Index)); // conversion kinda hackish :/ |
::sfz::File* pSfz = Sfzs.Borrow(Key.FileName, &Sfzs); |
97 |
|
|
98 |
dmsg(1,("Loading sfz instrument ('%s',%d)...",Key.FileName.c_str(),Key.Index)); |
dmsg(1,("Loading sfz instrument ('%s',%d)...",Key.FileName.c_str(),Key.Index)); |
99 |
if (Key.Index) { |
if (Key.Index) { |
166 |
dmsg(1,("Loading sfz file \'%s\'...", Key.c_str())); |
dmsg(1,("Loading sfz file \'%s\'...", Key.c_str())); |
167 |
::sfz::File* pSfz = new ::sfz::File(Key, &sampleManager); |
::sfz::File* pSfz = new ::sfz::File(Key, &sampleManager); |
168 |
dmsg(1,("OK\n")); |
dmsg(1,("OK\n")); |
169 |
|
InstrumentManagerThread* thread = parent->GetInstrumentManagerThread(); |
170 |
|
// let this code be executed periodically by instrument manager thread |
171 |
|
// in order to automatically reload this .sfz file whenever it was |
172 |
|
// modified, e.g. by some external text editor application |
173 |
|
thread->AddPeriodicJob("autoreload_sfz:" + Key, [this,Key,pSfz]{ |
174 |
|
if (pSfz->checkFileModified()) { |
175 |
|
dmsg(1,("Sfz file was modified: auto reloading '%s'\n", Key.c_str())); |
176 |
|
// passing NULL as consumer here instead of 'this' to ensure |
177 |
|
// that the ResourceToBeUpdated() and ResourceUpdated() method |
178 |
|
// pair below is executed |
179 |
|
Update(pSfz, NULL); |
180 |
|
} |
181 |
|
}); |
182 |
return pSfz; |
return pSfz; |
183 |
} |
} |
184 |
|
|
185 |
void InstrumentResourceManager::SfzResourceManager::Destroy(::sfz::File* pResource, void* pArg) { |
void InstrumentResourceManager::SfzResourceManager::Destroy(::sfz::File* pResource, void* pArg) { |
186 |
dmsg(1,("Freeing sfz file from memory...")); |
dmsg(1,("Freeing sfz file from memory...")); |
187 |
|
|
188 |
|
// stop periodic job previously scheduled above before freeing sfz file |
189 |
|
const String key = pResource->filename(); |
190 |
|
InstrumentManagerThread* thread = parent->GetInstrumentManagerThread(); |
191 |
|
thread->RemovePeriodicJob("autoreload_sfz:" + key); |
192 |
|
|
193 |
// Delete as much as possible of the sfz file. Some of the |
// Delete as much as possible of the sfz file. Some of the |
194 |
// regions and samples may still be in use - these |
// regions and samples may still be in use - these |
195 |
// will be deleted later by the HandBackRegion function. |
// will be deleted later by the HandBackRegion function. |
208 |
} |
} |
209 |
} |
} |
210 |
|
|
211 |
|
// free sfz file |
212 |
if (deleteInstrument) delete pResource; |
if (deleteInstrument) delete pResource; |
213 |
else dmsg(2,("keeping some samples that are in use...")); |
else dmsg(2,("keeping some samples that are in use...")); |
214 |
|
|
215 |
dmsg(1,("OK\n")); |
dmsg(1,("OK\n")); |
216 |
} |
} |
217 |
|
|
218 |
|
void InstrumentResourceManager::SfzResourceManager::ResourceToBeUpdated(::sfz::File* pResource, void*& pUpdateArg) { |
219 |
|
// Since the respective sfz::Instrument objects will already be |
220 |
|
// invalidated when ResourceUpdated() will be called subsequently, we |
221 |
|
// must assemble a list of the current sfz::Instrument objects being |
222 |
|
// subject of the .sfz file changed already here. |
223 |
|
std::set<::sfz::Instrument*>* pInstruments = new std::set<::sfz::Instrument*>(); |
224 |
|
{ |
225 |
|
std::vector<::sfz::Instrument*> instrumentsInUse = parent->Resources(false); |
226 |
|
for (size_t i = 0; i < instrumentsInUse.size(); i++) { |
227 |
|
::sfz::File* f = instrumentsInUse[i]->GetFile(); |
228 |
|
if (f == pResource) pInstruments->insert(instrumentsInUse[i]); |
229 |
|
} |
230 |
|
} |
231 |
|
pUpdateArg = pInstruments; |
232 |
|
} |
233 |
|
|
234 |
|
void InstrumentResourceManager::SfzResourceManager::ResourceUpdated(::sfz::File* pOldResource, ::sfz::File* pNewResource, void* pUpdateArg) { |
235 |
|
// force reload sfz::Instrument objects on engine channels that used that sfz file |
236 |
|
std::set<::sfz::Instrument*>* pInstruments = (std::set<::sfz::Instrument*>*)pUpdateArg; |
237 |
|
std::set<::sfz::Instrument*>::const_iterator it = pInstruments->begin(); |
238 |
|
std::set<::sfz::Instrument*>::const_iterator end = pInstruments->end(); |
239 |
|
for (; it != end; ++it) { |
240 |
|
::sfz::Instrument* instrument = *it; |
241 |
|
parent->Update(instrument, reinterpret_cast<SfzInstrConsumer*>(this)); |
242 |
|
} |
243 |
|
delete pInstruments; |
244 |
|
} |
245 |
|
|
246 |
}} // namespace LinuxSampler::sfz |
}} // namespace LinuxSampler::sfz |