/[svn]/gigedit/trunk/src/gigedit/mainwindow.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/mainwindow.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1265 by persson, Sun Jul 29 13:44:59 2007 UTC revision 1322 by schoenebeck, Tue Sep 4 11:04:56 2007 UTC
# Line 31  Line 31 
31  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
32  #endif  #endif
33    
34    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
35    namespace Glib {
36    Glib::ustring filename_display_basename(const std::string& filename)
37    {
38        gchar* gstr = g_path_get_basename(filename.c_str());
39        Glib::ustring str(gstr);
40        g_free(gstr);
41        return Glib::filename_to_utf8(str);
42    }
43    }
44    #endif
45    
46  #include <stdio.h>  #include <stdio.h>
47  #include <sndfile.h>  #include <sndfile.h>
48    
# Line 234  MainWindow::MainWindow() Line 246  MainWindow::MainWindow()
246      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
247      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
248      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
249        m_TreeViewSamples.signal_drag_begin().connect(
250            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
251        );
252      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
253          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
254      );      );
# Line 242  MainWindow::MainWindow() Line 257  MainWindow::MainWindow()
257          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
258      );      );
259      dimreg_edit.signal_dimreg_changed().connect(      dimreg_edit.signal_dimreg_changed().connect(
260          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
261      m_RegionChooser.signal_instrument_changed().connect(      m_RegionChooser.signal_instrument_changed().connect(
262          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
263      m_DimRegionChooser.signal_region_changed().connect(      m_DimRegionChooser.signal_region_changed().connect(
264          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
265      instrumentProps.signal_instrument_changed().connect(      instrumentProps.signal_instrument_changed().connect(
266          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
267    
268        dimreg_edit.signal_dimreg_to_be_changed().connect(
269            dimreg_to_be_changed_signal.make_slot());
270        dimreg_edit.signal_dimreg_changed().connect(
271            dimreg_changed_signal.make_slot());
272        dimreg_edit.signal_sample_ref_changed().connect(
273            sample_ref_changed_signal.make_slot());
274    
275        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
276            sigc::hide(
277                sigc::bind(
278                    file_structure_to_be_changed_signal.make_slot(),
279                    sigc::ref(this->file)
280                )
281            )
282        );
283        m_RegionChooser.signal_instrument_struct_changed().connect(
284            sigc::hide(
285                sigc::bind(
286                    file_structure_changed_signal.make_slot(),
287                    sigc::ref(this->file)
288                )
289            )
290        );
291        m_RegionChooser.signal_region_to_be_changed().connect(
292            region_to_be_changed_signal.make_slot());
293        m_RegionChooser.signal_region_changed_signal().connect(
294            region_changed_signal.make_slot());
295    
296      file = 0;      file = 0;
297      file_is_changed = false;      file_is_changed = false;
298    
299      show_all_children();      show_all_children();
300    
301        // start with a new gig file by default
302        on_action_file_new();
303  }  }
304    
305  MainWindow::~MainWindow()  MainWindow::~MainWindow()
# Line 407  bool MainWindow::close_confirmation_dial Line 454  bool MainWindow::close_confirmation_dial
454                                   Glib::filename_display_basename(filename).c_str());                                   Glib::filename_display_basename(filename).c_str());
455      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
456      g_free(msg);      g_free(msg);
457    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
458      dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));      dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
459    #endif
460      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
461      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
462      dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);      dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
463      dialog.set_default_response(Gtk::RESPONSE_YES);      dialog.set_default_response(Gtk::RESPONSE_YES);
464      int response = dialog.run();      int response = dialog.run();
465        dialog.hide();
466      if (response == Gtk::RESPONSE_YES) return file_save();      if (response == Gtk::RESPONSE_YES) return file_save();
467      return response != Gtk::RESPONSE_CANCEL;      return response != Gtk::RESPONSE_CANCEL;
468  }  }
# Line 434  void MainWindow::on_action_file_open() Line 484  void MainWindow::on_action_file_open()
484      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
485          std::string filename = dialog.get_filename();          std::string filename = dialog.get_filename();
486          printf("filename=%s\n", filename.c_str());          printf("filename=%s\n", filename.c_str());
         __clear();  
487          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
488          load_file(filename.c_str());          load_file(filename.c_str());
489          current_dir = Glib::path_get_dirname(filename);          current_dir = Glib::path_get_dirname(filename);
# Line 443  void MainWindow::on_action_file_open() Line 492  void MainWindow::on_action_file_open()
492    
493  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
494  {  {
495        __clear();
496      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
497      load_dialog->show_all();      load_dialog->show_all();
498      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 483  void MainWindow::on_action_file_save() Line 533  void MainWindow::on_action_file_save()
533      file_save();      file_save();
534  }  }
535    
536  bool MainWindow::file_save()  bool MainWindow::check_if_savable()
537  {  {
538      if (!file) return false;      if (!file) return false;
539    
540        if (!file->GetFirstSample()) {
541            Gtk::MessageDialog(*this, _("The file could not be saved "
542                                        "because it contains no samples"),
543                               false, Gtk::MESSAGE_ERROR).run();
544            return false;
545        }
546    
547        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
548             instrument = file->GetNextInstrument()) {
549            if (!instrument->GetFirstRegion()) {
550                Gtk::MessageDialog(*this, _("The file could not be saved "
551                                            "because there are instruments "
552                                            "that have no regions"),
553                                   false, Gtk::MESSAGE_ERROR).run();
554                return false;
555            }
556        }
557        return true;
558    }
559    
560    bool MainWindow::file_save()
561    {
562        if (!check_if_savable()) return false;
563      if (!file_has_name) return file_save_as();      if (!file_has_name) return file_save_as();
564    
565      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
566        file_structure_to_be_changed_signal.emit(this->file);
567      try {      try {
568          file->Save();          file->Save();
569          if (file_is_changed) {          if (file_is_changed) {
# Line 496  bool MainWindow::file_save() Line 571  bool MainWindow::file_save()
571              file_is_changed = false;              file_is_changed = false;
572          }          }
573      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
574            file_structure_changed_signal.emit(this->file);
575          Glib::ustring txt = "Could not save file: " + e.Message;          Glib::ustring txt = "Could not save file: " + e.Message;
576          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
577          msg.run();          msg.run();
# Line 503  bool MainWindow::file_save() Line 579  bool MainWindow::file_save()
579      }      }
580      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
581      __import_queued_samples();      __import_queued_samples();
582        file_structure_changed_signal.emit(this->file);
583      return true;      return true;
584  }  }
585    
586  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
587  {  {
588        if (!check_if_savable()) return;
589      file_save_as();      file_save_as();
590  }  }
591    
592  bool MainWindow::file_save_as()  bool MainWindow::file_save_as()
593  {  {
     if (!file) return false;  
594      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
595      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
596      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
# Line 535  bool MainWindow::file_save_as() Line 612  bool MainWindow::file_save_as()
612      dialog.set_current_name(Glib::filename_display_basename(filename));      dialog.set_current_name(Glib::filename_display_basename(filename));
613    
614      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
615            file_structure_to_be_changed_signal.emit(this->file);
616          try {          try {
617              std::string filename = dialog.get_filename();              std::string filename = dialog.get_filename();
618              if (!Glib::str_has_suffix(filename, ".gig")) {              if (!Glib::str_has_suffix(filename, ".gig")) {
# Line 548  bool MainWindow::file_save_as() Line 626  bool MainWindow::file_save_as()
626              file_has_name = true;              file_has_name = true;
627              file_is_changed = false;              file_is_changed = false;
628          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
629                file_structure_changed_signal.emit(this->file);
630              Glib::ustring txt = "Could not save file: " + e.Message;              Glib::ustring txt = "Could not save file: " + e.Message;
631              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
632              msg.run();              msg.run();
633              return false;              return false;
634          }          }
635          __import_queued_samples();          __import_queued_samples();
636            file_structure_changed_signal.emit(this->file);
637          return true;          return true;
638      }      }
639      return false;      return false;
# Line 1122  void MainWindow::on_action_add_sample() Line 1202  void MainWindow::on_action_add_sample()
1202                  {                  {
1203                      sample->MIDIUnityNote = instrument.basenote;                      sample->MIDIUnityNote = instrument.basenote;
1204    
1205    #if HAVE_SF_INSTRUMENT_LOOPS
1206                      if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {                      if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1207                          sample->Loops = 1;                          sample->Loops = 1;
1208    
# Line 1141  void MainWindow::on_action_add_sample() Line 1222  void MainWindow::on_action_add_sample()
1222                          sample->LoopPlayCount = instrument.loops[0].count;                          sample->LoopPlayCount = instrument.loops[0].count;
1223                          sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;                          sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1224                      }                      }
1225    #endif
1226                  }                  }
1227    
1228                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
# Line 1197  void MainWindow::on_action_remove_sample Line 1279  void MainWindow::on_action_remove_sample
1279                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1280                      members.push_back(pSample);                      members.push_back(pSample);
1281                  }                  }
1282                    // notify everybody that we're going to remove these samples
1283                    samples_to_be_removed_signal.emit(members);
1284                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1285                  // samples that belong to the group                  // samples that belong to the group
1286                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1287                    // notify that we're done with removal
1288                    samples_removed_signal.emit();
1289                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1290                  // them from the import queue                  // them from the import queue
1291                  for (std::list<gig::Sample*>::iterator member = members.begin();                  for (std::list<gig::Sample*>::iterator member = members.begin();
# Line 1216  void MainWindow::on_action_remove_sample Line 1302  void MainWindow::on_action_remove_sample
1302                  }                  }
1303                  file_changed();                  file_changed();
1304              } else if (sample) {              } else if (sample) {
1305                    // notify everybody that we're going to remove this sample
1306                    std::list<gig::Sample*> lsamples;
1307                    lsamples.push_back(sample);
1308                    samples_to_be_removed_signal.emit(lsamples);
1309                  // remove sample from the .gig file                  // remove sample from the .gig file
1310                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1311                    // notify that we're done with removal
1312                    samples_removed_signal.emit();
1313                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1314                  // the import queue                  // the import queue
1315                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
# Line 1229  void MainWindow::on_action_remove_sample Line 1321  void MainWindow::on_action_remove_sample
1321                          break;                          break;
1322                      }                      }
1323                  }                  }
1324                    dimreg_changed();
1325                  file_changed();                  file_changed();
1326              }              }
1327              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1328              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1329          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1330                // pretend we're done with removal (i.e. to avoid dead locks)
1331                samples_removed_signal.emit();
1332                // show error message
1333              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1334              msg.run();              msg.run();
1335          }          }
1336      }      }
1337  }  }
1338    
1339    // For some reason drag_data_get gets called two times for each
1340    // drag'n'drop (at least when target is an Entry). This work-around
1341    // makes sure the code in drag_data_get and drop_drag_data_received is
1342    // only executed once, as drag_begin only gets called once.
1343    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1344    {
1345        first_call_to_drag_data_get = true;
1346    }
1347    
1348  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,
1349                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1350  {  {
1351        if (!first_call_to_drag_data_get) return;
1352        first_call_to_drag_data_get = false;
1353    
1354      // get selected sample      // get selected sample
1355      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1356      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
# Line 1263  void MainWindow::on_sample_label_drop_dr Line 1371  void MainWindow::on_sample_label_drop_dr
1371      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1372    
1373      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1374          if (dimreg_edit.set_sample(sample)) {          std::cout << "Drop received sample \"" <<
1375              std::cout << "Drop received sample \"" <<              sample->pInfo->Name << "\"" << std::endl;
1376                  sample->pInfo->Name << "\"" << std::endl;          // drop success
1377              // drop success          context->drop_reply(true, time);
1378              context->drop_reply(true, time);  
1379              return;          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1380    
1381            // notify everybody that we're going to alter the region
1382            gig::Region* region = m_RegionChooser.get_region();
1383            region_to_be_changed_signal.emit(region);
1384    
1385            // find the samplechannel dimension
1386            gig::dimension_def_t* stereo_dimension = 0;
1387            for (int i = 0 ; i < region->Dimensions ; i++) {
1388                if (region->pDimensionDefinitions[i].dimension ==
1389                    gig::dimension_samplechannel) {
1390                    stereo_dimension = &region->pDimensionDefinitions[i];
1391                    break;
1392                }
1393            }
1394            bool channels_changed = false;
1395            if (sample->Channels == 1 && stereo_dimension) {
1396                // remove the samplechannel dimension
1397                region->DeleteDimension(stereo_dimension);
1398                channels_changed = true;
1399                region_changed();
1400            }
1401            dimreg_edit.set_sample(sample);
1402    
1403            if (sample->Channels == 2 && !stereo_dimension) {
1404                // add samplechannel dimension
1405                gig::dimension_def_t dim;
1406                dim.dimension = gig::dimension_samplechannel;
1407                dim.bits = 1;
1408                dim.zones = 2;
1409                region->AddDimension(&dim);
1410                channels_changed = true;
1411                region_changed();
1412            }
1413            if (channels_changed) {
1414                // unmap all samples with wrong number of channels
1415                // TODO: maybe there should be a warning dialog for this
1416                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1417                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1418                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1419                        gig::Sample* oldref = d->pSample;
1420                        d->pSample = NULL;
1421                        sample_ref_changed_signal.emit(oldref, NULL);
1422                    }
1423                }
1424          }          }
1425    
1426            // notify we're done with altering
1427            region_changed_signal.emit(region);
1428    
1429            return;
1430      }      }
1431      // drop failed      // drop failed
1432      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1308  void MainWindow::instrument_name_changed Line 1465  void MainWindow::instrument_name_changed
1465          file_changed();          file_changed();
1466      }      }
1467  }  }
1468    
1469    sigc::signal<void, gig::File*> MainWindow::signal_file_structure_to_be_changed() {
1470        return file_structure_to_be_changed_signal;
1471    }
1472    
1473    sigc::signal<void, gig::File*> MainWindow::signal_file_structure_changed() {
1474        return file_structure_changed_signal;
1475    }
1476    
1477    sigc::signal<void, std::list<gig::Sample*> > MainWindow::signal_samples_to_be_removed() {
1478        return samples_to_be_removed_signal;
1479    }
1480    
1481    sigc::signal<void> MainWindow::signal_samples_removed() {
1482        return samples_removed_signal;
1483    }
1484    
1485    sigc::signal<void, gig::Region*> MainWindow::signal_region_to_be_changed() {
1486        return region_to_be_changed_signal;
1487    }
1488    
1489    sigc::signal<void, gig::Region*> MainWindow::signal_region_changed() {
1490        return region_changed_signal;
1491    }
1492    
1493    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/> MainWindow::signal_sample_ref_changed() {
1494        return sample_ref_changed_signal;
1495    }
1496    
1497    sigc::signal<void, gig::DimensionRegion*> MainWindow::signal_dimreg_to_be_changed() {
1498        return dimreg_to_be_changed_signal;
1499    }
1500    
1501    sigc::signal<void, gig::DimensionRegion*> MainWindow::signal_dimreg_changed() {
1502        return dimreg_changed_signal;
1503    }

Legend:
Removed from v.1265  
changed lines
  Added in v.1322

  ViewVC Help
Powered by ViewVC