master merge; new files not added after initial cairocanvas patch application
This commit is contained in:
@@ -24,9 +24,8 @@ If the edit point is `mouse':
|
||||
if the mouse is over a selected region, or no region, this method returns all selected regions.
|
||||
if the mouse is over an unselected region, just that region is returned.
|
||||
|
||||
For other edit points the method returns the selected regions AND those that are both under the edit position
|
||||
AND on a selected track, or on a track which is in the same active edit-enabled route group as a selected
|
||||
region.
|
||||
For other edit points the method returns the selected regions. If no regions are selected, it returns
|
||||
the regions under the edit position on the selected tracks.
|
||||
|
||||
The action handlers call the appropriate method to decide which regions to operate on.
|
||||
|
||||
|
||||
@@ -440,6 +440,17 @@
|
||||
#ifdef WITH_VIDEOTIMELINE
|
||||
<separator/>
|
||||
<menuitem action="toggle-video-ruler"/>
|
||||
</menu>
|
||||
<menu action="VideoMonitorMenu">
|
||||
<menuitem action="zoom-vmon-100"/>
|
||||
<menuitem action="toggle-vmon-letterbox"/>
|
||||
<separator/>
|
||||
<menuitem action="toggle-vmon-ontop"/>
|
||||
<menuitem action="toggle-vmon-fullscreen"/>
|
||||
<separator/>
|
||||
<menuitem action="toggle-vmon-timecode"/>
|
||||
<menuitem action="toggle-vmon-frame"/>
|
||||
<menuitem action="toggle-vmon-osdbg"/>
|
||||
#endif
|
||||
</menu>
|
||||
<menu action="ScrollMenu">
|
||||
|
||||
@@ -660,22 +660,28 @@ ARDOUR_UI::startup ()
|
||||
app->ready ();
|
||||
|
||||
nsm_url = getenv ("NSM_URL");
|
||||
nsm = 0;
|
||||
|
||||
if (nsm_url) {
|
||||
nsm = new NSM_Client;
|
||||
if (!nsm->init (nsm_url)) {
|
||||
nsm->announce (PROGRAM_NAME, ":dirty:", "ardour3");
|
||||
|
||||
unsigned int i = 0;
|
||||
// wait for announce reply from nsm server
|
||||
do {
|
||||
for ( i = 0; i < 5000; ++i) {
|
||||
nsm->check ();
|
||||
usleep (10);
|
||||
} while (!nsm->is_active ());
|
||||
usleep (i);
|
||||
if (nsm->is_active())
|
||||
break;
|
||||
}
|
||||
// wait for open command from nsm server
|
||||
do {
|
||||
for ( i = 0; i < 5000; ++i) {
|
||||
nsm->check ();
|
||||
usleep (10);
|
||||
} while (!nsm->client_id ());
|
||||
usleep (1000);
|
||||
if (nsm->client_id ())
|
||||
break;
|
||||
}
|
||||
|
||||
if (_session && nsm) {
|
||||
_session->set_nsm_state( nsm->is_active() );
|
||||
@@ -698,12 +704,6 @@ ARDOUR_UI::startup ()
|
||||
}
|
||||
}
|
||||
|
||||
// wait for session is loaded reply from nsm server
|
||||
do {
|
||||
nsm->check ();
|
||||
usleep (10);
|
||||
} while (!nsm->session_loaded ());
|
||||
|
||||
}
|
||||
else {
|
||||
delete nsm;
|
||||
@@ -981,7 +981,7 @@ ARDOUR_UI::every_second ()
|
||||
update_disk_space ();
|
||||
update_timecode_format ();
|
||||
|
||||
if (nsm && nsm->is_active () && nsm->session_loaded ()) {
|
||||
if (nsm && nsm->is_active ()) {
|
||||
nsm->check ();
|
||||
|
||||
if (!_was_dirty && _session->dirty ()) {
|
||||
|
||||
@@ -4040,7 +4040,7 @@ Editor::restore_editing_space ()
|
||||
|
||||
/**
|
||||
* Make new playlists for a given track and also any others that belong
|
||||
* to the same active route group with the `edit' property.
|
||||
* to the same active route group with the `select' property.
|
||||
* @param v Track.
|
||||
*/
|
||||
|
||||
@@ -4056,7 +4056,7 @@ Editor::new_playlists (TimeAxisView* v)
|
||||
|
||||
/**
|
||||
* Use a copy of the current playlist for a given track and also any others that belong
|
||||
* to the same active route group with the `edit' property.
|
||||
* to the same active route group with the `select' property.
|
||||
* @param v Track.
|
||||
*/
|
||||
|
||||
@@ -4071,7 +4071,7 @@ Editor::copy_playlists (TimeAxisView* v)
|
||||
}
|
||||
|
||||
/** Clear the current playlist for a given track and also any others that belong
|
||||
* to the same active route group with the `edit' property.
|
||||
* to the same active route group with the `select' property.
|
||||
* @param v Track.
|
||||
*/
|
||||
|
||||
@@ -4592,32 +4592,16 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie
|
||||
}
|
||||
}
|
||||
|
||||
/** Start with regions that are selected. Then add equivalent regions
|
||||
* on tracks in the same active edit-enabled route group as any of
|
||||
* the regions that we started with.
|
||||
*/
|
||||
|
||||
RegionSelection
|
||||
Editor::get_regions_from_selection ()
|
||||
{
|
||||
return get_equivalent_regions (selection->regions, ARDOUR::Properties::select.property_id);
|
||||
}
|
||||
|
||||
/** Get regions using the following method:
|
||||
*
|
||||
* Make an initial region list using the selected regions, unless
|
||||
* Make a region list using the selected regions, unless
|
||||
* the edit point is `mouse' and the mouse is over an unselected
|
||||
* region. In this case, start with just that region.
|
||||
* region. In this case, use just that region.
|
||||
*
|
||||
* Then, add equivalent regions in active edit groups to the region list.
|
||||
*
|
||||
* Then, search the list of selected tracks to find any selected tracks which
|
||||
* do not contain regions already in the region list. If there are no selected
|
||||
* tracks and 'No Selection = All Tracks' is active, search all tracks rather
|
||||
* than just the selected.
|
||||
*
|
||||
* Add any regions that are under the edit point on these tracks to get the
|
||||
* returned region list.
|
||||
* If the edit point is not 'mouse', and there are no regions selected,
|
||||
* search the list of selected tracks and return regions that are under
|
||||
* the edit point on these tracks. If there are no selected tracks and
|
||||
* 'No Selection = All Tracks' is active, search all tracks,
|
||||
*
|
||||
* The rationale here is that the mouse edit point is special in that
|
||||
* its position describes both a time and a track; the other edit
|
||||
@@ -4639,48 +4623,25 @@ Editor::get_regions_from_selection_and_edit_point ()
|
||||
regions = selection->regions;
|
||||
}
|
||||
|
||||
TrackViewList tracks;
|
||||
|
||||
if (_edit_point != EditAtMouse) {
|
||||
tracks = selection->tracks;
|
||||
}
|
||||
if (regions.empty() && _edit_point != EditAtMouse) {
|
||||
TrackViewList tracks = selection->tracks;
|
||||
|
||||
/* Add any other regions that are in the same
|
||||
edit-activated route group as one of our regions.
|
||||
*/
|
||||
regions = get_equivalent_regions (regions, ARDOUR::Properties::select.property_id);
|
||||
framepos_t const where = get_preferred_edit_position ();
|
||||
|
||||
if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
|
||||
/* tracks is empty (no track selected), and 'No Selection = All Tracks'
|
||||
* is enabled, so consider all tracks
|
||||
*/
|
||||
tracks = track_views;
|
||||
}
|
||||
|
||||
if (!tracks.empty()) {
|
||||
/* now search the selected tracks for tracks which don't
|
||||
already contain regions to be acted upon, and get regions at
|
||||
the edit point on those tracks too.
|
||||
*/
|
||||
TrackViewList tracks_without_relevant_regions;
|
||||
|
||||
for (TrackViewList::iterator t = tracks.begin (); t != tracks.end (); ++t) {
|
||||
if (!regions.involves (**t)) {
|
||||
/* there are no equivalent regions on this track */
|
||||
tracks_without_relevant_regions.push_back (*t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tracks_without_relevant_regions.empty()) {
|
||||
/* there are some selected tracks with neither selected
|
||||
* regions or their equivalents: act upon all regions in
|
||||
* those tracks
|
||||
if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
|
||||
/* tracks is empty (no track selected), and 'No Selection = All Tracks'
|
||||
* is enabled, so consider all tracks
|
||||
*/
|
||||
get_regions_at (regions, where, tracks_without_relevant_regions);
|
||||
tracks = track_views;
|
||||
}
|
||||
|
||||
if (!tracks.empty()) {
|
||||
/* no region selected or entered, but some selected tracks:
|
||||
* act on all regions on the selected tracks at the edit point
|
||||
*/
|
||||
framepos_t const where = get_preferred_edit_position ();
|
||||
get_regions_at(regions, where, tracks);
|
||||
}
|
||||
}
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
@@ -4698,7 +4659,7 @@ Editor::get_regions_from_selection_and_entered ()
|
||||
regions.add (entered_regionview);
|
||||
}
|
||||
|
||||
return get_equivalent_regions (regions, ARDOUR::Properties::select.property_id);
|
||||
return regions;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -929,9 +929,18 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
ArdourCanvas::Group* videotl_group;
|
||||
Glib::RefPtr<Gtk::ToggleAction> ruler_video_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_proc_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_ontop_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_timecode_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_frame_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_osdbg_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_fullscreen_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> xjadeo_letterbox_action;
|
||||
Glib::RefPtr<Gtk::Action> xjadeo_zoom_100;
|
||||
void set_xjadeo_proc ();
|
||||
void toggle_xjadeo_proc (int state=-1);
|
||||
void set_xjadeo_sensitive (bool onoff);
|
||||
void set_xjadeo_viewoption (int);
|
||||
void toggle_xjadeo_viewoption (int what, int state=-1);
|
||||
void toggle_ruler_video (bool onoff) {ruler_video_action->set_active(onoff);}
|
||||
int videotl_bar_height; /* in units of timebar_height; default: 4 */
|
||||
int get_videotl_bar_height () const { return videotl_bar_height; }
|
||||
@@ -2040,7 +2049,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||
void get_regions_at (RegionSelection&, framepos_t where, const TrackViewList& ts) const;
|
||||
void get_regions_after (RegionSelection&, framepos_t where, const TrackViewList& ts) const;
|
||||
|
||||
RegionSelection get_regions_from_selection ();
|
||||
RegionSelection get_regions_from_selection_and_edit_point ();
|
||||
RegionSelection get_regions_from_selection_and_entered ();
|
||||
|
||||
|
||||
@@ -547,8 +547,19 @@ Editor::register_actions ()
|
||||
ruler_timecode_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-timecode-ruler"), _("Timecode"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_metric_timecode)));
|
||||
ruler_minsec_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-minsec-ruler"), _("Min:Sec"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_metric_minsec)));
|
||||
#ifdef WITH_VIDEOTIMELINE
|
||||
|
||||
ActionManager::register_action (editor_menu_actions, X_("VideoMonitorMenu"), _("Video Monitor"));
|
||||
|
||||
ruler_video_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-video-ruler"), _("Video"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_video_timeline)));
|
||||
xjadeo_proc_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("ToggleJadeo"), _("Show Video Monitor"), sigc::mem_fun (*this, &Editor::set_xjadeo_proc)));
|
||||
xjadeo_proc_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("ToggleJadeo"), _("Video Monitor"), sigc::mem_fun (*this, &Editor::set_xjadeo_proc)));
|
||||
|
||||
xjadeo_ontop_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-ontop"), _("Always on Top"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 1)));
|
||||
xjadeo_timecode_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 2)));
|
||||
xjadeo_frame_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-frame"), _("Framenumber"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 3)));
|
||||
xjadeo_osdbg_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-osdbg"), _("Timecode Background"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 4)));
|
||||
xjadeo_fullscreen_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-fullscreen"), _("Fullscreen"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 5)));
|
||||
xjadeo_letterbox_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-letterbox"), _("Letterbox"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 6)));
|
||||
xjadeo_zoom_100 = reg_sens (editor_actions, "zoom-vmon-100", _("Original Size"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 7));
|
||||
|
||||
#endif
|
||||
|
||||
@@ -565,6 +576,19 @@ Editor::register_actions ()
|
||||
ruler_video_action->set_active (false);
|
||||
xjadeo_proc_action->set_active (false);
|
||||
xjadeo_proc_action->set_sensitive (false);
|
||||
xjadeo_ontop_action->set_active (false);
|
||||
xjadeo_ontop_action->set_sensitive (false);
|
||||
xjadeo_timecode_action->set_active (false);
|
||||
xjadeo_timecode_action->set_sensitive (false);
|
||||
xjadeo_frame_action->set_active (false);
|
||||
xjadeo_frame_action->set_sensitive (false);
|
||||
xjadeo_osdbg_action->set_active (false);
|
||||
xjadeo_osdbg_action->set_sensitive (false);
|
||||
xjadeo_fullscreen_action->set_active (false);
|
||||
xjadeo_fullscreen_action->set_sensitive (false);
|
||||
xjadeo_letterbox_action->set_active (false);
|
||||
xjadeo_letterbox_action->set_sensitive (false);
|
||||
xjadeo_zoom_100->set_sensitive (false);
|
||||
#endif
|
||||
if (Profile->get_sae()) {
|
||||
ruler_bbt_action->set_active (true);
|
||||
@@ -763,6 +787,7 @@ Editor::set_xjadeo_sensitive (bool onoff)
|
||||
{
|
||||
xjadeo_proc_action->set_sensitive(onoff);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::toggle_xjadeo_proc (int state)
|
||||
{
|
||||
@@ -777,6 +802,14 @@ Editor::toggle_xjadeo_proc (int state)
|
||||
xjadeo_proc_action->set_active(!xjadeo_proc_action->get_active());
|
||||
break;
|
||||
}
|
||||
bool onoff = xjadeo_proc_action->get_active();
|
||||
xjadeo_ontop_action->set_sensitive(onoff);
|
||||
xjadeo_timecode_action->set_sensitive(onoff);
|
||||
xjadeo_frame_action->set_sensitive(onoff);
|
||||
xjadeo_osdbg_action->set_sensitive(onoff);
|
||||
xjadeo_fullscreen_action->set_sensitive(onoff);
|
||||
xjadeo_letterbox_action->set_sensitive(onoff);
|
||||
xjadeo_zoom_100->set_sensitive(onoff);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -788,6 +821,84 @@ Editor::set_xjadeo_proc ()
|
||||
ARDOUR_UI::instance()->video_timeline->close_video_monitor();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::toggle_xjadeo_viewoption (int what, int state)
|
||||
{
|
||||
Glib::RefPtr<Gtk::ToggleAction> action;
|
||||
switch (what) {
|
||||
case 1:
|
||||
action = xjadeo_ontop_action;
|
||||
break;
|
||||
case 2:
|
||||
action = xjadeo_timecode_action;
|
||||
break;
|
||||
case 3:
|
||||
action = xjadeo_frame_action;
|
||||
break;
|
||||
case 4:
|
||||
action = xjadeo_osdbg_action;
|
||||
break;
|
||||
case 5:
|
||||
action = xjadeo_fullscreen_action;
|
||||
break;
|
||||
case 6:
|
||||
action = xjadeo_letterbox_action;
|
||||
break;
|
||||
case 7:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
switch(state) {
|
||||
case 1:
|
||||
action->set_active(true);
|
||||
break;
|
||||
case 0:
|
||||
action->set_active(false);
|
||||
break;
|
||||
default:
|
||||
action->set_active(!action->get_active());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_xjadeo_viewoption (int what)
|
||||
{
|
||||
Glib::RefPtr<Gtk::ToggleAction> action;
|
||||
switch (what) {
|
||||
case 1:
|
||||
action = xjadeo_ontop_action;
|
||||
break;
|
||||
case 2:
|
||||
action = xjadeo_timecode_action;
|
||||
break;
|
||||
case 3:
|
||||
action = xjadeo_frame_action;
|
||||
break;
|
||||
case 4:
|
||||
action = xjadeo_osdbg_action;
|
||||
break;
|
||||
case 5:
|
||||
action = xjadeo_fullscreen_action;
|
||||
break;
|
||||
case 6:
|
||||
action = xjadeo_letterbox_action;
|
||||
break;
|
||||
case 7:
|
||||
ARDOUR_UI::instance()->video_timeline->control_video_monitor(what, 0);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (action->get_active()) {
|
||||
ARDOUR_UI::instance()->video_timeline->control_video_monitor(what, 1);
|
||||
} else {
|
||||
ARDOUR_UI::instance()->video_timeline->control_video_monitor(what, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
|
||||
@@ -3737,7 +3737,7 @@ Editor::cut_copy (CutCopyOp op)
|
||||
/* we only want to cut regions if some are selected */
|
||||
|
||||
if (!selection->regions.empty()) {
|
||||
rs = get_regions_from_selection ();
|
||||
rs = selection->regions;
|
||||
}
|
||||
|
||||
switch (effective_mouse_mode()) {
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/rc_configuration.h"
|
||||
#include "ardour/audio_track.h"
|
||||
#include "ardour/audioregion.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "editor.h"
|
||||
@@ -33,6 +35,7 @@
|
||||
#include "video_image_frame.h"
|
||||
#include "export_video_dialog.h"
|
||||
#include "export_video_infobox.h"
|
||||
#include "interthread_progress_window.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
@@ -95,11 +98,27 @@ Editor::embed_audio_from_video (std::string path, framepos_t n)
|
||||
vector<std::string> paths;
|
||||
paths.push_back(path);
|
||||
#if 0
|
||||
do_embed (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, n);
|
||||
#else
|
||||
do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, ARDOUR::SrcBest, n);
|
||||
unlink(path.c_str());
|
||||
#else
|
||||
current_interthread_info = &import_status;
|
||||
import_status.current = 1;
|
||||
import_status.total = paths.size ();
|
||||
import_status.all_done = false;
|
||||
|
||||
ImportProgressWindow ipw (&import_status, _("Import"), _("Cancel Import"));
|
||||
ipw.show ();
|
||||
|
||||
boost::shared_ptr<ARDOUR::Track> track;
|
||||
bool ok = (import_sndfiles (paths, Editing::ImportAsTrack, ARDOUR::SrcBest, n, 1, 1, track, false) == 0);
|
||||
if (ok && track) {
|
||||
boost::shared_ptr<ARDOUR::Playlist> pl = track->playlist();
|
||||
pl->find_next_region(n, ARDOUR::End, 0)->set_video_locked(true);
|
||||
_session->save_state ("");
|
||||
}
|
||||
|
||||
import_status.all_done = true;
|
||||
#endif
|
||||
unlink(path.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -66,21 +66,21 @@ using namespace ARDOUR;
|
||||
ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
|
||||
: ArdourDialog (_("Export Video File "))
|
||||
, editor (ed)
|
||||
, outfn_path_label (_("Output File:"), Gtk::ALIGN_LEFT)
|
||||
, outfn_path_label (_("File:"), Gtk::ALIGN_LEFT)
|
||||
, outfn_browse_button (_("Browse"))
|
||||
, invid_path_label (_("Input Video File:"), Gtk::ALIGN_LEFT)
|
||||
, invid_path_label (_("Video:"), Gtk::ALIGN_LEFT)
|
||||
, invid_browse_button (_("Browse"))
|
||||
, transcode_button (_("Export"))
|
||||
, abort_button (_("Abort"))
|
||||
, scale_checkbox (_("Scale Video (W x H):"))
|
||||
, width_adjustment (128, 768, 1920, 1, 16, 0)
|
||||
, width_adjustment (768, 128, 1920, 1, 16, 0)
|
||||
, width_spinner (width_adjustment)
|
||||
, height_adjustment (128, 576, 1920, 1, 16, 0)
|
||||
, height_adjustment (576, 128, 1920, 1, 16, 0)
|
||||
, height_spinner (height_adjustment)
|
||||
, aspect_checkbox (_("Set Aspect Ratio:"))
|
||||
, normalize_checkbox (_("Normalize Audio"))
|
||||
, twopass_checkbox (_("2 Pass Encoding"))
|
||||
, optimizations_checkbox (_("Optimizations:"))
|
||||
, optimizations_checkbox (_("Codec Optimizations:"))
|
||||
, optimizations_label ("-")
|
||||
, deinterlace_checkbox (_("Deinterlace"))
|
||||
, bframes_checkbox (_("Use [2] B-frames (MPEG 2 or 4 only)"))
|
||||
@@ -92,7 +92,6 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
|
||||
{
|
||||
set_session (s);
|
||||
|
||||
|
||||
set_name ("ExportVideoDialog");
|
||||
set_position (Gtk::WIN_POS_MOUSE);
|
||||
set_modal (true);
|
||||
@@ -117,29 +116,32 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
|
||||
}
|
||||
delete transcoder; transcoder = 0;
|
||||
|
||||
l = manage (new Label (_("<b>Files:</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
l = manage (new Label (_("<b>Output:</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
l->set_use_markup ();
|
||||
vbox->pack_start (*l, false, false);
|
||||
vbox->pack_start (*l, false, false, 4);
|
||||
|
||||
path_hbox = manage (new HBox);
|
||||
path_hbox->pack_start (outfn_path_label, false, false, 3);
|
||||
path_hbox->pack_start (outfn_path_entry, true, true, 3);
|
||||
path_hbox->pack_start (outfn_browse_button, false, false, 3);
|
||||
outfn_browse_button.set_name ("PaddedButton");
|
||||
vbox->pack_start (*path_hbox, false, false);
|
||||
vbox->pack_start (*path_hbox, false, false, 2);
|
||||
|
||||
l = manage (new Label (_("<b>Input:</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
l->set_use_markup ();
|
||||
vbox->pack_start (*l, false, false, 4);
|
||||
|
||||
path_hbox = manage (new HBox);
|
||||
path_hbox->pack_start (invid_path_label, false, false, 3);
|
||||
path_hbox->pack_start (invid_path_entry, true, true, 3);
|
||||
path_hbox->pack_start (invid_browse_button, false, false, 3);
|
||||
invid_browse_button.set_name ("PaddedButton");
|
||||
vbox->pack_start (*path_hbox, false, false);
|
||||
vbox->pack_start (*path_hbox, false, false, 2);
|
||||
|
||||
path_hbox = manage (new HBox);
|
||||
l = manage (new Label (_("Input Audio (Ardour Session):"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
path_hbox->pack_start (*l, true, true, 3);
|
||||
path_hbox->pack_start (insnd_combo, true, true, 3);
|
||||
vbox->pack_start (*path_hbox, false, false);
|
||||
l = manage (new Label (_("Audio:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
path_hbox->pack_start (*l, false, false, 3);
|
||||
l = manage (new Label (_("Master Bus"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
path_hbox->pack_start (*l, false, false, 2);
|
||||
vbox->pack_start (*path_hbox, false, false, 2);
|
||||
|
||||
insnd_combo.set_name ("PaddedButton");
|
||||
insnd_combo.append_text("from ardour session-start to session-end");
|
||||
@@ -168,43 +170,47 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
|
||||
l->set_use_markup ();
|
||||
options_box->pack_start (*l, false, true, 4);
|
||||
|
||||
Table* t = manage (new Table (4, 11));
|
||||
Table* t = manage (new Table (4, 12));
|
||||
t->set_spacings (4);
|
||||
int ty = 0;
|
||||
options_box->pack_start (*t, true, true, 4);
|
||||
l = manage (new Label (_("Range:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 0, 1, ty, ty+1);
|
||||
t->attach (insnd_combo, 1, 4, ty, ty+1); ty++;
|
||||
l = manage (new Label (_("Preset:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 0, 1, 0, 1);
|
||||
t->attach (preset_combo, 1, 4, 0, 1);
|
||||
t->attach (*l, 0, 1, ty, ty+1);
|
||||
t->attach (preset_combo, 1, 4, ty, ty+1); ty++;
|
||||
l = manage (new Label (_("Video Codec:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 0, 1, 1, 2);
|
||||
t->attach (video_codec_combo, 1, 2, 1, 2);
|
||||
t->attach (*l, 0, 1, ty, ty+1);
|
||||
t->attach (video_codec_combo, 1, 2, ty, ty+1);
|
||||
l = manage (new Label (_("Video KBit/s:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 2, 3, 1, 2);
|
||||
t->attach (video_bitrate_combo, 3, 4, 1, 2);
|
||||
t->attach (*l, 2, 3, ty, ty+1);
|
||||
t->attach (video_bitrate_combo, 3, 4, ty, ty+1); ty++;
|
||||
l = manage (new Label (_("Audio Codec:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 0, 1, 2, 3);
|
||||
t->attach (audio_codec_combo, 1, 2, 2, 3);
|
||||
t->attach (*l, 0, 1, ty, ty+1);
|
||||
t->attach (audio_codec_combo, 1, 2, ty, ty+1);
|
||||
l = manage (new Label (_("Audio KBit/s:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 2, 3, 2, 3);
|
||||
t->attach (audio_bitrate_combo, 3, 4, 2, 3);
|
||||
t->attach (*l, 2, 3, ty, ty+1);
|
||||
t->attach (audio_bitrate_combo, 3, 4, ty, ty+1); ty++;
|
||||
l = manage (new Label (_("Audio Samplerate:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
|
||||
t->attach (*l, 0, 1, 3, 4);
|
||||
t->attach (audio_samplerate_combo, 1, 2, 3, 4);
|
||||
t->attach (normalize_checkbox, 2, 4, 3, 4);
|
||||
t->attach (scale_checkbox, 0, 2, 4, 5);
|
||||
t->attach (width_spinner, 2, 3, 4, 5);
|
||||
t->attach (height_spinner, 3, 4, 4, 5);
|
||||
t->attach (fps_checkbox, 0, 3, 5, 6);
|
||||
t->attach (fps_combo, 3, 4, 5, 6);
|
||||
t->attach (aspect_checkbox, 2, 3, 6, 7);
|
||||
t->attach (aspect_combo, 3, 4, 6, 7);
|
||||
t->attach (twopass_checkbox, 0, 2, 6, 7);
|
||||
t->attach (bframes_checkbox, 0, 2, 7, 8);
|
||||
t->attach (deinterlace_checkbox, 2, 4, 7, 8);
|
||||
t->attach (meta_checkbox, 2, 4, 8, 9);
|
||||
t->attach (optimizations_checkbox, 0, 1, 9, 10);
|
||||
t->attach (optimizations_label, 1, 4, 9, 10);
|
||||
t->attach (*l, 0, 1, ty, ty+1);
|
||||
t->attach (audio_samplerate_combo, 1, 2, ty, ty+1);
|
||||
t->attach (normalize_checkbox, 2, 4, ty, ty+1); ty++;
|
||||
t->attach (scale_checkbox, 0, 2, ty, ty+1);
|
||||
t->attach (width_spinner, 2, 3, ty, ty+1);
|
||||
t->attach (height_spinner, 3, 4, ty, ty+1); ty++;
|
||||
t->attach (fps_checkbox, 0, 3, ty, ty+1);
|
||||
t->attach (fps_combo, 3, 4, ty, ty+1); ty++;
|
||||
t->attach (twopass_checkbox, 0, 2, ty, ty+1);
|
||||
t->attach (aspect_checkbox, 2, 3, ty, ty+1);
|
||||
t->attach (aspect_combo, 3, 4, ty, ty+1); ty++;
|
||||
t->attach (bframes_checkbox, 0, 2, ty, ty+1);
|
||||
t->attach (deinterlace_checkbox, 2, 4, ty, ty+1); ty++;
|
||||
t->attach (meta_checkbox, 2, 4, ty, ty+1); ty++;
|
||||
t->attach (optimizations_checkbox, 0, 1, ty, ty+1);
|
||||
t->attach (optimizations_label, 1, 4, ty, ty+1); ty++;
|
||||
#if 1 /* tentative debug mode */
|
||||
t->attach (debug_checkbox, 0, 4, 10, 11);
|
||||
t->attach (debug_checkbox, 0, 4, ty, ty+1); ty++;
|
||||
#endif
|
||||
|
||||
preset_combo.set_name ("PaddedButton");
|
||||
@@ -293,7 +299,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
|
||||
fps_checkbox_toggled();
|
||||
video_codec_combo_changed();
|
||||
|
||||
vbox->pack_start (*options_box, false, true);
|
||||
vbox->pack_start (*options_box, false, true, 4);
|
||||
get_vbox()->set_spacing (4);
|
||||
get_vbox()->pack_start (*vbox, false, false);
|
||||
|
||||
@@ -344,9 +350,41 @@ ExportVideoDialog::update_progress (framecnt_t c, framecnt_t a)
|
||||
if (a == 0 || c > a) {
|
||||
pbar.set_pulse_step(.1);
|
||||
pbar.pulse();
|
||||
return;
|
||||
} else {
|
||||
double progress = (double)c / (double) a;
|
||||
progress = progress / ((twopass ? 2.0 : 1.0) + (normalize ? 2.0 : 1.0));
|
||||
if (normalize && twopass) progress += (firstpass ? .5 : .75);
|
||||
else if (normalize) progress += 2.0/3.0;
|
||||
else if (twopass) progress += (firstpass ? 1.0/3.0 : 2.0/3.0);
|
||||
else progress += .5;
|
||||
|
||||
pbar.set_fraction (progress);
|
||||
}
|
||||
pbar.set_fraction ((double)c / (double) a);
|
||||
}
|
||||
|
||||
|
||||
gint
|
||||
ExportVideoDialog::audio_progress_display ()
|
||||
{
|
||||
std::string status_text;
|
||||
double progress = 0.0;
|
||||
if (status->normalizing) {
|
||||
pbar.set_text (_("Normalizing audio"));
|
||||
progress = ((float) status->current_normalize_cycle) / status->total_normalize_cycles;
|
||||
progress = progress / (twopass ? 4.0 : 3.0) + (twopass ? .25 : 1.0/3.0);
|
||||
} else {
|
||||
pbar.set_text (_("Exporting audio"));
|
||||
progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan;
|
||||
progress = progress / ((twopass ? 2.0 : 1.0) + (normalize ? 2.0 : 1.0));
|
||||
}
|
||||
if (progress < previous_progress) {
|
||||
// Work around gtk bug
|
||||
pbar.hide();
|
||||
pbar.show();
|
||||
}
|
||||
previous_progress = progress;
|
||||
pbar.set_fraction (progress);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -355,10 +393,9 @@ ExportVideoDialog::finished ()
|
||||
if (aborted) {
|
||||
unlink(outfn_path_entry.get_text().c_str());
|
||||
unlink (insnd.c_str());
|
||||
warning << _("Video Export Failed or Was Aborted") << endmsg;
|
||||
Gtk::Dialog::response(RESPONSE_CANCEL);
|
||||
} else if (twopass) {
|
||||
twopass = false;
|
||||
} else if (twopass && firstpass) {
|
||||
firstpass = false;
|
||||
if (transcoder) { delete transcoder; transcoder = 0;}
|
||||
encode_pass(2);
|
||||
} else {
|
||||
@@ -386,6 +423,8 @@ ExportVideoDialog::launch_export ()
|
||||
progress_box->show();
|
||||
aborted = false;
|
||||
twopass = twopass_checkbox.get_active();
|
||||
firstpass = true;
|
||||
normalize = normalize_checkbox.get_active();
|
||||
|
||||
/* export audio track */
|
||||
ExportTimespanPtr tsp = _session->get_export_handler()->add_timespan();
|
||||
@@ -394,7 +433,7 @@ ExportVideoDialog::launch_export ()
|
||||
boost::shared_ptr<AudioGrapher::BroadcastInfo> b;
|
||||
XMLTree tree;
|
||||
std::string vtl_samplerate = audio_samplerate_combo.get_active_text();
|
||||
std::string vtl_normalize = normalize_checkbox.get_active()?"true":"false";
|
||||
std::string vtl_normalize = normalize ? "true" : "false";
|
||||
tree.read_buffer(std::string(
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<ExportFormatSpecification name=\"VTL-WAV-16\" id=\"3094591e-ccb9-4385-a93f-c9955ffeb1f0\">"
|
||||
@@ -486,34 +525,19 @@ ExportVideoDialog::launch_export ()
|
||||
/* do sound export */
|
||||
_session->get_export_handler()->add_export_config (tsp, ccp, fmp, fnp, b);
|
||||
_session->get_export_handler()->do_export();
|
||||
boost::shared_ptr<ARDOUR::ExportStatus> status = _session->get_export_status ();
|
||||
//status->running = true;
|
||||
status = _session->get_export_status ();
|
||||
|
||||
float previous_progress = 0.0;
|
||||
audio_progress_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ExportVideoDialog::audio_progress_display), 100);
|
||||
previous_progress = 0.0;
|
||||
while (status->running) {
|
||||
if (aborted) { status->abort(); }
|
||||
|
||||
float progress = 0.0;
|
||||
if (status->normalizing) {
|
||||
pbar.set_text (_("Normalizing audio"));
|
||||
progress = ((float) status->current_normalize_cycle) / status->total_normalize_cycles;
|
||||
} else {
|
||||
pbar.set_text (_("Exporting audio"));
|
||||
progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan;
|
||||
}
|
||||
if (progress < previous_progress) {
|
||||
// Work around gtk bug
|
||||
pbar.hide();
|
||||
pbar.show();
|
||||
}
|
||||
previous_progress = progress;
|
||||
pbar.set_fraction (progress);
|
||||
if (gtk_events_pending()) {
|
||||
gtk_main_iteration ();
|
||||
} else {
|
||||
usleep (10000);
|
||||
}
|
||||
}
|
||||
audio_progress_connection.disconnect();
|
||||
status->finish ();
|
||||
if (status->aborted()) {
|
||||
unlink (insnd.c_str());
|
||||
@@ -775,7 +799,6 @@ ExportVideoDialog::video_codec_combo_changed ()
|
||||
{
|
||||
if (( video_codec_combo.get_active_text() == "mpeg4"
|
||||
||video_codec_combo.get_active_text() == "mpeg2video"
|
||||
||video_codec_combo.get_active_text() == "flv"
|
||||
) && !(
|
||||
preset_combo.get_active_text() == "dvd-PAL"
|
||||
||preset_combo.get_active_text() == "dvd-NTSC"
|
||||
@@ -888,14 +911,14 @@ ExportVideoDialog::preset_combo_changed ()
|
||||
if (p == "dvd-PAL" || p == "dvd-NTSC") {
|
||||
for (it = c.begin(); it != c.end(); ++it) {
|
||||
int row = it->get_top_attach();
|
||||
if (row ==1 || row ==2 || row==4 || row==5 || row == 8) {
|
||||
if (row == 2 || row == 3 || row== 5 || row== 6 || row == 9) {
|
||||
it->get_widget()->hide();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (it = c.begin(); it != c.end(); ++it) {
|
||||
int row = it->get_top_attach();
|
||||
if (row ==1 || row ==2 || row==4 || row==5 || row == 8) {
|
||||
if (row == 2 || row == 3 || row== 5 || row== 6 || row == 9) {
|
||||
it->get_widget()->show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,17 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList
|
||||
|
||||
bool aborted;
|
||||
bool twopass;
|
||||
bool firstpass;
|
||||
bool normalize;
|
||||
|
||||
void finished ();
|
||||
void update_progress (ARDOUR::framecnt_t, ARDOUR::framecnt_t);
|
||||
|
||||
boost::shared_ptr<ARDOUR::ExportStatus> status;
|
||||
sigc::connection audio_progress_connection;
|
||||
gint audio_progress_display ();
|
||||
float previous_progress;
|
||||
|
||||
TranscodeFfmpeg *transcoder;
|
||||
std::string insnd;
|
||||
|
||||
|
||||
114
gtk2_ardour/hit.cc
Normal file
114
gtk2_ardour/hit.cc
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: Dave Robillard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "evoral/Note.hpp"
|
||||
#include "canvas/polygon.h"
|
||||
#include "midi_region_view.h"
|
||||
#include "public_editor.h"
|
||||
#include "utils.h"
|
||||
#include "hit.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace ArdourCanvas;
|
||||
|
||||
Hit::Hit (
|
||||
MidiRegionView& region,
|
||||
Group* group,
|
||||
double /*size*/,
|
||||
const boost::shared_ptr<NoteType> note,
|
||||
bool with_events)
|
||||
: NoteBase (region, with_events, note)
|
||||
{
|
||||
_polygon = new Polygon (group);
|
||||
set_item (_polygon);
|
||||
}
|
||||
|
||||
void
|
||||
Hit::move_event (double dx, double dy)
|
||||
{
|
||||
_polygon->move (Duple (dx, dy));
|
||||
}
|
||||
|
||||
Coord
|
||||
Hit::x0 () const
|
||||
{
|
||||
boost::optional<Rect> bbox = _polygon->bounding_box ();
|
||||
assert (bbox);
|
||||
return bbox.get().x0;
|
||||
}
|
||||
|
||||
Coord
|
||||
Hit::x1 () const
|
||||
{
|
||||
boost::optional<Rect> bbox = _polygon->bounding_box ();
|
||||
assert (bbox);
|
||||
return bbox.get().x1;
|
||||
}
|
||||
|
||||
Coord
|
||||
Hit::y0 () const
|
||||
{
|
||||
boost::optional<Rect> bbox = _polygon->bounding_box ();
|
||||
assert (bbox);
|
||||
return bbox.get().y0;
|
||||
}
|
||||
|
||||
Coord
|
||||
Hit::y1 () const
|
||||
{
|
||||
boost::optional<Rect> bbox = _polygon->bounding_box ();
|
||||
assert (bbox);
|
||||
return bbox.get().y1;
|
||||
}
|
||||
|
||||
void
|
||||
Hit::set_outline_color (uint32_t color)
|
||||
{
|
||||
_polygon->set_outline_color (color);
|
||||
}
|
||||
|
||||
void
|
||||
Hit::set_fill_color (uint32_t color)
|
||||
{
|
||||
_polygon->set_fill_color (color);
|
||||
}
|
||||
|
||||
void
|
||||
Hit::show ()
|
||||
{
|
||||
_polygon->show ();
|
||||
}
|
||||
|
||||
void
|
||||
Hit::hide ()
|
||||
{
|
||||
_polygon->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
Hit::set_height (Distance /*height*/)
|
||||
{
|
||||
/* XXX */
|
||||
}
|
||||
|
||||
void
|
||||
Hit::set_position (Duple position)
|
||||
{
|
||||
_polygon->set_position (position);
|
||||
}
|
||||
63
gtk2_ardour/hit.h
Normal file
63
gtk2_ardour/hit.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: Dave Robillard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __gtk_ardour_hit_h__
|
||||
#define __gtk_ardour_hit_h__
|
||||
|
||||
#include <iostream>
|
||||
#include "note_base.h"
|
||||
|
||||
namespace ArdourCanvas {
|
||||
class Polygon;
|
||||
}
|
||||
|
||||
class Hit : public NoteBase
|
||||
{
|
||||
public:
|
||||
typedef Evoral::Note<double> NoteType;
|
||||
|
||||
Hit (
|
||||
MidiRegionView& region,
|
||||
ArdourCanvas::Group* group,
|
||||
double size,
|
||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>(),
|
||||
bool with_events = true);
|
||||
|
||||
void show ();
|
||||
void hide ();
|
||||
|
||||
ArdourCanvas::Coord x0 () const;
|
||||
ArdourCanvas::Coord y0 () const;
|
||||
ArdourCanvas::Coord x1 () const;
|
||||
ArdourCanvas::Coord y1 () const;
|
||||
|
||||
void set_position (ArdourCanvas::Duple);
|
||||
|
||||
void set_height (ArdourCanvas::Coord);
|
||||
|
||||
void set_outline_color (uint32_t);
|
||||
void set_fill_color (uint32_t);
|
||||
|
||||
void move_event (double, double);
|
||||
|
||||
private:
|
||||
ArdourCanvas::Polygon* _polygon;
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_hit_h__ */
|
||||
376
gtk2_ardour/note_base.cc
Normal file
376
gtk2_ardour/note_base.cc
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: David Robillard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gtkmm2ext/keyboard.h"
|
||||
|
||||
#include "canvas/text.h"
|
||||
|
||||
#include "note_base.h"
|
||||
#include "midi_region_view.h"
|
||||
#include "public_editor.h"
|
||||
#include "editing_syms.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Gtkmm2ext;
|
||||
using ARDOUR::MidiModel;
|
||||
using namespace ArdourCanvas;
|
||||
|
||||
PBD::Signal1<void,NoteBase*> NoteBase::NoteBaseDeleted;
|
||||
|
||||
/// dividing the hue circle in 16 parts, hand adjusted for equal look, courtesy Thorsten Wilms
|
||||
const uint32_t NoteBase::midi_channel_colors[16] = {
|
||||
0xd32d2dff, 0xd36b2dff, 0xd3972dff, 0xd3d12dff,
|
||||
0xa0d32dff, 0x7dd32dff, 0x2dd45eff, 0x2dd3c4ff,
|
||||
0x2da5d3ff, 0x2d6fd3ff, 0x432dd3ff, 0x662dd3ff,
|
||||
0x832dd3ff, 0xa92dd3ff, 0xd32dbfff, 0xd32d67ff
|
||||
};
|
||||
|
||||
NoteBase::NoteBase(MidiRegionView& region, bool with_events, const boost::shared_ptr<NoteType> note)
|
||||
: _region(region)
|
||||
, _item (0)
|
||||
, _text(0)
|
||||
// , _channel_selector_widget()
|
||||
, _state(None)
|
||||
, _note(note)
|
||||
, _with_events (with_events)
|
||||
, _selected(false)
|
||||
, _valid (true)
|
||||
, _mouse_x_fraction (-1.0)
|
||||
, _mouse_y_fraction (-1.0)
|
||||
{
|
||||
}
|
||||
|
||||
NoteBase::~NoteBase()
|
||||
{
|
||||
NoteBaseDeleted (this);
|
||||
|
||||
delete _text;
|
||||
|
||||
/* XXX */
|
||||
// delete _channel_selector_widget;
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::set_item (Item* item)
|
||||
{
|
||||
_item = item;
|
||||
_item->set_data ("notebase", this);
|
||||
|
||||
if (_with_events) {
|
||||
_item->Event.connect (sigc::mem_fun (*this, &NoteBase::event_handler));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::invalidate ()
|
||||
{
|
||||
_valid = false;
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::validate ()
|
||||
{
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::show_velocity()
|
||||
{
|
||||
if (!_text) {
|
||||
_text = new Text (_item->parent ());
|
||||
_text->set_ignore_events (true);
|
||||
_text->set_color (ARDOUR_UI::config()->canvasvar_MidiNoteVelocityText.get());
|
||||
_text->set_alignment (Pango::ALIGN_CENTER);
|
||||
}
|
||||
|
||||
_text->set_x_position ((x0() + x1()) / 2);
|
||||
_text->set_y_position ((y0() + y1()) / 2);
|
||||
ostringstream velo(ios::ate);
|
||||
velo << int(_note->velocity());
|
||||
_text->set (velo.str ());
|
||||
_text->show();
|
||||
_text->raise_to_top();
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::hide_velocity()
|
||||
{
|
||||
delete _text;
|
||||
_text = 0;
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::on_channel_selection_change(uint16_t selection)
|
||||
{
|
||||
// make note change its color if its channel is not marked active
|
||||
if ( (selection & (1 << _note->channel())) == 0 ) {
|
||||
set_fill_color(ARDOUR_UI::config()->canvasvar_MidiNoteInactiveChannel.get());
|
||||
set_outline_color(calculate_outline(ARDOUR_UI::config()->canvasvar_MidiNoteInactiveChannel.get()));
|
||||
} else {
|
||||
// set the color according to the notes selection state
|
||||
set_selected(_selected);
|
||||
}
|
||||
// this forces the item to update..... maybe slow...
|
||||
_item->hide();
|
||||
_item->show();
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::on_channel_change(uint8_t channel)
|
||||
{
|
||||
_region.note_selected(this, true);
|
||||
hide_channel_selector();
|
||||
_region.change_channel(channel);
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::show_channel_selector ()
|
||||
{
|
||||
#if 0
|
||||
if (_channel_selector_widget == 0) {
|
||||
|
||||
if(_region.channel_selector_scoped_note() != 0){
|
||||
_region.channel_selector_scoped_note()->hide_channel_selector();
|
||||
_region.set_channel_selector_scoped_note(0);
|
||||
}
|
||||
|
||||
SingleMidiChannelSelector* _channel_selector = new SingleMidiChannelSelector(_note->channel());
|
||||
_channel_selector->show_all();
|
||||
_channel_selector->channel_selected.connect(
|
||||
sigc::mem_fun(this, &NoteBase::on_channel_change));
|
||||
|
||||
_channel_selector->clicked.connect (
|
||||
sigc::mem_fun (this, &NoteBase::hide_channel_selector));
|
||||
|
||||
_channel_selector_widget = new Widget(*(_item->property_parent()),
|
||||
x1(),
|
||||
y2() + 2,
|
||||
(Gtk::Widget &) *_channel_selector);
|
||||
|
||||
_channel_selector_widget->hide();
|
||||
_channel_selector_widget->property_height() = 100;
|
||||
_channel_selector_widget->property_width() = 100;
|
||||
_channel_selector_widget->raise_to_top();
|
||||
_channel_selector_widget->show();
|
||||
|
||||
_region.set_channel_selector_scoped_note(this);
|
||||
} else {
|
||||
hide_channel_selector();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::hide_channel_selector ()
|
||||
{
|
||||
#if 0
|
||||
if (_channel_selector_widget) {
|
||||
_channel_selector_widget->hide();
|
||||
delete _channel_selector_widget;
|
||||
_channel_selector_widget = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::set_selected(bool selected)
|
||||
{
|
||||
if (!_note) {
|
||||
return;
|
||||
}
|
||||
|
||||
_selected = selected;
|
||||
set_fill_color (base_color ());
|
||||
|
||||
if (_selected) {
|
||||
set_outline_color(calculate_outline(ARDOUR_UI::config()->canvasvar_MidiNoteSelected.get()));
|
||||
|
||||
if(_region.channel_selector_scoped_note() != 0){
|
||||
_region.channel_selector_scoped_note()->hide_channel_selector();
|
||||
_region.set_channel_selector_scoped_note(0);
|
||||
}
|
||||
} else {
|
||||
set_outline_color(calculate_outline(base_color()));
|
||||
hide_channel_selector();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define SCALE_USHORT_TO_UINT8_T(x) ((x) / 257)
|
||||
|
||||
uint32_t
|
||||
NoteBase::base_color()
|
||||
{
|
||||
using namespace ARDOUR;
|
||||
|
||||
ColorMode mode = _region.color_mode();
|
||||
|
||||
const uint8_t min_opacity = 15;
|
||||
uint8_t opacity = std::max(min_opacity, uint8_t(_note->velocity() + _note->velocity()));
|
||||
|
||||
switch (mode) {
|
||||
case TrackColor:
|
||||
{
|
||||
Gdk::Color color = _region.midi_stream_view()->get_region_color();
|
||||
return UINT_INTERPOLATE (RGBA_TO_UINT(
|
||||
SCALE_USHORT_TO_UINT8_T(color.get_red()),
|
||||
SCALE_USHORT_TO_UINT8_T(color.get_green()),
|
||||
SCALE_USHORT_TO_UINT8_T(color.get_blue()),
|
||||
opacity),
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteSelected.get(), 0.5);
|
||||
}
|
||||
|
||||
case ChannelColors:
|
||||
return UINT_INTERPOLATE (UINT_RGBA_CHANGE_A (NoteBase::midi_channel_colors[_note->channel()],
|
||||
opacity),
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteSelected.get(), 0.5);
|
||||
|
||||
default:
|
||||
return meter_style_fill_color(_note->velocity(), selected());
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
NoteBase::set_mouse_fractions (GdkEvent* ev)
|
||||
{
|
||||
double ix, iy;
|
||||
bool set_cursor = false;
|
||||
|
||||
switch (ev->type) {
|
||||
case GDK_MOTION_NOTIFY:
|
||||
ix = ev->motion.x;
|
||||
iy = ev->motion.y;
|
||||
set_cursor = true;
|
||||
break;
|
||||
case GDK_ENTER_NOTIFY:
|
||||
ix = ev->crossing.x;
|
||||
iy = ev->crossing.y;
|
||||
set_cursor = true;
|
||||
break;
|
||||
case GDK_BUTTON_PRESS:
|
||||
case GDK_BUTTON_RELEASE:
|
||||
ix = ev->button.x;
|
||||
iy = ev->button.y;
|
||||
break;
|
||||
default:
|
||||
_mouse_x_fraction = -1.0;
|
||||
_mouse_y_fraction = -1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
boost::optional<Rect> bbox = _item->bounding_box ();
|
||||
assert (bbox);
|
||||
|
||||
_item->canvas_to_item (ix, iy);
|
||||
/* XXX: CANVAS */
|
||||
/* hmm, something wrong here. w2i should give item-local coordinates
|
||||
but it doesn't. for now, finesse this.
|
||||
*/
|
||||
ix = ix - bbox.get().x0;
|
||||
iy = iy - bbox.get().y0;
|
||||
|
||||
/* fraction of width/height */
|
||||
double xf;
|
||||
double yf;
|
||||
bool notify = false;
|
||||
|
||||
xf = ix / bbox.get().width ();
|
||||
yf = iy / bbox.get().height ();
|
||||
|
||||
if (xf != _mouse_x_fraction || yf != _mouse_y_fraction) {
|
||||
notify = true;
|
||||
}
|
||||
|
||||
_mouse_x_fraction = xf;
|
||||
_mouse_y_fraction = yf;
|
||||
|
||||
if (notify) {
|
||||
if (big_enough_to_trim()) {
|
||||
_region.note_mouse_position (_mouse_x_fraction, _mouse_y_fraction, set_cursor);
|
||||
} else {
|
||||
/* pretend the mouse is in the middle, because this is not big enough
|
||||
to trim right now.
|
||||
*/
|
||||
_region.note_mouse_position (0.5, 0.5, set_cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NoteBase::event_handler (GdkEvent* ev)
|
||||
{
|
||||
if (!_region.get_time_axis_view().editor().internal_editing()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ev->type) {
|
||||
case GDK_ENTER_NOTIFY:
|
||||
set_mouse_fractions (ev);
|
||||
_region.note_entered (this);
|
||||
break;
|
||||
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
set_mouse_fractions (ev);
|
||||
_region.note_left (this);
|
||||
break;
|
||||
|
||||
case GDK_MOTION_NOTIFY:
|
||||
set_mouse_fractions (ev);
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_PRESS:
|
||||
set_mouse_fractions (ev);
|
||||
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state) && _selected) {
|
||||
show_channel_selector();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_BUTTON_RELEASE:
|
||||
set_mouse_fractions (ev);
|
||||
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return _region.get_time_axis_view().editor().canvas_note_event (ev, _item);
|
||||
}
|
||||
|
||||
bool
|
||||
NoteBase::mouse_near_ends () const
|
||||
{
|
||||
return (_mouse_x_fraction >= 0.0 && _mouse_x_fraction < 0.25) ||
|
||||
(_mouse_x_fraction >= 0.75 && _mouse_x_fraction < 1.0);
|
||||
}
|
||||
|
||||
bool
|
||||
NoteBase::big_enough_to_trim () const
|
||||
{
|
||||
return (x1() - x0()) > 10;
|
||||
}
|
||||
|
||||
172
gtk2_ardour/note_base.h
Normal file
172
gtk2_ardour/note_base.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: David Robillard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __gtk_ardour_note_base_h__
|
||||
#define __gtk_ardour_note_base_h__
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "canvas/types.h"
|
||||
#include "ardour/midi_model.h"
|
||||
|
||||
#include "rgb_macros.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "ui_config.h"
|
||||
|
||||
class Editor;
|
||||
class MidiRegionView;
|
||||
|
||||
namespace Evoral {
|
||||
template<typename T> class Note;
|
||||
}
|
||||
|
||||
namespace ArdourCanvas {
|
||||
class Item;
|
||||
class Text;
|
||||
}
|
||||
|
||||
/** This manages all the event handling for any MIDI event on the canvas.
|
||||
*
|
||||
* This is not actually a canvas item itself to avoid the dreaded diamond,
|
||||
* since various types of canvas items (Note (rect), Hit (diamond), etc)
|
||||
* need to share this functionality but can't share an ancestor.
|
||||
*
|
||||
* Note: Because of this, derived classes need to manually bounce events to
|
||||
* on_event, it won't happen automatically.
|
||||
*
|
||||
* A newer, better canvas should remove the need for all the ugly here.
|
||||
*/
|
||||
class NoteBase : public sigc::trackable
|
||||
{
|
||||
public:
|
||||
typedef Evoral::Note<ARDOUR::MidiModel::TimeType> NoteType;
|
||||
|
||||
NoteBase (
|
||||
MidiRegionView& region,
|
||||
bool,
|
||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>()
|
||||
);
|
||||
|
||||
virtual ~NoteBase ();
|
||||
|
||||
void set_item (ArdourCanvas::Item *);
|
||||
|
||||
static PBD::Signal1<void, NoteBase*> NoteBaseDeleted;
|
||||
|
||||
virtual void show() = 0;
|
||||
virtual void hide() = 0;
|
||||
|
||||
bool valid() const { return _valid; }
|
||||
void invalidate ();
|
||||
void validate ();
|
||||
|
||||
bool selected() const { return _selected; }
|
||||
void set_selected(bool yn);
|
||||
|
||||
virtual void move_event(double dx, double dy) = 0;
|
||||
|
||||
uint32_t base_color();
|
||||
|
||||
void show_velocity();
|
||||
void hide_velocity();
|
||||
|
||||
/** Channel changed for this specific event */
|
||||
void on_channel_change(uint8_t channel);
|
||||
|
||||
/** Channel selection changed */
|
||||
void on_channel_selection_change(uint16_t selection);
|
||||
|
||||
void show_channel_selector();
|
||||
void hide_channel_selector();
|
||||
|
||||
virtual void set_outline_color(uint32_t c) = 0;
|
||||
virtual void set_fill_color(uint32_t c) = 0;
|
||||
|
||||
virtual ArdourCanvas::Coord x0 () const = 0;
|
||||
virtual ArdourCanvas::Coord y0 () const = 0;
|
||||
virtual ArdourCanvas::Coord x1 () const = 0;
|
||||
virtual ArdourCanvas::Coord y1 () const = 0;
|
||||
|
||||
float mouse_x_fraction() const { return _mouse_x_fraction; }
|
||||
float mouse_y_fraction() const { return _mouse_y_fraction; }
|
||||
|
||||
const boost::shared_ptr<NoteType> note() const { return _note; }
|
||||
MidiRegionView& region_view() const { return _region; }
|
||||
|
||||
inline static uint32_t meter_style_fill_color(uint8_t vel, bool selected) {
|
||||
if (selected) {
|
||||
if (vel < 64) {
|
||||
return UINT_INTERPOLATE(
|
||||
ARDOUR_UI::config()->canvasvar_SelectedMidiNoteColorBase.get(),
|
||||
ARDOUR_UI::config()->canvasvar_SelectedMidiNoteColorMid.get(),
|
||||
(vel / (double)63.0));
|
||||
} else {
|
||||
return UINT_INTERPOLATE(
|
||||
ARDOUR_UI::config()->canvasvar_SelectedMidiNoteColorMid.get(),
|
||||
ARDOUR_UI::config()->canvasvar_SelectedMidiNoteColorTop.get(),
|
||||
((vel-64) / (double)63.0));
|
||||
}
|
||||
} else {
|
||||
if (vel < 64) {
|
||||
return UINT_INTERPOLATE(
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteColorBase.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteColorMid.get(),
|
||||
(vel / (double)63.0));
|
||||
} else {
|
||||
return UINT_INTERPOLATE(
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteColorMid.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MidiNoteColorTop.get(),
|
||||
((vel-64) / (double)63.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// calculate outline colors from fill colors of notes
|
||||
inline static uint32_t calculate_outline(uint32_t color) {
|
||||
return UINT_INTERPOLATE(color, 0x000000ff, 0.5);
|
||||
}
|
||||
|
||||
/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
|
||||
static const uint32_t midi_channel_colors[16];
|
||||
|
||||
bool mouse_near_ends () const;
|
||||
bool big_enough_to_trim () const;
|
||||
|
||||
protected:
|
||||
enum State { None, Pressed, Dragging };
|
||||
|
||||
MidiRegionView& _region;
|
||||
ArdourCanvas::Item* _item;
|
||||
ArdourCanvas::Text* _text;
|
||||
// Widget* _channel_selector_widget;
|
||||
State _state;
|
||||
const boost::shared_ptr<NoteType> _note;
|
||||
bool _with_events;
|
||||
bool _own_note;
|
||||
bool _selected;
|
||||
bool _valid;
|
||||
float _mouse_x_fraction;
|
||||
float _mouse_y_fraction;
|
||||
|
||||
void set_mouse_fractions (GdkEvent*);
|
||||
|
||||
private:
|
||||
bool event_handler (GdkEvent *);
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_note_h__ */
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
NSM_Client::NSM_Client()
|
||||
{
|
||||
_session_loaded = false;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -59,9 +58,3 @@ NSM_Client::command_open(const char *name,
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
NSM_Client::command_session_is_loaded ( void )
|
||||
{
|
||||
_session_loaded = true;
|
||||
}
|
||||
|
||||
@@ -28,17 +28,12 @@ class NSM_Client:public NSM::Client
|
||||
NSM_Client();
|
||||
~NSM_Client() { }
|
||||
|
||||
bool session_loaded(void) { return _session_loaded; }
|
||||
|
||||
protected:
|
||||
|
||||
bool _session_loaded;
|
||||
|
||||
int command_open(const char *name,
|
||||
const char *display_name,
|
||||
const char *client_id,
|
||||
char **out_msg);
|
||||
int command_save(char **out_msg);
|
||||
void command_session_is_loaded (void);
|
||||
};
|
||||
|
||||
|
||||
@@ -295,6 +295,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
|
||||
virtual void queue_visual_videotimeline_update () = 0;
|
||||
virtual void toggle_ruler_video (bool) = 0;
|
||||
virtual void toggle_xjadeo_proc (int) = 0;
|
||||
virtual void toggle_xjadeo_viewoption (int, int) = 0;
|
||||
virtual void set_xjadeo_sensitive (bool onoff) = 0;
|
||||
virtual int get_videotl_bar_height () const = 0;
|
||||
virtual void set_video_timeline_height (const int h) = 0;
|
||||
|
||||
@@ -345,7 +345,7 @@ RhythmFerret::do_split_action ()
|
||||
performed on the selection only (without entered_regionview or the edit point
|
||||
being considered)
|
||||
*/
|
||||
RegionSelection regions = editor.get_regions_from_selection();
|
||||
RegionSelection regions = editor.selection->regions;
|
||||
|
||||
if (regions.empty()) {
|
||||
return;
|
||||
|
||||
@@ -243,7 +243,7 @@ RouteTimeAxisView::set_route (boost::shared_ptr<Route> rt)
|
||||
|
||||
route_group_menu = new RouteGroupMenu (_session, plist);
|
||||
|
||||
// gm.get_gain_slider().signal_scroll_event().connect(sigc::mem_fun(*this, &RouteTimeAxisView::controls_ebox_scroll), false);
|
||||
gm.get_gain_slider().signal_scroll_event().connect(sigc::mem_fun(*this, &RouteTimeAxisView::controls_ebox_scroll), false);
|
||||
|
||||
gm.get_level_meter().signal_scroll_event().connect (sigc::mem_fun (*this, &RouteTimeAxisView::controls_ebox_scroll), false);
|
||||
}
|
||||
|
||||
86
gtk2_ardour/sys_ex.cc
Normal file
86
gtk2_ardour/sys_ex.cc
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (C) 2009 Paul Davis
|
||||
Author: Hans Baier
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "canvas/flag.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "sys_ex.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SysEx::SysEx (
|
||||
MidiRegionView& region,
|
||||
ArdourCanvas::Group* parent,
|
||||
string& text,
|
||||
double height,
|
||||
double x,
|
||||
double y)
|
||||
: _region (region)
|
||||
{
|
||||
_flag = new ArdourCanvas::Flag (
|
||||
parent,
|
||||
height,
|
||||
ARDOUR_UI::config()->canvasvar_MidiSysExOutline.get(),
|
||||
ARDOUR_UI::config()->canvasvar_MidiSysExFill.get(),
|
||||
ArdourCanvas::Duple (x, y)
|
||||
);
|
||||
|
||||
_flag->set_text (text);
|
||||
}
|
||||
|
||||
SysEx::~SysEx()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SysEx::event_handler (GdkEvent* ev)
|
||||
{
|
||||
switch (ev->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (ev->button.button == 3) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GDK_SCROLL:
|
||||
if (ev->scroll.direction == GDK_SCROLL_UP) {
|
||||
return true;
|
||||
} else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SysEx::hide ()
|
||||
{
|
||||
_flag->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
SysEx::show ()
|
||||
{
|
||||
_flag->show ();
|
||||
}
|
||||
54
gtk2_ardour/sys_ex.h
Normal file
54
gtk2_ardour/sys_ex.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (C) 2009 Paul Davis
|
||||
Author: Hans Baier
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SYSEX_H__
|
||||
#define __SYSEX_H__
|
||||
|
||||
class MidiRegionView;
|
||||
|
||||
namespace ArdourCanvas {
|
||||
class Flag;
|
||||
}
|
||||
|
||||
class SysEx
|
||||
{
|
||||
public:
|
||||
SysEx (
|
||||
MidiRegionView& region,
|
||||
ArdourCanvas::Group* parent,
|
||||
std::string& text,
|
||||
double height,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
~SysEx ();
|
||||
|
||||
void hide ();
|
||||
void show ();
|
||||
|
||||
ArdourCanvas::Item& item() const { return *_flag; }
|
||||
|
||||
private:
|
||||
bool event_handler (GdkEvent* ev);
|
||||
|
||||
MidiRegionView& _region;
|
||||
ArdourCanvas::Flag* _flag;
|
||||
};
|
||||
|
||||
#endif /* __SYSEX_H__ */
|
||||
@@ -418,7 +418,7 @@ SystemExec::terminate ()
|
||||
if (pid) {
|
||||
::fprintf(stderr, "Child process is running. trying SIGTERM\n");
|
||||
::kill(pid, SIGTERM);
|
||||
::usleep(10000);
|
||||
::usleep(50000);
|
||||
wait(WNOHANG);
|
||||
}
|
||||
if (pid) {
|
||||
|
||||
@@ -464,7 +464,7 @@ TranscodeFfmpeg::transcode (std::string outfile, const int outw, const int outh,
|
||||
argp[6] = (char*) calloc(10,sizeof(char)); snprintf(argp[6], 10, "%ix%i", width, height);
|
||||
argp[7] = strdup("-y");
|
||||
argp[8] = strdup("-vcodec");
|
||||
argp[9] = strdup("mjpeg");
|
||||
argp[9] = strdup("mpeg4");
|
||||
argp[10] = strdup("-an");
|
||||
argp[11] = strdup("-intra");
|
||||
argp[12] = strdup("-g");
|
||||
|
||||
@@ -39,10 +39,14 @@ VideoMonitor::VideoMonitor (PublicEditor *ed, std::string xjadeo_bin_path)
|
||||
sync_by_manual_seek = false;
|
||||
_restore_settings_mask = 0;
|
||||
clock_connection = sigc::connection();
|
||||
state_connection = sigc::connection();
|
||||
debug_enable = false;
|
||||
state_clk_divide = 0;
|
||||
starting = 0;
|
||||
osdmode = 10; // 1: frameno, 2: timecode, 8: box
|
||||
|
||||
process = new SystemExec(xjadeo_bin_path, X_("-R"));
|
||||
process->ReadStdout.connect (*this, invalidator (*this), boost::bind (&VideoMonitor::parse_output, this, _1 ,_2), gui_context());
|
||||
process->ReadStdout.connect_same_thread (*this, boost::bind (&VideoMonitor::parse_output, this, _1 ,_2));
|
||||
process->Terminated.connect (*this, invalidator (*this), boost::bind (&VideoMonitor::terminated, this), gui_context());
|
||||
}
|
||||
|
||||
@@ -51,6 +55,9 @@ VideoMonitor::~VideoMonitor ()
|
||||
if (clock_connection.connected()) {
|
||||
clock_connection.disconnect();
|
||||
}
|
||||
if (state_connection.connected()) {
|
||||
state_connection.disconnect();
|
||||
}
|
||||
delete process;
|
||||
}
|
||||
|
||||
@@ -75,6 +82,8 @@ void
|
||||
VideoMonitor::quit ()
|
||||
{
|
||||
if (!is_started()) return;
|
||||
if (state_connection.connected()) { state_connection.disconnect(); }
|
||||
if (clock_connection.connected()) { clock_connection.disconnect(); }
|
||||
process->write_to_stdin("get windowsize\n");
|
||||
process->write_to_stdin("get windowpos\n");
|
||||
process->write_to_stdin("get letterbox\n");
|
||||
@@ -92,13 +101,14 @@ VideoMonitor::quit ()
|
||||
int timeout = 40;
|
||||
while (is_started() && --timeout) {
|
||||
usleep(50000);
|
||||
sched_yield();
|
||||
}
|
||||
if (timeout == 0) {
|
||||
if (timeout <= 0) {
|
||||
printf("xjadeo connection: time-out. session may not be saved.\n");
|
||||
process->terminate();
|
||||
}
|
||||
#endif
|
||||
process->terminate();
|
||||
if (clock_connection.connected()) { clock_connection.disconnect(); }
|
||||
save_session();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -106,7 +116,9 @@ VideoMonitor::open (std::string filename)
|
||||
{
|
||||
if (!is_started()) return;
|
||||
manually_seeked_frame = 0;
|
||||
osdmode = 10; // 1: frameno, 2: timecode, 8: box
|
||||
sync_by_manual_seek = false;
|
||||
starting = 15;
|
||||
process->write_to_stdin("load " + filename + "\n");
|
||||
process->write_to_stdin("set fps -1\n");
|
||||
process->write_to_stdin("window resize 100%\n");
|
||||
@@ -119,9 +131,29 @@ VideoMonitor::open (std::string filename)
|
||||
if (skip_setting(it->first)) { continue; }
|
||||
process->write_to_stdin(it->first + " " + it->second + "\n");
|
||||
}
|
||||
if (!state_connection.connected()) {
|
||||
starting = 15;
|
||||
querystate();
|
||||
state_clk_divide = 0;
|
||||
/* TODO once every two second or so -- state_clk_divide hack below */
|
||||
state_connection = ARDOUR_UI::RapidScreenUpdate.connect (sigc::mem_fun (*this, &VideoMonitor::querystate));
|
||||
}
|
||||
xjadeo_sync_setup();
|
||||
}
|
||||
|
||||
void
|
||||
VideoMonitor::querystate ()
|
||||
{
|
||||
/* clock-divider hack -- RapidScreenUpdate == every_point_one_seconds */
|
||||
state_clk_divide = (state_clk_divide + 1) % 15; // every 1.5 seconds
|
||||
if (state_clk_divide != 0) return;
|
||||
|
||||
process->write_to_stdin("get fullscreen\n");
|
||||
process->write_to_stdin("get ontop\n");
|
||||
process->write_to_stdin("get osdcfg\n");
|
||||
process->write_to_stdin("get letterbox\n");
|
||||
}
|
||||
|
||||
bool
|
||||
VideoMonitor::skip_setting (std::string which)
|
||||
{
|
||||
@@ -136,6 +168,51 @@ VideoMonitor::skip_setting (std::string which)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
VideoMonitor::send_cmd (int what, int param)
|
||||
{
|
||||
bool osd_update = false;
|
||||
if (!is_started()) return;
|
||||
switch (what) {
|
||||
case 1:
|
||||
if (param) process->write_to_stdin("window ontop on\n");
|
||||
else process->write_to_stdin("window ontop off\n");
|
||||
break;
|
||||
case 2:
|
||||
if (param) osdmode |= 2;
|
||||
else osdmode &= ~2;
|
||||
osd_update = true;
|
||||
break;
|
||||
case 3:
|
||||
if (param) osdmode |= 1;
|
||||
else osdmode &= ~1;
|
||||
osd_update = true;
|
||||
break;
|
||||
case 4:
|
||||
if (param) osdmode |= 8;
|
||||
else osdmode &= ~8;
|
||||
osd_update = true;
|
||||
break;
|
||||
case 5:
|
||||
if (param) process->write_to_stdin("window zoom on\n");
|
||||
else process->write_to_stdin("window zoom off\n");
|
||||
break;
|
||||
case 6:
|
||||
if (param) process->write_to_stdin("window letterbox on\n");
|
||||
else process->write_to_stdin("window letterbox off\n");
|
||||
break;
|
||||
case 7:
|
||||
process->write_to_stdin("window resize 100%");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (osd_update >= 0) {
|
||||
std::ostringstream osstream; osstream << "osd mode " << osdmode << "\n";
|
||||
process->write_to_stdin(osstream.str());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
VideoMonitor::is_started ()
|
||||
{
|
||||
@@ -196,12 +273,37 @@ VideoMonitor::parse_output (std::string d, size_t s)
|
||||
} else if(key == "windowsize") {
|
||||
xjadeo_settings["window size"] = value;
|
||||
} else if(key == "windowontop") {
|
||||
if (starting || xjadeo_settings["window ontop"] != value) {
|
||||
starting &= ~2;
|
||||
if (atoi(value.c_str())) { UiState("xjadeo-window-ontop-on"); }
|
||||
else { UiState("xjadeo-window-ontop-off"); }
|
||||
}
|
||||
xjadeo_settings["window ontop"] = value;
|
||||
} else if(key == "fullscreen") {
|
||||
if (starting || xjadeo_settings["window zoom"] != value) {
|
||||
starting &= ~4;
|
||||
if (atoi(value.c_str())) { UiState("xjadeo-window-fullscreen-on"); }
|
||||
else { UiState("xjadeo-window-fullscreen-off"); }
|
||||
}
|
||||
xjadeo_settings["window zoom"] = value;
|
||||
} else if(key == "letterbox") {
|
||||
if (starting || xjadeo_settings["window letterbox"] != value) {
|
||||
starting &= ~8;
|
||||
if (atoi(value.c_str())) { UiState("xjadeo-window-letterbox-on"); }
|
||||
else { UiState("xjadeo-window-letterbox-off"); }
|
||||
}
|
||||
xjadeo_settings["window letterbox"] = value;
|
||||
} else if(key == "osdmode") {
|
||||
if (starting || xjadeo_settings["osd mode"] != value) {
|
||||
starting &= ~1;
|
||||
osdmode = atoi(value.c_str());
|
||||
if ((osdmode & 1) == 1) { UiState("xjadeo-window-osd-frame-on"); }
|
||||
if ((osdmode & 1) == 0) { UiState("xjadeo-window-osd-frame-off"); }
|
||||
if ((osdmode & 2) == 2) { UiState("xjadeo-window-osd-timecode-on"); }
|
||||
if ((osdmode & 2) == 0) { UiState("xjadeo-window-osd-timecode-off"); }
|
||||
if ((osdmode & 8) == 8) { UiState("xjadeo-window-osd-box-on"); }
|
||||
if ((osdmode & 8) == 0) { UiState("xjadeo-window-osd-box-off"); }
|
||||
}
|
||||
xjadeo_settings["osd mode"] = value;
|
||||
} else if(key == "offset") {
|
||||
xjadeo_settings["set offset"] = value;
|
||||
@@ -218,6 +320,7 @@ VideoMonitor::parse_output (std::string d, size_t s)
|
||||
void
|
||||
VideoMonitor::terminated ()
|
||||
{
|
||||
process->terminate(); // from gui-context clean up
|
||||
save_session();
|
||||
Terminated();
|
||||
}
|
||||
@@ -298,6 +401,7 @@ VideoMonitor::get_custom_setting (const std::string k)
|
||||
{
|
||||
return (xjadeo_settings[k]);
|
||||
}
|
||||
|
||||
#define NO_OFFSET (1<<31) //< skip setting or modifying offset -- TODO check ARDOUR::frameoffset_t max value.
|
||||
void
|
||||
VideoMonitor::srsupdate ()
|
||||
|
||||
@@ -71,9 +71,12 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
|
||||
void set_offset (ARDOUR::frameoffset_t);
|
||||
void manual_seek (ARDOUR::framepos_t, bool, ARDOUR::frameoffset_t);
|
||||
void srsupdate ();
|
||||
void querystate ();
|
||||
bool synced_by_manual_seeks() { return sync_by_manual_seek; }
|
||||
|
||||
sigc::signal<void> Terminated;
|
||||
PBD::Signal1<void,std::string> UiState;
|
||||
void send_cmd (int what, int param);
|
||||
|
||||
#if 1
|
||||
void set_debug (bool onoff) { debug_enable = onoff; }
|
||||
@@ -99,6 +102,10 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
|
||||
ARDOUR::framepos_t manually_seeked_frame;
|
||||
bool sync_by_manual_seek;
|
||||
sigc::connection clock_connection;
|
||||
sigc::connection state_connection;
|
||||
int state_clk_divide;
|
||||
int starting;
|
||||
int osdmode;
|
||||
#if 1
|
||||
bool debug_enable;
|
||||
#endif
|
||||
|
||||
@@ -155,8 +155,8 @@ VideoTimeLine::close_session ()
|
||||
if (video_duration == 0) {
|
||||
return;
|
||||
}
|
||||
close_video_monitor();
|
||||
save_session();
|
||||
close_video_monitor();
|
||||
|
||||
remove_frames();
|
||||
video_filename = "";
|
||||
@@ -581,6 +581,30 @@ VideoTimeLine::gui_update(std::string const & t) {
|
||||
editor->toggle_xjadeo_proc(0);
|
||||
//close_video_monitor();
|
||||
editor->set_xjadeo_sensitive(false);
|
||||
} else if (t == "xjadeo-window-ontop-on") {
|
||||
editor->toggle_xjadeo_viewoption(1, 1);
|
||||
} else if (t == "xjadeo-window-ontop-off") {
|
||||
editor->toggle_xjadeo_viewoption(1, 0);
|
||||
} else if (t == "xjadeo-window-osd-timecode-on") {
|
||||
editor->toggle_xjadeo_viewoption(2, 1);
|
||||
} else if (t == "xjadeo-window-osd-timecode-off") {
|
||||
editor->toggle_xjadeo_viewoption(2, 0);
|
||||
} else if (t == "xjadeo-window-osd-frame-on") {
|
||||
editor->toggle_xjadeo_viewoption(3, 1);
|
||||
} else if (t == "xjadeo-window-osd-frame-off") {
|
||||
editor->toggle_xjadeo_viewoption(3, 0);
|
||||
} else if (t == "xjadeo-window-osd-box-on") {
|
||||
editor->toggle_xjadeo_viewoption(4, 1);
|
||||
} else if (t == "xjadeo-window-osd-box-off") {
|
||||
editor->toggle_xjadeo_viewoption(4, 0);
|
||||
} else if (t == "xjadeo-window-fullscreen-on") {
|
||||
editor->toggle_xjadeo_viewoption(5, 1);
|
||||
} else if (t == "xjadeo-window-fullscreen-off") {
|
||||
editor->toggle_xjadeo_viewoption(5, 0);
|
||||
} else if (t == "xjadeo-window-letterbox-on") {
|
||||
editor->toggle_xjadeo_viewoption(6, 1);
|
||||
} else if (t == "xjadeo-window-letterbox-off") {
|
||||
editor->toggle_xjadeo_viewoption(6, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,6 +712,7 @@ VideoTimeLine::open_video_monitor() {
|
||||
vmonitor = new VideoMonitor(editor, _xjadeo_bin);
|
||||
vmonitor->set_session(_session);
|
||||
vmonitor->Terminated.connect (sigc::mem_fun (*this, &VideoTimeLine::terminated_video_monitor));
|
||||
vmonitor->UiState.connect (*this, invalidator (*this), boost::bind (&VideoTimeLine::gui_update, this, _1), gui_context());
|
||||
} else if (vmonitor->is_started()) {
|
||||
return;
|
||||
}
|
||||
@@ -723,6 +748,15 @@ VideoTimeLine::close_video_monitor() {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VideoTimeLine::control_video_monitor(int what, int param) {
|
||||
if (!vmonitor || !vmonitor->is_started()) {
|
||||
return;
|
||||
}
|
||||
vmonitor->send_cmd(what, param);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VideoTimeLine::terminated_video_monitor () {
|
||||
if (vmonitor) {
|
||||
|
||||
@@ -78,6 +78,7 @@ class VideoTimeLine : public sigc::trackable, public ARDOUR::SessionHandlePtr, p
|
||||
|
||||
void open_video_monitor ();
|
||||
void close_video_monitor ();
|
||||
void control_video_monitor (int, int);
|
||||
void terminated_video_monitor ();
|
||||
void manual_seek_video_monitor (framepos_t pos);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ using namespace PBD;
|
||||
|
||||
MIDIClock_Slave::MIDIClock_Slave (Session& s, MIDI::Port& p, int ppqn)
|
||||
: ppqn (ppqn)
|
||||
, bandwidth (1.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
{
|
||||
session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
|
||||
rebind (p);
|
||||
@@ -53,7 +53,7 @@ MIDIClock_Slave::MIDIClock_Slave (Session& s, MIDI::Port& p, int ppqn)
|
||||
MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
|
||||
: session(session_proxy)
|
||||
, ppqn (ppqn)
|
||||
, bandwidth (1.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
|
||||
{
|
||||
reset ();
|
||||
}
|
||||
@@ -149,11 +149,12 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
|
||||
calculate_filter_coefficients();
|
||||
|
||||
// calculate loop error
|
||||
// we use session->audible_frame() instead of t1 here
|
||||
// we use session->transport_frame() instead of t1 here
|
||||
// because t1 is used to calculate the transport speed,
|
||||
// so the loop will compensate for accumulating rounding errors
|
||||
error = (double(should_be_position) - double(session->audible_frame()));
|
||||
error = (double(should_be_position) - double(session->transport_frame()));
|
||||
e = error / double(session->frame_rate());
|
||||
current_delta = error;
|
||||
|
||||
// update DLL
|
||||
t0 = t1;
|
||||
@@ -328,8 +329,8 @@ MIDIClock_Slave::speed_and_position (double& speed, framepos_t& pos)
|
||||
// calculate speed
|
||||
speed = ((t1 - t0) * session->frame_rate()) / one_ppqn_in_frames;
|
||||
|
||||
// provide a 3% deadzone to lock the speed
|
||||
if (fabs(speed - 1.0) <= 0.03)
|
||||
// provide a 0.1% deadzone to lock the speed
|
||||
if (fabs(speed - 1.0) <= 0.001)
|
||||
speed = 1.0;
|
||||
|
||||
// calculate position
|
||||
@@ -344,7 +345,6 @@ MIDIClock_Slave::speed_and_position (double& speed, framepos_t& pos)
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiClock, string_compose ("speed_and_position: %1 & %2 <-> %3 (transport)\n", speed, pos, session->transport_frame()));
|
||||
current_delta = pos - session->transport_frame();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -515,7 +515,9 @@ Session::follow_slave (pframes_t nframes)
|
||||
slave_speed = 0.0f;
|
||||
}
|
||||
|
||||
if (_slave->is_always_synced() || Config->get_timecode_source_is_synced()) {
|
||||
if (_slave->is_always_synced() ||
|
||||
(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
|
||||
) {
|
||||
|
||||
/* if the TC source is synced, then we assume that its
|
||||
speed is binary: 0.0 or 1.0
|
||||
@@ -543,7 +545,9 @@ Session::follow_slave (pframes_t nframes)
|
||||
_slave_state, slave_transport_frame, slave_speed, this_delta, average_slave_delta));
|
||||
|
||||
|
||||
if (_slave_state == Running && !_slave->is_always_synced() && !Config->get_timecode_source_is_synced()) {
|
||||
if (_slave_state == Running && !_slave->is_always_synced() &&
|
||||
!(Config->get_timecode_source_is_synced() && (dynamic_cast<TimecodeSlave*>(_slave)) != 0)
|
||||
) {
|
||||
|
||||
if (_transport_speed != 0.0f) {
|
||||
|
||||
|
||||
35
libs/canvas/canvas/fwd.h
Normal file
35
libs/canvas/canvas/fwd.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 2011 Paul Davis
|
||||
Author: Carl Hetherington <cth@carlh.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __canvas_canvas_fwd_h__
|
||||
#define __canvas_canvas_fwd_h__
|
||||
|
||||
namespace ArdourCanvas {
|
||||
class WaveView;
|
||||
class Line;
|
||||
class Rectangle;
|
||||
class Polygon;
|
||||
class PolyLine;
|
||||
class GtkCanvas;
|
||||
class GtkCanvasViewport;
|
||||
class Text;
|
||||
}
|
||||
|
||||
#endif /* __canvas_canvas_fwd_h__ */
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
typedef const Note<Time>* value_type;
|
||||
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||
const boost::shared_ptr< const Note<Time> > b) const {
|
||||
return musical_time_less_than (a->end_time(), b->end_time());
|
||||
return musical_time_greater_than (a->end_time(), b->end_time());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user