: Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
- primary_clock (X_("TransportClockDisplay"), true, false, true),
- secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
- preroll_clock (X_("PreRollClock"), true, true),
- postroll_clock (X_("PostRollClock"), true, true),
+ primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
+ secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
+ preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
+ postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
/* adjuster table */
/* big clock */
- big_clock ("BigClockNonRecording", true, false, true),
+ big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
/* transport */
throw failed_constructor();
}
+ /* listen to clock mode changes */
+
+ AudioClock::ModeChanged.connect (mem_fun (*this, &ARDOUR_UI::store_clock_modes));
+
/* start the time-of-day-clock */
update_wall_clock ();
/* if it already exists, we must have write access */
if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
- MessageDialog msg (*editor, _("\
-You do not have write access to this session.\n\
-This prevents the session from being loaded."));
+ MessageDialog msg (*editor, _("You do not have write access to this session.\n"
+ "This prevents the session from being loaded."));
msg.run ();
return -1;
}
{
XMLNode* node = new XMLNode(X_("ClockModes"));
- node->add_property (X_("primary"), enum_2_string (primary_clock.mode()));
- node->add_property (X_("secondary"), enum_2_string (secondary_clock.mode()));
+ for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
+ node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
+ }
session->add_extra_xml (*node);
session->set_dirty ();
}
-void
-ARDOUR_UI::restore_clock_modes ()
-{
- XMLProperty* prop;
- XMLNode * node = session->extra_xml (X_("ClockModes"));
- AudioClock::Mode mode;
-
- if (node) {
- if ((prop = node->property ("primary")) != 0) {
- mode = AudioClock::Mode (string_2_enum (prop->value(), mode));
- primary_clock.set_mode (mode);
- }
- if ((prop = node->property ("secondary")) != 0) {
- mode = AudioClock::Mode (string_2_enum (prop->value(), mode));
- secondary_clock.set_mode (mode);
- }
- }
-}
#include <cmath>
#include <pbd/convert.h>
+#include <pbd/enumwriter.h>
#include <gtkmm2ext/utils.h>
using namespace PBD;
using namespace sigc;
using namespace Gtk;
+using namespace std;
using PBD::atoi;
using PBD::atof;
+sigc::signal<void> AudioClock::ModeChanged;
+vector<AudioClock*> AudioClock::clocks;
+
const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
2, /* SMPTE_Hours */
2, /* SMPTE_Minutes */
10 /* Audio Frame */
};
-AudioClock::AudioClock (std::string name, bool allow_edit, bool duration, bool with_info)
- : is_duration (duration),
+AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
+ : _name (clock_name),
+ is_transient (transient),
+ is_duration (duration),
editable (allow_edit),
colon1 (":"),
colon2 (":"),
clock_frame.add (clock_base);
- set_name (name);
+ set_widget_name (widget_name);
_mode = BBT; /* lie to force mode switch */
set_mode (SMPTE);
}
set (last_when, true);
+
+ if (!is_transient) {
+ clocks.push_back (this);
+ }
}
void
-AudioClock::set_name (string name)
+AudioClock::set_widget_name (string name)
{
Widget::set_name (name);
}
if (smpte_upper_info_label) {
- float smpte_frames = session->smpte_frames_per_second();
+ double smpte_frames = session->smpte_frames_per_second();
if ( fmod(smpte_frames, 1.0) == 0.0) {
- sprintf (buf, "%u", int (smpte_frames));
+ sprintf (buf, "%u", int (smpte_frames));
} else {
sprintf (buf, "%.2f", smpte_frames);
}
session = s;
if (s) {
+
+ XMLProperty* prop;
+ XMLNode* node = session->extra_xml (X_("ClockModes"));
+ AudioClock::Mode amode;
+
+ if (node) {
+ if ((prop = node->property (_name.c_str())) != 0) {
+ amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
+ set_mode (amode);
+ }
+ }
+
set (last_when, true);
}
}
set (last_when, true);
clock_base.show_all ();
key_entry_state = 0;
+
+ if (!is_transient) {
+ ModeChanged (); /* EMIT SIGNAL */
+ }
}
void
Off
};
- AudioClock (std::string name, bool editable, bool is_duration = false, bool with_info = false);
+ AudioClock (std::string clock_name, bool transient, std::string widget_name, bool editable, bool is_duration = false, bool with_info = false);
Mode mode() const { return _mode; }
void set (nframes_t, bool force = false);
void set_mode (Mode);
- void set_name (std::string);
+ void set_widget_name (std::string);
+
+ std::string name() const { return _name; }
nframes_t current_time (nframes_t position = 0) const;
nframes_t current_duration (nframes_t position = 0) const;
void set_session (ARDOUR::Session *s);
sigc::signal<void> ValueChanged;
-
+
+ static sigc::signal<void> ModeChanged;
+ static std::vector<AudioClock*> clocks;
+
private:
ARDOUR::Session *session;
Mode _mode;
uint32_t key_entry_state;
+ std::string _name;
+ bool is_transient;
bool is_duration;
bool editable;
name_label (_("NAME:")),
audition_button (_("play")),
time_table (3, 2),
- start_clock ("AudioRegionEditorClock", true),
- end_clock ("AudioRegionEditorClock", true),
- length_clock ("AudioRegionEditorClock", true, true),
- sync_offset_clock ("AudioRegionEditorClock", true, true)
+ start_clock (X_("regionstart"), true, X_("AudioRegionEditorClock"), true),
+ end_clock (X_("regionend"), true, X_("AudioRegionEditorClock"), true),
+ length_clock (X_("regionlength"), true, X_("AudioRegionEditorClock"), true, true),
+ sync_offset_clock (X_("regionsyncoffset"), true, X_("AudioRegionEditorClock"), true, true)
{
start_clock.set_session (&_session);
/* tool bar related */
- edit_cursor_clock (X_("EditCursorClock"), true),
- zoom_range_clock (X_("ZoomRangeClock"), true, true),
+ edit_cursor_clock (X_("editcursor"), false, X_("EditCursorClock"), true),
+ zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true),
toolbar_selection_clock_table (2,3),
/* nudge */
- nudge_clock (X_("NudgeClock"), true, true)
+ nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true)
{
constructed = false;
route_list_menu = 0;
region_list_menu = 0;
marker_menu = 0;
+ start_end_marker_menu = 0;
range_marker_menu = 0;
marker_menu_item = 0;
tm_marker_menu = 0;
void clear_markers ();
void clear_ranges ();
void clear_locations ();
+ void unhide_markers ();
+ void unhide_ranges ();
void jump_forward_to_mark ();
void jump_backward_to_mark ();
void cursor_align (bool playhead_to_edit);
void tm_marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
void transport_marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
void new_transport_marker_context_menu (GdkEventButton*, ArdourCanvas::Item*);
- void build_range_marker_menu ();
- void build_marker_menu ();
+ void build_range_marker_menu (bool loop_or_punch);
+ void build_marker_menu (bool start_or_end);
void build_tm_marker_menu ();
- void build_transport_marker_menu ();
void build_new_transport_marker_menu ();
Gtk::Menu* tm_marker_menu;
Gtk::Menu* marker_menu;
+ Gtk::Menu* start_end_marker_menu;
Gtk::Menu* range_marker_menu;
Gtk::Menu* transport_marker_menu;
Gtk::Menu* new_transport_marker_menu;
if (playhead_cursor) playhead_cursor->set_length (canvas_height);
if (marker_drag_line) {
- marker_drag_line_points.back().set_x(canvas_height);
+ marker_drag_line_points.back().set_y(canvas_height);
marker_drag_line->property_points() = marker_drag_line_points;
}
void
Editor::mouse_add_new_marker (nframes_t where)
{
+ string markername;
if (session) {
- Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->locations()->next_available_name(markername,"mark");
+ Location *location = new Location (where, where, markername, Location::IsMark);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
Location* loc = find_location_from_marker (marker, is_start);
if (session && loc) {
- if (loc->is_end()) {
- /* you can't hide or delete this marker */
- return;
- }
- if (loc->is_auto_loop() || loc->is_auto_punch()) {
- // just hide them
- loc->set_hidden (true, this);
- }
- else {
- Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker), loc));
- }
+ Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::really_remove_marker), loc));
}
}
Location * loc = find_location_from_marker (marker, is_start);
if (loc == transport_loop_location() || loc == transport_punch_location()) {
if (transport_marker_menu == 0) {
- build_transport_marker_menu ();
+ build_range_marker_menu (true);
}
marker_menu_item = item;
transport_marker_menu->popup (1, ev->time);
} else {
if (loc->is_mark()) {
- if (marker_menu == 0) {
- build_marker_menu ();
- }
+ bool start_or_end = loc->is_start() || loc->is_end();
+ Menu *markerMenu;
+ if (start_or_end) {
+ if (start_end_marker_menu == 0)
+ build_marker_menu (true);
+ markerMenu = start_end_marker_menu;
+ } else {
+ if (marker_menu == 0)
+ build_marker_menu (false);
+ markerMenu = marker_menu;
+ }
// GTK2FIX use action group sensitivity
}
#endif
marker_menu_item = item;
- marker_menu->popup (1, ev->time);
+ markerMenu->popup (1, ev->time);
}
if (loc->is_range_marker()) {
if (range_marker_menu == 0){
- build_range_marker_menu ();
+ build_range_marker_menu (false);
}
marker_menu_item = item;
range_marker_menu->popup (1, ev->time);
Editor::transport_marker_context_menu (GdkEventButton* ev, ArdourCanvas::Item* item)
{
if (transport_marker_menu == 0) {
- build_transport_marker_menu ();
+ build_range_marker_menu (true);
}
transport_marker_menu->popup (1, ev->time);
}
void
-Editor::build_marker_menu ()
+Editor::build_marker_menu (bool start_or_end)
{
using namespace Menu_Helpers;
- marker_menu = new Menu;
- MenuList& items = marker_menu->items();
- marker_menu->set_name ("ArdourContextMenu");
+ Menu *markerMenu = new Menu;
+ if (start_or_end) {
+ start_end_marker_menu = markerMenu;
+ } else {
+ marker_menu = markerMenu;
+ }
+ MenuList& items = markerMenu->items();
+ markerMenu->set_name ("ArdourContextMenu");
items.push_back (MenuElem (_("Locate to Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
items.push_back (MenuElem (_("Play from Mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Rename Mark"), mem_fun(*this, &Editor::marker_menu_rename)));
items.push_back (MenuElem (_("Hide Mark"), mem_fun(*this, &Editor::marker_menu_hide)));
+ if (start_or_end) return;
+ items.push_back (MenuElem (_("Rename Mark"), mem_fun(*this, &Editor::marker_menu_rename)));
items.push_back (MenuElem (_("Remove Mark"), mem_fun(*this, &Editor::marker_menu_remove)));
}
void
-Editor::build_range_marker_menu ()
+Editor::build_range_marker_menu (bool loop_or_punch)
{
using namespace Menu_Helpers;
- range_marker_menu = new Menu;
- MenuList& items = range_marker_menu->items();
- range_marker_menu->set_name ("ArdourContextMenu");
+ Menu *markerMenu = new Menu;
+ if (loop_or_punch) {
+ transport_marker_menu = markerMenu;
+ } else {
+ range_marker_menu = markerMenu;
+ }
+ MenuList& items = markerMenu->items();
+ markerMenu->set_name ("ArdourContextMenu");
items.push_back (MenuElem (_("Locate to Range Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
items.push_back (MenuElem (_("Play from Range Mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
- items.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range)));
- items.push_back (MenuElem (_("Loop Range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
+ if (! loop_or_punch) {
+ items.push_back (MenuElem (_("Play Range"), mem_fun(*this, &Editor::marker_menu_play_range)));
+ items.push_back (MenuElem (_("Loop Range"), mem_fun(*this, &Editor::marker_menu_loop_range)));
+ }
items.push_back (MenuElem (_("Set Range Mark from Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
items.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename)));
items.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide)));
- items.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove)));
+ if (! loop_or_punch) {
+ items.push_back (MenuElem (_("Rename Range"), mem_fun(*this, &Editor::marker_menu_rename)));
+ items.push_back (MenuElem (_("Remove Range"), mem_fun(*this, &Editor::marker_menu_remove)));
+ }
items.push_back (SeparatorElem());
new_transport_marker_menu->signal_unmap_event().connect ( mem_fun(*this, &Editor::new_transport_marker_menu_popdown));
}
-void
-Editor::build_transport_marker_menu ()
-{
- using namespace Menu_Helpers;
-
- transport_marker_menu = new Menu;
- MenuList& items = transport_marker_menu->items();
- transport_marker_menu->set_name ("ArdourContextMenu");
-
- items.push_back (MenuElem (_("Locate to Range Mark"), mem_fun(*this, &Editor::marker_menu_set_playhead)));
- items.push_back (MenuElem (_("Play from Range Mark"), mem_fun(*this, &Editor::marker_menu_play_from)));
- items.push_back (MenuElem (_("Set Range Mark from Playhead"), mem_fun(*this, &Editor::marker_menu_set_from_playhead)));
- items.push_back (MenuElem (_("Set Range from Range Selection"), mem_fun(*this, &Editor::marker_menu_set_from_selection)));
- items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Hide Range"), mem_fun(*this, &Editor::marker_menu_hide)));
- items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Separate Regions in Range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
- items.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
-}
-
void
Editor::marker_menu_hide ()
{
Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
{
Location * newloc = 0;
+ string rangename;
if (!drag_info.first_move) {
drag_range_markerbar_op (item, event);
{
begin_reversible_command (_("new range marker"));
XMLNode &before = session->locations()->get_state();
- newloc = new Location(temp_location->start(), temp_location->end(), "unnamed", Location::IsRangeMarker);
+ session->locations()->next_available_name(rangename,"unnamed");
+ newloc = new Location(temp_location->start(), temp_location->end(), rangename, Location::IsRangeMarker);
session->locations()->add (newloc, true);
XMLNode &after = session->locations()->get_state();
session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
void
Editor::add_location_from_selection ()
{
+ string rangename;
+
if (selection->time.empty()) {
return;
}
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
- Location *location = new Location (start, end, "selection", Location::IsRangeMarker);
+ session->locations()->next_available_name(rangename,"selection");
+ Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
void
Editor::add_location_from_playhead_cursor ()
{
+ string markername;
+
nframes_t where = session->audible_frame();
- Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->locations()->next_available_name(markername,"mark");
+ Location *location = new Location (where, where, markername, Location::IsMark);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
nframes_t pos;
float prefix;
bool was_floating;
+ string markername;
if (get_prefix (prefix, was_floating)) {
pos = session->audible_frame ();
}
}
- session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
+ session->locations()->next_available_name(markername,"mark");
+ session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
}
void
session->locations()->clear ();
}
+void
+Editor::unhide_markers ()
+{
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ Location *l = (*i).first;
+ if (l->is_hidden() && l->is_mark()) {
+ l->set_hidden(false, this);
+ }
+ }
+}
+
+void
+Editor::unhide_ranges ()
+{
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ Location *l = (*i).first;
+ if (l->is_hidden() && l->is_range_marker()) {
+ l->set_hidden(false, this);
+ }
+ }
+}
+
/* INSERT/REPLACE */
void
case MarkerBarItem:
ruler_items.push_back (MenuElem (_("New location marker"), bind ( mem_fun(*this, &Editor::mouse_add_new_marker), where)));
ruler_items.push_back (MenuElem (_("Clear all locations"), mem_fun(*this, &Editor::clear_markers)));
+ ruler_items.push_back (MenuElem (_("Unhide locations"), mem_fun(*this, &Editor::unhide_markers)));
ruler_items.push_back (SeparatorElem ());
break;
case RangeMarkerBarItem:
//ruler_items.push_back (MenuElem (_("New Range")));
ruler_items.push_back (MenuElem (_("Clear all ranges"), mem_fun(*this, &Editor::clear_ranges)));
+ ruler_items.push_back (MenuElem (_("Unhide ranges"), mem_fun(*this, &Editor::unhide_ranges)));
ruler_items.push_back (SeparatorElem ());
break;
item_table (1, 7, false),
start_set_button (_("Set")),
start_go_button (_("Go")),
- start_clock (X_("LocationEditRowClock"), true),
+ start_clock (X_("locationstart"), true, X_("LocationEditRowClock"), true),
end_set_button (_("Set")),
end_go_button (_("Go")),
- end_clock (X_("LocationEditRowClock"), true),
- length_clock (X_("LocationEditRowClock"), true, true),
+ end_clock (X_("locationend"), true, X_("LocationEditRowClock"), true),
+ length_clock (X_("locationlength"), true, X_("LocationEditRowClock"), true, true),
cd_check_button (_("CD")),
hide_check_button (_("Hidden")),
remove_button (_("Remove")),
}
hide_check_button.set_active (location->is_hidden());
- if (location->is_auto_loop() || location->is_auto_punch()) {
+ if (location->is_auto_loop() || location-> is_auto_punch()) {
// use label instead of entry
name_label.set_text (location->name());
void
LocationUI::add_new_location()
{
+ string markername;
+
if (session) {
nframes_t where = session->audible_frame();
- Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->locations()->next_available_name(markername,"mark");
+ Location *location = new Location (where, where, markername, Location::IsMark);
session->begin_reversible_command (_("add marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
void
LocationUI::add_new_range()
{
+ string rangename;
+
if (session) {
nframes_t where = session->audible_frame();
- Location *location = new Location (where, where, "unnamed",
- Location::IsRangeMarker);
+ session->locations()->next_available_name(rangename,"unnamed");
+ Location *location = new Location (where, where, rangename, Location::IsRangeMarker);
session->begin_reversible_command (_("add range marker"));
XMLNode &before = session->locations()->get_state();
session->locations()->add (location, true);
/* Loading a session, but the session doesn't exist */
if (isnew) {
- error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
-To create it from the command line, start ardour as \"ardour --new %1"), path) << endmsg;
+ error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
+ "To create it from the command line, start ardour as \"ardour --new %1"), path)
+ << endmsg;
return false;
}
ARDOUR::AudioEngine *engine;
vector<Glib::ustring> null_file_list;
+ Glib::thread_init();
gtk_set_locale ();
- (void) bindtextdomain (PACKAGE, LOCALEDIR);
+ (void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
- // catch_signals ();
+ // catch error message system signals ();
text_receiver.listen_to (error);
text_receiver.listen_to (info);
<< endl;
}
- // needs a better home.
- Glib::thread_init();
-
try {
ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
} catch (failed_constructor& err) {
/* Sync */
- smpte_offset_clock (X_("SMPTEOffsetClock"), true, true),
+ smpte_offset_clock (X_("smpteoffset"), false, X_("SMPTEOffsetClock"), true, true),
smpte_offset_negative_button (_("SMPTE offset is negative")),
/* MIDI */
Location* end_location() const;
Location* start_location() const;
+ int next_available_name(string& result,string base);
uint32_t num_range_markers() const;
int set_current (Location *, bool want_lock = true);
void set_auto_punch_location (Location *);
void set_auto_loop_location (Location *);
+ int location_name(string& result, string base = string(""));
void reset_input_monitor_state ();
#include "i18n.h"
+#define SUFFIX_MAX 32
+
using namespace std;
using namespace ARDOUR;
using namespace sigc;
return ret;
}
+int
+Locations::next_available_name(string& result,string base)
+{
+ LocationList::iterator i;
+ Location* location;
+ string temp;
+ string::size_type l;
+ int suffix;
+ char buf[32];
+ bool available[SUFFIX_MAX+1];
+
+ result = base;
+ for (int k=1; k<SUFFIX_MAX; k++) {
+ available[k] = true;
+ }
+ l = base.length();
+ for (i = locations.begin(); i != locations.end(); ++i) {
+ location =* i;
+ temp = location->name();
+ if (l && !temp.find(base,0)) {
+ suffix = atoi(temp.substr(l,3));
+ if (suffix) available[suffix] = false;
+ }
+ }
+ for (int k=1; k<=SUFFIX_MAX; k++) {
+ if (available[k]) {
+ snprintf (buf, 31, "%d", k);
+ result += buf;
+ return 1;
+ }
+ }
+ return 0;
+}
+
int
Locations::set_current_unlocked (Location *loc)
{