1280 |
|
|
1281 |
void MainWindow::on_action_file_new() |
void MainWindow::on_action_file_new() |
1282 |
{ |
{ |
1283 |
|
m_SampleImportQueue.clear(); |
1284 |
} |
} |
1285 |
|
|
1286 |
void MainWindow::on_action_file_open() |
void MainWindow::on_action_file_open() |
1303 |
} |
} |
1304 |
instrument_menu->get_submenu()->items().clear(); |
instrument_menu->get_submenu()->items().clear(); |
1305 |
|
|
1306 |
|
m_SampleImportQueue.clear(); |
1307 |
m_refTreeModel->clear(); |
m_refTreeModel->clear(); |
1308 |
m_refSamplesTreeModel->clear(); |
m_refSamplesTreeModel->clear(); |
1309 |
if (file) delete file; |
if (file) delete file; |
1343 |
|
|
1344 |
void MainWindow::on_action_file_save() |
void MainWindow::on_action_file_save() |
1345 |
{ |
{ |
1346 |
|
if (!file) return; |
1347 |
|
file->Save(); |
1348 |
|
__import_queued_samples(); |
1349 |
} |
} |
1350 |
|
|
1351 |
void MainWindow::on_action_file_save_as() |
void MainWindow::on_action_file_save_as() |
1352 |
{ |
{ |
1353 |
|
if (!file) return; |
1354 |
Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE); |
Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE); |
1355 |
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
1356 |
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); |
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); |
1360 |
if (dialog.run() == Gtk::RESPONSE_OK) { |
if (dialog.run() == Gtk::RESPONSE_OK) { |
1361 |
printf("filename=%s\n", dialog.get_filename().c_str()); |
printf("filename=%s\n", dialog.get_filename().c_str()); |
1362 |
file->Save(dialog.get_filename()); |
file->Save(dialog.get_filename()); |
1363 |
|
__import_queued_samples(); |
1364 |
|
} |
1365 |
|
} |
1366 |
|
|
1367 |
|
// actually write the sample(s)' data to the gig file |
1368 |
|
void MainWindow::__import_queued_samples() { |
1369 |
|
Glib::ustring error_files; |
1370 |
|
for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) { |
1371 |
|
printf("Importing sample %s\n",(*iter).sample_path.c_str()); |
1372 |
|
SF_INFO info; |
1373 |
|
info.format = 0; |
1374 |
|
SNDFILE* hFile = sf_open((*iter).sample_path.c_str(), SFM_READ, &info); |
1375 |
|
try { |
1376 |
|
if (!hFile) throw std::string("could not open file"); |
1377 |
|
// determine sample's bit depth |
1378 |
|
int bitdepth; |
1379 |
|
switch (info.format & 0xff) { |
1380 |
|
case SF_FORMAT_PCM_S8: |
1381 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1382 |
|
break; |
1383 |
|
case SF_FORMAT_PCM_16: |
1384 |
|
bitdepth = 16; |
1385 |
|
break; |
1386 |
|
case SF_FORMAT_PCM_24: |
1387 |
|
bitdepth = 32; // we simply convert to 32 bit for now |
1388 |
|
break; |
1389 |
|
case SF_FORMAT_PCM_32: |
1390 |
|
bitdepth = 32; |
1391 |
|
break; |
1392 |
|
case SF_FORMAT_PCM_U8: |
1393 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1394 |
|
break; |
1395 |
|
case SF_FORMAT_FLOAT: |
1396 |
|
bitdepth = 32; |
1397 |
|
break; |
1398 |
|
case SF_FORMAT_DOUBLE: |
1399 |
|
bitdepth = 32; // I guess we will always truncate this to 32 bit |
1400 |
|
break; |
1401 |
|
default: |
1402 |
|
sf_close(hFile); // close sound file |
1403 |
|
throw std::string("format not supported"); // unsupported subformat (yet?) |
1404 |
|
} |
1405 |
|
// allocate appropriate copy buffer (TODO: for now we copy it in one piece, might be tough for very long samples) |
1406 |
|
// and copy sample data into buffer |
1407 |
|
int8_t* buffer = NULL; |
1408 |
|
switch (bitdepth) { |
1409 |
|
case 16: |
1410 |
|
buffer = new int8_t[2 * info.channels * info.frames]; |
1411 |
|
sf_readf_short(hFile, (short*) buffer, info.frames); // libsndfile does the conversion for us (if needed) |
1412 |
|
break; |
1413 |
|
case 32: |
1414 |
|
buffer = new int8_t[4 * info.channels * info.frames]; |
1415 |
|
sf_readf_int(hFile, (int*) buffer, info.frames); // libsndfile does the conversion for us (if needed) |
1416 |
|
break; |
1417 |
|
} |
1418 |
|
// write from buffer directly (physically) into .gig file |
1419 |
|
(*iter).gig_sample->Write(buffer, info.frames); |
1420 |
|
// cleanup |
1421 |
|
sf_close(hFile); |
1422 |
|
delete buffer; |
1423 |
|
// on success we remove the sample from the import queue, otherwise keep it, maybe it works the next time ? |
1424 |
|
m_SampleImportQueue.erase(iter); |
1425 |
|
} catch (std::string what) { // remember the files that made trouble (and their cause) |
1426 |
|
if (error_files.size()) error_files += "\n"; |
1427 |
|
error_files += (*iter).sample_path += " (" + what + ")"; |
1428 |
|
} |
1429 |
|
} |
1430 |
|
// show error message box when some sample(s) could not be imported |
1431 |
|
if (error_files.size()) { |
1432 |
|
Glib::ustring txt = "Could not import the following sample(s):\n" + error_files; |
1433 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); |
1434 |
|
msg.run(); |
1435 |
} |
} |
1436 |
} |
} |
1437 |
|
|
1764 |
int bitdepth; |
int bitdepth; |
1765 |
switch (info.format & 0xff) { |
switch (info.format & 0xff) { |
1766 |
case SF_FORMAT_PCM_S8: |
case SF_FORMAT_PCM_S8: |
1767 |
bitdepth = 8; |
bitdepth = 16; // we simply convert to 16 bit for now |
1768 |
break; |
break; |
1769 |
case SF_FORMAT_PCM_16: |
case SF_FORMAT_PCM_16: |
1770 |
bitdepth = 16; |
bitdepth = 16; |
1771 |
break; |
break; |
1772 |
case SF_FORMAT_PCM_24: |
case SF_FORMAT_PCM_24: |
1773 |
bitdepth = 24; |
bitdepth = 32; // we simply convert to 32 bit for now |
1774 |
break; |
break; |
1775 |
case SF_FORMAT_PCM_32: |
case SF_FORMAT_PCM_32: |
1776 |
bitdepth = 32; |
bitdepth = 32; |
1777 |
break; |
break; |
1778 |
|
case SF_FORMAT_PCM_U8: |
1779 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1780 |
|
break; |
1781 |
|
case SF_FORMAT_FLOAT: |
1782 |
|
bitdepth = 32; |
1783 |
|
break; |
1784 |
|
case SF_FORMAT_DOUBLE: |
1785 |
|
bitdepth = 32; // I guess we will always truncate this to 32 bit |
1786 |
|
break; |
1787 |
default: |
default: |
1788 |
sf_close(hFile); // close sound file |
sf_close(hFile); // close sound file |
1789 |
throw std::string("format not supported"); // unsupported subformat (yet?) |
throw std::string("format not supported"); // unsupported subformat (yet?) |
1790 |
} |
} |
1791 |
// add a new sample to the .gig file |
// add a new sample to the .gig file |
1792 |
gig::Sample* sample = file->AddSample(); |
gig::Sample* sample = file->AddSample(); |
1793 |
sample->pInfo->Name = (*iter).raw(); |
sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw(); // file name without path |
1794 |
sample->Channels = info.channels; |
sample->Channels = info.channels; |
1795 |
sample->BitDepth = bitdepth; |
sample->BitDepth = bitdepth; |
1796 |
sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels; |
sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels; |
1797 |
sample->SamplesPerSecond = info.samplerate; |
sample->SamplesPerSecond = info.samplerate; |
1798 |
// schedule resizing the sample (which will be done physically when File::Save() is called) |
// schedule resizing the sample (which will be done physically when File::Save() is called) |
1799 |
sample->Resize(info.frames); |
sample->Resize(info.frames); |
1800 |
|
// schedule that physical resize and sample import (data copying), performed when "Save" is requested |
1801 |
|
SampleImportItem sched_item; |
1802 |
|
sched_item.gig_sample = sample; |
1803 |
|
sched_item.sample_path = *iter; |
1804 |
|
m_SampleImportQueue.push_back(sched_item); |
1805 |
// add sample to the tree view |
// add sample to the tree view |
1806 |
Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(row.children()); |
Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(row.children()); |
1807 |
Gtk::TreeModel::Row rowSample = *iterSample; |
Gtk::TreeModel::Row rowSample = *iterSample; |
1839 |
} else if (sample) { |
} else if (sample) { |
1840 |
file->DeleteSample(sample); |
file->DeleteSample(sample); |
1841 |
} |
} |
1842 |
|
// if sample was just previously added, remove it from the import queue |
1843 |
|
if (sample) { |
1844 |
|
for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) { |
1845 |
|
if ((*iter).gig_sample == sample) { |
1846 |
|
m_SampleImportQueue.erase(iter); |
1847 |
|
break; |
1848 |
|
} |
1849 |
|
} |
1850 |
|
} |
1851 |
// remove respective row(s) from samples tree view |
// remove respective row(s) from samples tree view |
1852 |
m_refSamplesTreeModel->erase(it); |
m_refSamplesTreeModel->erase(it); |
1853 |
} catch (RIFF::Exception e) { |
} catch (RIFF::Exception e) { |