27 |
#if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6 |
#if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6 |
28 |
#define ABOUT_DIALOG |
#define ABOUT_DIALOG |
29 |
#include <gtkmm/aboutdialog.h> |
#include <gtkmm/aboutdialog.h> |
30 |
|
#include <gtkmm/messagedialog.h> |
31 |
#endif |
#endif |
32 |
|
|
33 |
|
#include <stdio.h> |
34 |
|
#include <sndfile.h> |
35 |
|
|
36 |
#define _(String) gettext(String) |
#define _(String) gettext(String) |
37 |
|
|
38 |
|
template<class T> inline std::string ToString(T o) { |
39 |
|
std::stringstream ss; |
40 |
|
ss << o; |
41 |
|
return ss.str(); |
42 |
|
} |
43 |
|
|
44 |
bool update_gui; |
bool update_gui; |
45 |
|
|
46 |
uint8_t& access_UnityNote(gig::DimensionRegion* dimreg) |
uint8_t& access_UnityNote(gig::DimensionRegion* dimreg) |
520 |
eSampleLoops("SampleLoops", &access_SampleLoops, 0, 1) |
eSampleLoops("SampleLoops", &access_SampleLoops, 0, 1) |
521 |
{ |
{ |
522 |
// set_border_width(5); |
// set_border_width(5); |
523 |
set_default_size(400, 200); |
// set_default_size(400, 200); |
524 |
|
|
525 |
|
|
526 |
add(m_VBox); |
add(m_VBox); |
533 |
m_TreeView.signal_button_press_event().connect_notify( |
m_TreeView.signal_button_press_event().connect_notify( |
534 |
sigc::mem_fun(*this, &MainWindow::on_button_release)); |
sigc::mem_fun(*this, &MainWindow::on_button_release)); |
535 |
|
|
536 |
// Add the TreeView, inside a ScrolledWindow, with the button underneath: |
// Add the TreeView tab, inside a ScrolledWindow, with the button underneath: |
537 |
m_ScrolledWindow.add(m_TreeView); |
m_ScrolledWindow.add(m_TreeView); |
538 |
m_ScrolledWindow.set_size_request(400, 600); |
// m_ScrolledWindow.set_size_request(200, 600); |
539 |
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
540 |
|
|
541 |
|
m_ScrolledWindowSamples.add(m_TreeViewSamples); |
542 |
|
m_ScrolledWindowSamples.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
543 |
|
|
544 |
|
|
545 |
for (int i = 0 ; i < 5 ; i++) { |
for (int i = 0 ; i < 5 ; i++) { |
546 |
table[i] = new Gtk::Table(3, 1); |
table[i] = new Gtk::Table(3, 1); |
547 |
table[i]->set_col_spacings(5); |
table[i]->set_col_spacings(5); |
791 |
m_Notebook.append_page(*table[2], "EG3"); |
m_Notebook.append_page(*table[2], "EG3"); |
792 |
m_Notebook.append_page(*table[3], "Velocity"); |
m_Notebook.append_page(*table[3], "Velocity"); |
793 |
m_Notebook.append_page(*table[4], "Misc"); |
m_Notebook.append_page(*table[4], "Misc"); |
794 |
m_Notebook.set_size_request(400, 500); |
// m_Notebook.set_size_request(400, 500); |
795 |
|
|
796 |
m_HPaned.add1(m_ScrolledWindow); |
m_TreeViewNotebook.set_size_request(300); |
797 |
|
m_HPaned.add1(m_TreeViewNotebook); |
798 |
m_HPaned.add2(m_Notebook); |
m_HPaned.add2(m_Notebook); |
799 |
|
|
800 |
|
|
801 |
|
m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples"); |
802 |
|
m_TreeViewNotebook.append_page(m_ScrolledWindow, "Instruments"); |
803 |
|
|
804 |
|
|
805 |
actionGroup = Gtk::ActionGroup::create(); |
actionGroup = Gtk::ActionGroup::create(); |
806 |
|
|
807 |
actionGroup->add(Gtk::Action::create("MenuFile", _("_File"))); |
actionGroup->add(Gtk::Action::create("MenuFile", _("_File"))); |
845 |
sigc::mem_fun( |
sigc::mem_fun( |
846 |
*this, &MainWindow::on_action_help_about)); |
*this, &MainWindow::on_action_help_about)); |
847 |
#endif |
#endif |
848 |
action = Gtk::Action::create("Remove", "Ta bort"); |
action = Gtk::Action::create("Remove", Gtk::Stock::REMOVE); |
849 |
actionGroup->add(action, |
actionGroup->add(action, |
850 |
sigc::mem_fun( |
sigc::mem_fun( |
851 |
*this, &MainWindow::hide)); |
*this, &MainWindow::hide)); |
852 |
|
|
853 |
|
// sample right-click popup actions |
854 |
|
actionGroup->add( |
855 |
|
Gtk::Action::create("SampleProperties", Gtk::Stock::PROPERTIES), |
856 |
|
sigc::mem_fun(*this, &MainWindow::on_action_sample_properties) |
857 |
|
); |
858 |
|
actionGroup->add( |
859 |
|
Gtk::Action::create("AddGroup", _("Add _Group")), |
860 |
|
sigc::mem_fun(*this, &MainWindow::on_action_add_group) |
861 |
|
); |
862 |
|
actionGroup->add( |
863 |
|
Gtk::Action::create("AddSample", _("Add _Sample(s)")), |
864 |
|
sigc::mem_fun(*this, &MainWindow::on_action_add_sample) |
865 |
|
); |
866 |
|
actionGroup->add( |
867 |
|
Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE), |
868 |
|
sigc::mem_fun(*this, &MainWindow::on_action_remove_sample) |
869 |
|
); |
870 |
|
|
871 |
uiManager = Gtk::UIManager::create(); |
uiManager = Gtk::UIManager::create(); |
872 |
uiManager->insert_action_group(actionGroup); |
uiManager->insert_action_group(actionGroup); |
873 |
// add_accel_group(uiManager->get_accel_group()); |
// add_accel_group(uiManager->get_accel_group()); |
898 |
" <menuitem action='InstrProperties'/>" |
" <menuitem action='InstrProperties'/>" |
899 |
" <menuitem action='Remove'/>" |
" <menuitem action='Remove'/>" |
900 |
" </popup>" |
" </popup>" |
901 |
|
" <popup name='SamplePopupMenu'>" |
902 |
|
" <menuitem action='SampleProperties'/>" |
903 |
|
" <menuitem action='AddGroup'/>" |
904 |
|
" <menuitem action='AddSample'/>" |
905 |
|
" <separator/>" |
906 |
|
" <menuitem action='RemoveSample'/>" |
907 |
|
" </popup>" |
908 |
"</ui>"; |
"</ui>"; |
909 |
uiManager->add_ui_from_string(ui_info); |
uiManager->add_ui_from_string(ui_info); |
910 |
|
|
930 |
m_TreeView.append_column("Instrument", m_Columns.m_col_name); |
m_TreeView.append_column("Instrument", m_Columns.m_col_name); |
931 |
m_TreeView.set_headers_visible(false); |
m_TreeView.set_headers_visible(false); |
932 |
|
|
933 |
|
// create samples treeview (including its data model) |
934 |
|
m_refSamplesTreeModel = Gtk::TreeStore::create(m_SamplesModel); |
935 |
|
m_TreeViewSamples.set_model(m_refSamplesTreeModel); |
936 |
|
m_TreeViewSamples.append_column("Samples", m_SamplesModel.m_col_name); |
937 |
|
m_TreeViewSamples.set_headers_visible(false); |
938 |
|
m_TreeViewSamples.signal_button_press_event().connect_notify( |
939 |
|
sigc::mem_fun(*this, &MainWindow::on_sample_treeview_button_release) |
940 |
|
); |
941 |
|
|
942 |
file = 0; |
file = 0; |
943 |
|
|
944 |
show_all_children(); |
show_all_children(); |
1285 |
|
|
1286 |
void MainWindow::on_action_file_new() |
void MainWindow::on_action_file_new() |
1287 |
{ |
{ |
1288 |
|
m_SampleImportQueue.clear(); |
1289 |
} |
} |
1290 |
|
|
1291 |
void MainWindow::on_action_file_open() |
void MainWindow::on_action_file_open() |
1308 |
} |
} |
1309 |
instrument_menu->get_submenu()->items().clear(); |
instrument_menu->get_submenu()->items().clear(); |
1310 |
|
|
1311 |
|
m_SampleImportQueue.clear(); |
1312 |
m_refTreeModel->clear(); |
m_refTreeModel->clear(); |
1313 |
|
m_refSamplesTreeModel->clear(); |
1314 |
if (file) delete file; |
if (file) delete file; |
1315 |
|
|
1316 |
// getInfo(dialog.get_filename().c_str(), *this); |
// getInfo(dialog.get_filename().c_str(), *this); |
1348 |
|
|
1349 |
void MainWindow::on_action_file_save() |
void MainWindow::on_action_file_save() |
1350 |
{ |
{ |
1351 |
|
if (!file) return; |
1352 |
|
file->Save(); |
1353 |
|
__import_queued_samples(); |
1354 |
} |
} |
1355 |
|
|
1356 |
void MainWindow::on_action_file_save_as() |
void MainWindow::on_action_file_save_as() |
1357 |
{ |
{ |
1358 |
|
if (!file) return; |
1359 |
Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE); |
Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE); |
1360 |
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
1361 |
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); |
dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); |
1365 |
if (dialog.run() == Gtk::RESPONSE_OK) { |
if (dialog.run() == Gtk::RESPONSE_OK) { |
1366 |
printf("filename=%s\n", dialog.get_filename().c_str()); |
printf("filename=%s\n", dialog.get_filename().c_str()); |
1367 |
file->Save(dialog.get_filename()); |
file->Save(dialog.get_filename()); |
1368 |
|
__import_queued_samples(); |
1369 |
|
} |
1370 |
|
} |
1371 |
|
|
1372 |
|
// actually write the sample(s)' data to the gig file |
1373 |
|
void MainWindow::__import_queued_samples() { |
1374 |
|
Glib::ustring error_files; |
1375 |
|
for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) { |
1376 |
|
printf("Importing sample %s\n",(*iter).sample_path.c_str()); |
1377 |
|
SF_INFO info; |
1378 |
|
info.format = 0; |
1379 |
|
SNDFILE* hFile = sf_open((*iter).sample_path.c_str(), SFM_READ, &info); |
1380 |
|
try { |
1381 |
|
if (!hFile) throw std::string("could not open file"); |
1382 |
|
// determine sample's bit depth |
1383 |
|
int bitdepth; |
1384 |
|
switch (info.format & 0xff) { |
1385 |
|
case SF_FORMAT_PCM_S8: |
1386 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1387 |
|
break; |
1388 |
|
case SF_FORMAT_PCM_16: |
1389 |
|
bitdepth = 16; |
1390 |
|
break; |
1391 |
|
case SF_FORMAT_PCM_24: |
1392 |
|
bitdepth = 32; // we simply convert to 32 bit for now |
1393 |
|
break; |
1394 |
|
case SF_FORMAT_PCM_32: |
1395 |
|
bitdepth = 32; |
1396 |
|
break; |
1397 |
|
case SF_FORMAT_PCM_U8: |
1398 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1399 |
|
break; |
1400 |
|
case SF_FORMAT_FLOAT: |
1401 |
|
bitdepth = 32; |
1402 |
|
break; |
1403 |
|
case SF_FORMAT_DOUBLE: |
1404 |
|
bitdepth = 32; // I guess we will always truncate this to 32 bit |
1405 |
|
break; |
1406 |
|
default: |
1407 |
|
sf_close(hFile); // close sound file |
1408 |
|
throw std::string("format not supported"); // unsupported subformat (yet?) |
1409 |
|
} |
1410 |
|
// allocate appropriate copy buffer (TODO: for now we copy it in one piece, might be tough for very long samples) |
1411 |
|
// and copy sample data into buffer |
1412 |
|
int8_t* buffer = NULL; |
1413 |
|
switch (bitdepth) { |
1414 |
|
case 16: |
1415 |
|
buffer = new int8_t[2 * info.channels * info.frames]; |
1416 |
|
sf_readf_short(hFile, (short*) buffer, info.frames); // libsndfile does the conversion for us (if needed) |
1417 |
|
break; |
1418 |
|
case 32: |
1419 |
|
buffer = new int8_t[4 * info.channels * info.frames]; |
1420 |
|
sf_readf_int(hFile, (int*) buffer, info.frames); // libsndfile does the conversion for us (if needed) |
1421 |
|
break; |
1422 |
|
} |
1423 |
|
// write from buffer directly (physically) into .gig file |
1424 |
|
(*iter).gig_sample->Write(buffer, info.frames); |
1425 |
|
// cleanup |
1426 |
|
sf_close(hFile); |
1427 |
|
delete buffer; |
1428 |
|
// on success we remove the sample from the import queue, otherwise keep it, maybe it works the next time ? |
1429 |
|
m_SampleImportQueue.erase(iter); |
1430 |
|
} catch (std::string what) { // remember the files that made trouble (and their cause) |
1431 |
|
if (error_files.size()) error_files += "\n"; |
1432 |
|
error_files += (*iter).sample_path += " (" + what + ")"; |
1433 |
|
} |
1434 |
|
} |
1435 |
|
// show error message box when some sample(s) could not be imported |
1436 |
|
if (error_files.size()) { |
1437 |
|
Glib::ustring txt = "Could not import the following sample(s):\n" + error_files; |
1438 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); |
1439 |
|
msg.run(); |
1440 |
} |
} |
1441 |
} |
} |
1442 |
|
|
1622 |
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument")); |
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument")); |
1623 |
|
|
1624 |
int instrument_index = 0; |
int instrument_index = 0; |
1625 |
|
Gtk::RadioMenuItem::Group instrument_group; |
1626 |
for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ; |
for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ; |
1627 |
instrument = gig->GetNextInstrument()) { |
instrument = gig->GetNextInstrument()) { |
1628 |
Gtk::TreeModel::iterator iter = m_refTreeModel->append(); |
Gtk::TreeModel::iterator iter = m_refTreeModel->append(); |
1630 |
row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str(); |
row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str(); |
1631 |
row[m_Columns.m_col_instr] = instrument; |
row[m_Columns.m_col_instr] = instrument; |
1632 |
// create a menu item for this instrument |
// create a menu item for this instrument |
1633 |
Gtk::MenuItem* item= new Gtk::MenuItem(instrument->pInfo->Name.c_str()); |
Gtk::RadioMenuItem* item= new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str()); |
1634 |
instrument_menu->get_submenu()->append(*item); |
instrument_menu->get_submenu()->append(*item); |
1635 |
item->signal_activate().connect( |
item->signal_activate().connect( |
1636 |
sigc::bind( |
sigc::bind( |
1642 |
} |
} |
1643 |
instrument_menu->show(); |
instrument_menu->show(); |
1644 |
instrument_menu->get_submenu()->show_all_children(); |
instrument_menu->get_submenu()->show_all_children(); |
1645 |
|
|
1646 |
|
for (gig::Group* group = gig->GetFirstGroup(); group; group = gig->GetNextGroup()) { |
1647 |
|
if (group->Name != "") { |
1648 |
|
Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append(); |
1649 |
|
Gtk::TreeModel::Row rowGroup = *iterGroup; |
1650 |
|
rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str(); |
1651 |
|
rowGroup[m_SamplesModel.m_col_group] = group; |
1652 |
|
rowGroup[m_SamplesModel.m_col_sample] = NULL; |
1653 |
|
for (gig::Sample* sample = group->GetFirstSample(); sample; sample = group->GetNextSample()) { |
1654 |
|
Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(rowGroup.children()); |
1655 |
|
Gtk::TreeModel::Row rowSample = *iterSample; |
1656 |
|
rowSample[m_SamplesModel.m_col_name] = sample->pInfo->Name.c_str(); |
1657 |
|
rowSample[m_SamplesModel.m_col_sample] = sample; |
1658 |
|
rowSample[m_SamplesModel.m_col_group] = NULL; |
1659 |
|
} |
1660 |
|
} |
1661 |
|
} |
1662 |
} |
} |
1663 |
|
|
1664 |
void MainWindow::on_button_release(GdkEventButton* button) |
void MainWindow::on_button_release(GdkEventButton* button) |
1684 |
void MainWindow::on_instrument_selection_change(int index) { |
void MainWindow::on_instrument_selection_change(int index) { |
1685 |
m_RegionChooser.set_instrument(file->GetInstrument(index)); |
m_RegionChooser.set_instrument(file->GetInstrument(index)); |
1686 |
} |
} |
1687 |
|
|
1688 |
|
void MainWindow::on_sample_treeview_button_release(GdkEventButton* button) { |
1689 |
|
if (button->type == GDK_BUTTON_PRESS && button->button == 3) { |
1690 |
|
Gtk::Menu* sample_popup = |
1691 |
|
dynamic_cast<Gtk::Menu*>(uiManager->get_widget("/SamplePopupMenu")); |
1692 |
|
// update enabled/disabled state of sample popup items |
1693 |
|
Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection(); |
1694 |
|
Gtk::TreeModel::iterator it = sel->get_selected(); |
1695 |
|
bool group_selected = false; |
1696 |
|
bool sample_selected = false; |
1697 |
|
if (it) { |
1698 |
|
Gtk::TreeModel::Row row = *it; |
1699 |
|
group_selected = row[m_SamplesModel.m_col_group]; |
1700 |
|
sample_selected = row[m_SamplesModel.m_col_sample]; |
1701 |
|
} |
1702 |
|
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/SampleProperties"))->set_sensitive(group_selected || sample_selected); |
1703 |
|
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddSample"))->set_sensitive(group_selected || sample_selected); |
1704 |
|
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddGroup"))->set_sensitive(file); |
1705 |
|
dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/RemoveSample"))->set_sensitive(group_selected || sample_selected); |
1706 |
|
// show sample popup |
1707 |
|
sample_popup->popup(button->button, button->time); |
1708 |
|
} |
1709 |
|
} |
1710 |
|
|
1711 |
|
void MainWindow::on_action_sample_properties() { |
1712 |
|
//TODO: show a dialog where the selected sample's properties can be edited |
1713 |
|
} |
1714 |
|
|
1715 |
|
void MainWindow::on_action_add_group() { |
1716 |
|
static int __sample_indexer = 0; |
1717 |
|
if (!file) return; |
1718 |
|
gig::Group* group = file->AddGroup(); |
1719 |
|
group->Name = "Unnamed Group"; |
1720 |
|
if (__sample_indexer) group->Name += " " + ToString(__sample_indexer); |
1721 |
|
__sample_indexer++; |
1722 |
|
// update sample tree view |
1723 |
|
Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append(); |
1724 |
|
Gtk::TreeModel::Row rowGroup = *iterGroup; |
1725 |
|
rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str(); |
1726 |
|
rowGroup[m_SamplesModel.m_col_sample] = NULL; |
1727 |
|
rowGroup[m_SamplesModel.m_col_group] = group; |
1728 |
|
} |
1729 |
|
|
1730 |
|
void MainWindow::on_action_add_sample() { |
1731 |
|
if (!file) return; |
1732 |
|
// get selected group |
1733 |
|
Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection(); |
1734 |
|
Gtk::TreeModel::iterator it = sel->get_selected(); |
1735 |
|
if (!it) return; |
1736 |
|
Gtk::TreeModel::Row row = *it; |
1737 |
|
gig::Group* group = row[m_SamplesModel.m_col_group]; |
1738 |
|
if (!group) { // not a group, but a sample is selected (probably) |
1739 |
|
gig::Sample* sample = row[m_SamplesModel.m_col_sample]; |
1740 |
|
if (!sample) return; |
1741 |
|
it = row.parent(); // resolve parent (that is the sample's group) |
1742 |
|
if (!it) return; |
1743 |
|
row = *it; |
1744 |
|
group = row[m_SamplesModel.m_col_group]; |
1745 |
|
if (!group) return; |
1746 |
|
} |
1747 |
|
// show 'browse for file' dialog |
1748 |
|
Gtk::FileChooserDialog dialog(*this, _("Add Sample(s)")); |
1749 |
|
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
1750 |
|
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK); |
1751 |
|
dialog.set_select_multiple(true); |
1752 |
|
Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile (yet to do ;-) |
1753 |
|
soundfilter.add_pattern("*.wav"); |
1754 |
|
soundfilter.set_name("Sound Files"); |
1755 |
|
Gtk::FileFilter allpassfilter; // matches every file |
1756 |
|
allpassfilter.add_pattern("*.*"); |
1757 |
|
allpassfilter.set_name("All Files"); |
1758 |
|
dialog.add_filter(soundfilter); |
1759 |
|
dialog.add_filter(allpassfilter); |
1760 |
|
if (dialog.run() == Gtk::RESPONSE_OK) { |
1761 |
|
Glib::ustring error_files; |
1762 |
|
Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames(); |
1763 |
|
for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin(); iter != filenames.end(); ++iter) { |
1764 |
|
printf("Adding sample %s\n",(*iter).c_str()); |
1765 |
|
// use libsndfile to retrieve file informations |
1766 |
|
SF_INFO info; |
1767 |
|
info.format = 0; |
1768 |
|
SNDFILE* hFile = sf_open((*iter).c_str(), SFM_READ, &info); |
1769 |
|
try { |
1770 |
|
if (!hFile) throw std::string("could not open file"); |
1771 |
|
int bitdepth; |
1772 |
|
switch (info.format & 0xff) { |
1773 |
|
case SF_FORMAT_PCM_S8: |
1774 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1775 |
|
break; |
1776 |
|
case SF_FORMAT_PCM_16: |
1777 |
|
bitdepth = 16; |
1778 |
|
break; |
1779 |
|
case SF_FORMAT_PCM_24: |
1780 |
|
bitdepth = 32; // we simply convert to 32 bit for now |
1781 |
|
break; |
1782 |
|
case SF_FORMAT_PCM_32: |
1783 |
|
bitdepth = 32; |
1784 |
|
break; |
1785 |
|
case SF_FORMAT_PCM_U8: |
1786 |
|
bitdepth = 16; // we simply convert to 16 bit for now |
1787 |
|
break; |
1788 |
|
case SF_FORMAT_FLOAT: |
1789 |
|
bitdepth = 32; |
1790 |
|
break; |
1791 |
|
case SF_FORMAT_DOUBLE: |
1792 |
|
bitdepth = 32; // I guess we will always truncate this to 32 bit |
1793 |
|
break; |
1794 |
|
default: |
1795 |
|
sf_close(hFile); // close sound file |
1796 |
|
throw std::string("format not supported"); // unsupported subformat (yet?) |
1797 |
|
} |
1798 |
|
// add a new sample to the .gig file |
1799 |
|
gig::Sample* sample = file->AddSample(); |
1800 |
|
sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw(); // file name without path |
1801 |
|
sample->Channels = info.channels; |
1802 |
|
sample->BitDepth = bitdepth; |
1803 |
|
sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels; |
1804 |
|
sample->SamplesPerSecond = info.samplerate; |
1805 |
|
// schedule resizing the sample (which will be done physically when File::Save() is called) |
1806 |
|
sample->Resize(info.frames); |
1807 |
|
// schedule that physical resize and sample import (data copying), performed when "Save" is requested |
1808 |
|
SampleImportItem sched_item; |
1809 |
|
sched_item.gig_sample = sample; |
1810 |
|
sched_item.sample_path = *iter; |
1811 |
|
m_SampleImportQueue.push_back(sched_item); |
1812 |
|
// add sample to the tree view |
1813 |
|
Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(row.children()); |
1814 |
|
Gtk::TreeModel::Row rowSample = *iterSample; |
1815 |
|
rowSample[m_SamplesModel.m_col_name] = sample->pInfo->Name.c_str(); |
1816 |
|
rowSample[m_SamplesModel.m_col_sample] = sample; |
1817 |
|
rowSample[m_SamplesModel.m_col_group] = NULL; |
1818 |
|
// close sound file |
1819 |
|
sf_close(hFile); |
1820 |
|
} catch (std::string what) { // remember the files that made trouble (and their cause) |
1821 |
|
if (error_files.size()) error_files += "\n"; |
1822 |
|
error_files += *iter += " (" + what + ")"; |
1823 |
|
} |
1824 |
|
} |
1825 |
|
// show error message box when some file(s) could not be opened / added |
1826 |
|
if (error_files.size()) { |
1827 |
|
Glib::ustring txt = "Could not add the following sample(s):\n" + error_files; |
1828 |
|
Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); |
1829 |
|
msg.run(); |
1830 |
|
} |
1831 |
|
} |
1832 |
|
} |
1833 |
|
|
1834 |
|
void MainWindow::on_action_remove_sample() { |
1835 |
|
if (!file) return; |
1836 |
|
Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection(); |
1837 |
|
Gtk::TreeModel::iterator it = sel->get_selected(); |
1838 |
|
if (it) { |
1839 |
|
Gtk::TreeModel::Row row = *it; |
1840 |
|
gig::Group* group = row[m_SamplesModel.m_col_group]; |
1841 |
|
gig::Sample* sample = row[m_SamplesModel.m_col_sample]; |
1842 |
|
try { |
1843 |
|
// remove group or sample from the gig file |
1844 |
|
if (group) { |
1845 |
|
file->DeleteGroup(group); |
1846 |
|
} else if (sample) { |
1847 |
|
file->DeleteSample(sample); |
1848 |
|
} |
1849 |
|
// if sample was just previously added, remove it from the import queue |
1850 |
|
if (sample) { |
1851 |
|
for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) { |
1852 |
|
if ((*iter).gig_sample == sample) { |
1853 |
|
m_SampleImportQueue.erase(iter); |
1854 |
|
break; |
1855 |
|
} |
1856 |
|
} |
1857 |
|
} |
1858 |
|
// remove respective row(s) from samples tree view |
1859 |
|
m_refSamplesTreeModel->erase(it); |
1860 |
|
} catch (RIFF::Exception e) { |
1861 |
|
Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR); |
1862 |
|
msg.run(); |
1863 |
|
} |
1864 |
|
} |
1865 |
|
} |