AddRouteDialog::refill_track_modes ()
{
vector<string> s;
-
+
s.push_back (_("Normal"));
if (!ARDOUR::Profile->get_sae ()) {
ret.set (DataType::MIDI, 1);
break;
}
-
+
return ret;
}
bool name_template_is_default () const;
std::string track_template ();
ARDOUR::PluginInfoPtr requested_instrument ();
-
+
ARDOUR::TrackMode mode();
ARDOUR::RouteGroup* route_group ();
enum InsertAt {
/* The inactive color for the LED is just a fairly dark version of the
* active color.
*/
-
+
ArdourCanvas::HSV inactive (led_active_color);
inactive.v = 0.35;
void set_layout_ellipsize_width (int w);
void set_layout_font (const Pango::FontDescription&);
void set_text_ellipsize (Pango::EllipsizeMode);
-
+
sigc::signal<void> signal_led_clicked;
sigc::signal<void> signal_clicked;
bool
ArdourDisplay::on_button_press_event (GdkEventButton*)
{
- _menu.popup (1, gtk_get_current_event_time());
+ _menu.popup (1, gtk_get_current_event_time());
return true;
}
boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable();
if (c) {
float val = c->get_interface();
-
+
if ( ev->direction == GDK_SCROLL_UP )
val += 0.05 * scale; //by default, we step in 1/20ths of the knob travel
else
val -= 0.05 * scale;
-
+
c->set_interface(val);
}
using namespace Menu_Helpers;
MenuList& items = _menu.items ();
-
+
items.push_back (e);
}
ArdourKnob::render (cairo_t* cr, cairo_rectangle_t *)
{
cairo_pattern_t* shade_pattern;
-
+
float width = get_width();
float height = get_height();
-
+
const float scale = min(width, height);
const float pointer_thickness = 3.0 * (scale/80); //(if the knob is 80 pixels wide, we want a 3-pix line on it)
-
+
const float start_angle = ((180 - 65) * G_PI) / 180;
const float end_angle = ((360 + 65) * G_PI) / 180;
const float value_angle = start_angle + (_val * (end_angle - start_angle));
const float zero_angle = start_angle + (zero * (end_angle - start_angle));
-
+
float value_x = cos (value_angle);
float value_y = sin (value_angle);
float xc = 0.5 + width/ 2.0;
float yc = 0.5 + height/ 2.0;
-
+
cairo_translate (cr, xc, yc); //after this, everything is based on the center of the knob
//get the knob color from the theme
float center_radius = 0.48*scale;
float border_width = 0.8;
-
+
bool arc = (_elements & Arc)==Arc;
bool bevel = (_elements & Bevel)==Bevel;
bool flat = _flat_buttons;
-
+
if ( arc ) {
center_radius = scale*0.33;
float outer_progress_radius = scale*0.48;
float progress_width = (outer_progress_radius-inner_progress_radius);
float progress_radius = inner_progress_radius + progress_width/2.0;
-
+
//dark arc background
cairo_set_source_rgb (cr, 0.3, 0.3, 0.3 );
cairo_set_line_width (cr, progress_width);
cairo_stroke (cr);
#endif
}
-
+
if (!flat) {
//knob shadow
cairo_save(cr);
ArdourCanvas::set_source_rgba(cr, knob_color);
cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI);
cairo_fill (cr);
-
- //gradient
+
+ //gradient
if (bevel) {
//knob gradient
shade_pattern = cairo_pattern_create_linear (0.0, -yc, 0.0, yc); //note we have to offset the gradient from our centerpoint
ArdourCanvas::set_source_rgb_a (cr, knob_color, 0.5 );
cairo_arc (cr, 0, 0, center_radius-pointer_thickness, 0, 2.0*G_PI);
cairo_fill (cr);
- } else {
+ } else {
//radial gradient
shade_pattern = cairo_pattern_create_radial ( -center_radius, -center_radius, 1, -center_radius, -center_radius, center_radius*2.5 ); //note we have to offset the gradient from our centerpoint
cairo_pattern_add_color_stop_rgba (shade_pattern, 0.0, 1,1,1, 0.2);
cairo_fill (cr);
cairo_pattern_destroy (shade_pattern);
}
-
+
} else {
//inner circle
ArdourCanvas::set_source_rgba(cr, knob_color);
cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI);
cairo_fill (cr);
}
-
+
//black knob border
cairo_set_line_width (cr, border_width);
cairo_set_source_rgba (cr, 0,0,0, 1 );
cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI);
cairo_stroke (cr);
-
+
//line shadow
if (!flat) {
cairo_save(cr);
cairo_stroke (cr);
cairo_restore(cr);
}
-
+
//line
cairo_set_source_rgba (cr, 1,1,1, 1 );
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_arc (cr, 0, 0, center_radius, 0, 2.0*G_PI);
cairo_fill (cr);
}
-
- cairo_identity_matrix(cr);
+
+ cairo_identity_matrix(cr);
}
void
boost::shared_ptr<PBD::Controllable> c = binding_proxy.get_controllable();
if (c) {
float val = c->get_interface();
-
+
if ( ev->direction == GDK_SCROLL_UP )
val += scale;
else
- val -= scale;
+ val -= scale;
c->set_interface(val);
}
if (ev->button != 1 && ev->button != 2) {
return false;
}
-
+
set_active_state (Gtkmm2ext::ExplicitActive);
_tooltip.start_drag();
add_modal_grab();
if (_active_state != s)
CairoWidget::set_active_state (s);
}
-
+
void
ArdourKnob::set_visual_state (Gtkmm2ext::VisualState s)
{
if (_visual_state != s)
CairoWidget::set_visual_state (s);
}
-
+
bool
ArdourKnob::on_focus_in_event (GdkEventFocus* ev)
float _val; // current value [0..1]
float _normal; // default value, arc
float _dead_zone_delta;
-
+
Flags _flags;
void action_sensitivity_changed ();
xmlSetGenericErrorFunc (this, libxml_generic_error_func);
xmlSetStructuredErrorFunc (this, libxml_structured_error_func);
-
+
UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
UIConfiguration::instance().map_parameters (pc);
/* Trigger setting up the color scheme and loading the GTK RC file */
UIConfiguration::instance().load_rc_file (false);
-
+
_process_thread = new ProcessThread ();
_process_thread->init ();
ARDOUR::Session* the_session() { return _session; }
bool get_smart_mode () const;
-
+
int get_session_parameters (bool quit_on_cancel, bool should_be_new = false, std::string load_template = "");
int build_session_from_dialog (SessionDialog&, const std::string& session_name, const std::string& session_path);
bool ask_about_loading_existing_session (const std::string& session_path);
void save_state (const std::string & state_name = "", bool switch_to_it = false);
static ARDOUR_UI *instance () { return theArdourUI; }
-
+
PublicEditor& the_editor() { return *editor;}
Mixer_UI* the_mixer() { return mixer; }
void create_xrun_marker (framepos_t);
GUIObjectState* gui_object_state;
-
+
MainClock* primary_clock;
MainClock* secondary_clock;
void focus_on_clock ();
void audition_blink (bool);
void feedback_blink (bool);
void error_blink (bool);
-
+
void set_flat_buttons();
void soloing_changed (bool);
void auditioning_changed (bool);
void _auditioning_changed (bool);
-
+
bool solo_alert_press (GdkEventButton* ev);
bool audition_alert_press (GdkEventButton* ev);
bool feedback_alert_press (GdkEventButton *);
Gtk::Label format_label;
void update_format ();
-
+
void every_second ();
void every_point_one_seconds ();
void every_point_zero_something_seconds ();
shuttle_box = manage (new ShuttleControl);
shuttle_box->show ();
-
+
VBox* transport_vbox = manage (new VBox);
transport_vbox->set_name ("TransportBase");
transport_vbox->set_border_width (0);
UIConfiguration::instance().set_follow_edits (tact->get_active ());
}
-
+
{
Glib::RefPtr<Gdk::Window> win;
Glib::RefPtr<Gdk::Screen> screen;
-
+
if (editor) {
win = editor->get_window ();
}
} else {
screen = Gdk::Screen::get_default();
}
-
+
if (g_getenv ("ARDOUR_LOVES_STUPID_TINY_SCREENS") == 0 && screen && screen->get_height() < 700) {
Gtk::MessageDialog msg (_("This screen is not tall enough to display the mixer window"));
msg.run ();
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
-
+
act = ActionManager::register_action (main_actions, X_("OpenVideo"), _("Open Video"),
sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::add_video), (Gtk::Window*) 0));
ActionManager::session_sensitive_actions.push_back (act);
if (parent) {
set_transient_for (*parent);
}
-
+
ARDOUR_UI::CloseAllDialogs.connect (sigc::mem_fun (*this, &ArdourWindow::hide));
proxy = new WM::ProxyTemporary (get_title(), this);
Gtk::Requisition req;
CairoWidget::on_realize ();
-
+
set_clock_dimensions (req);
first_width = req.width;
cairo_save (cr);
cairo_scale (cr, xscale, yscale);
}
-
+
pango_cairo_show_layout (cr, _layout->gobj());
if (xscale != 1.0 || yscale != 1.0) {
Glib::RefPtr<Gtk::Style> style = get_style ();
Pango::FontDescription font;
int w;
-
+
tmp = Pango::Layout::create (get_pango_context());
-
+
if (!is_realized()) {
font = get_font_for_style (get_name());
} else {
font = style->get_font();
}
-
+
tmp->set_font_description (font);
font.set_size (INFO_FONT_SIZE);
edit_string.clear ();
_layout->set_text ("");
}
-
+
input_string.clear ();
editing = true;
edit_is_negative = false;
-
+
if (f) {
input_string = get_field (f);
show_edit_status (merge_input_and_edit_string ());
_layout->set_text (edit_string);
}
-
+
queue_draw ();
Keyboard::magic_widget_grab_focus ();
* to font distortion.
*/
void set_scale (double x, double y);
-
+
static void print_minsec (framepos_t, char* buf, size_t bufsize, float frame_rate);
sigc::signal<void> ValueChanged;
ARDOUR::framecnt_t parse_as_minsec_distance (const std::string&);
ARDOUR::framecnt_t parse_as_bbt_distance (const std::string&);
ARDOUR::framecnt_t parse_as_frames_distance (const std::string&);
-
+
void set_font (Pango::FontDescription);
void set_colors ();
void show_edit_status (int length);
if (!Profile->get_sae()) {
gain_line.reset (new AudioRegionGainLine (line_name, *this, *group, audio_region()->envelope()));
}
-
+
update_envelope_visibility ();
gain_line->reset ();
if (end_xfade_rect) {
if (audio_region()->fade_out_active()) {
end_xfade_rect->set_fill (false);
- } else {
+ } else {
end_xfade_rect->set_fill_color (UIConfiguration::instance().color_mod ("inactive crossfade", "inactive crossfade"));
end_xfade_rect->set_fill (true);
}
interesting_stuff.add (ARDOUR::Properties::length);
if (what_changed.contains (interesting_stuff)) {
-
+
for (uint32_t n = 0; n < waves.size(); ++n) {
waves[n]->region_resized ();
}
if (wcnt > 0) {
gdouble ht;
-
+
if (!UIConfiguration::instance().get_show_name_highlight() || (height < NAME_HIGHLIGHT_THRESH)) {
ht = height / (double) wcnt;
} else {
ht = (height - NAME_HIGHLIGHT_SIZE) / (double) wcnt;
}
-
+
for (uint32_t n = 0; n < wcnt; ++n) {
-
+
gdouble yoff = floor (ht * n);
-
+
waves[n]->set_height (ht);
waves[n]->set_y_position (yoff);
}
hide_start_xfade ();
return;
}
-
+
double effective_height;
if (_height >= NAME_HIGHLIGHT_THRESH) {
double const pwidth = floor(trackview.editor().sample_to_pixel (width));
-
+
/* the right edge should be right on the region frame is the pixel
* width is zero. Hence the additional + 1.0 at the end.
*/
}
/* points *MUST* be in anti-clockwise order */
-
+
Points points;
Points::size_type pi;
boost::shared_ptr<const Evoral::ControlList> list (audio_region()->fade_out());
double length = list->length();
points.assign (list->size(), Duple());
-
+
for (x = list->begin(), pi = 0; x != list->end(); ++x, ++pi) {
points[pi].x = _pixel_width - pwidth + (pwidth * ((*x)->when/length));
points[pi].y = effective_height - ((*x)->value * (effective_height - 1.));
npoints = inverse->size();
ipoints.assign (npoints, Duple());
-
+
Evoral::ControlList::const_iterator x;
Points::size_type pi;
double length = inverse->length();
}
show_end_xfade();
-
+
reset_fade_out_shape_width (ar, ar->fade_out()->back()->when);
}
npoints = inverse->size();
ipoints.assign (npoints, Duple());
-
+
const double rend = trackview.editor().sample_to_pixel (_region->length() - width);
-
+
Evoral::ControlList::const_iterator x;
Points::size_type pi;
double length = inverse->length();
/* first waveview starts at 1.0, not 0.0 since that will overlap the
* frame
*/
-
+
gdouble yoff = which * ht;
WaveView *wave = new WaveView (group, audio_region ());
CANVAS_DEBUG_NAME (wave, string_compose ("wave view for chn %1 of %2", which, get_item_name()));
-
+
wave->set_channel (which);
wave->set_y_position (yoff);
wave->set_height (ht);
wave->set_show_zero_line (true);
wave->set_clip_level (UIConfiguration::instance().get_waveform_clip_level ());
wave->set_start_shift (1.0);
-
+
wave->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_wave_view_event), wave, this));
-
+
switch (UIConfiguration::instance().get_waveform_shape()) {
case Rectified:
wave->set_shape (WaveView::Rectified);
default:
wave->set_shape (WaveView::Normal);
}
-
+
wave->set_logscaled (UIConfiguration::instance().get_waveform_scale() == Logarithmic);
vector<ArdourCanvas::WaveView*> v;
} else {
if (_region->muted()) {
/* hide outline with zero alpha */
- outline = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("waveform outline"), 0);
+ outline = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("waveform outline"), 0);
fill = UINT_RGBA_CHANGE_A(UIConfiguration::instance().color ("waveform fill"), MUTED_ALPHA);
} else {
outline = UIConfiguration::instance().color ("waveform outline");
void redraw_end_xfade_to (boost::shared_ptr<ARDOUR::AudioRegion>, framecnt_t, ArdourCanvas::Points&, double, double, double);
void redraw_start_xfade ();
void redraw_end_xfade ();
-
+
void hide_xfades ();
void hide_start_xfade ();
void hide_end_xfade ();
{
list<AudioRegionView*> start_hidden;
list<AudioRegionView*> end_hidden;
-
+
for (list<RegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
AutomationTracks::iterator existing = _automation_tracks.find (param);
if (existing != _automation_tracks.end()) {
-
+
/* automation track created because we had existing data for
* the processor, but visibility may need to be controlled
* since it will have been set visible by default.
*/
existing->second->set_marked_for_display (show);
-
+
if (!no_redraw) {
request_redraw ();
}
} else if (param.type() == MuteAutomation) {
create_mute_automation_child (param, show);
-
+
} else {
error << "AudioTimeAxisView: unknown automation child " << EventTypeMap::instance().to_symbol(param) << endmsg;
} else {
_our_time_converter = true;
}
-
+
_visible = Line;
update_pending = false;
/* leave control points setting unchanged, we are just hiding the
overall line
*/
-
+
set_visibility (AutomationLine::VisibleAspects (_visible & ~Line));
}
/* get the maximum distance we can move any of these points along the x-axis
*/
-
+
double tx; /* possible position a point would move to, given dx */
ControlPoint* cp;
-
+
if (dx > 0) {
/* check the last point, since we're moving later in time */
cp = back();
no motion ever took place, but need to do before we handle
motion.
*/
-
+
/* partition the points we are dragging into (potentially several)
* set(s) of contiguous points. this will not happen with a normal
* drag, but if the user does a discontiguous selection, it can.
*/
-
+
uint32_t expected_view_index = 0;
CCP contig;
-
+
for (list<ControlPoint*>::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) {
if (i == _drag_points.begin() || (*i)->view_index() != expected_view_index) {
contig.reset (new ContiguousControlPoints (*this));
(*ccp)->compute_x_bounds (trackview.editor());
}
_drag_had_movement = true;
- }
+ }
/* OK, now on to the stuff related to *this* motion event. First, for
* each contiguous range, figure out the maximum x-axis motion we are
}
/* clamp y */
-
+
for (list<ControlPoint*>::iterator i = _drag_points.begin(); i != _drag_points.end(); ++i) {
double const y = ((_height - (*i)->get_y()) / _height) + dy;
if (y < 0) {
if (dx || dy) {
/* and now move each section */
-
+
for (vector<CCP>::iterator ccp = contiguous_points.begin(); ccp != contiguous_points.end(); ++ccp) {
(*ccp)->move (dx, dy);
}
line->set_steps (line_points, is_stepped());
}
}
-
+
_drag_distance += dx;
_drag_x += dx;
_last_drag_fraction = fraction;
XMLNode &before = alist->get_state();
alist->erase (cp.model());
-
+
trackview.editor().session()->add_command(
new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()));
/* model_when is relative to the start of the source, so we just need to add on the origin_b here
(as it is the session frame position of the start of the source)
*/
-
+
framepos_t const session_frames_when = _time_converter->to (model_when) + _time_converter->origin_b ();
if (session_frames_when >= start && session_frames_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) {
np = events.size();
Evoral::ControlList& e = const_cast<Evoral::ControlList&> (events);
-
+
for (AutomationList::iterator ai = e.begin(); ai != e.end(); ++ai, ++pi) {
double tx = (*ai)->when;
_name) << endmsg;
continue;
}
-
+
if (tx >= max_framepos || tx < 0 || tx >= _maximum_time) {
continue;
}
-
+
/* convert x-coordinate to a canvas unit coordinate (this takes
* zoom and scroll into account).
*/
-
+
tx = trackview.editor().sample_to_pixel_unrounded (tx);
-
+
/* convert from canonical view height (0..1.0) to actual
* height coordinates (using X11's top-left rooted system)
*/
ControlPoints = 0x2,
SelectedControlPoints = 0x4
};
-
+
AutomationLine (const std::string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
}
tipname += nom;
_name = tipname;
-
+
CANVAS_DEBUG_NAME (_canvas_display, string_compose ("main for auto %2/%1", _name, r->name()));
CANVAS_DEBUG_NAME (selection_group, string_compose ("selections for auto %2/%1", _name, r->name()));
CANVAS_DEBUG_NAME (_ghost_group, string_compose ("ghosts for auto %2/%1", _name, r->name()));
if (name_label.get_parent()) {
name_label.get_parent()->remove (name_label);
}
-
+
name_label.set_text (_name);
name_label.set_alignment (Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
name_label.set_name (X_("TrackParameterName"));
}
boost::shared_ptr<AutomationList> list = _line->the_list ();
-
+
if (list->in_write_pass()) {
/* do not allow the GUI to add automation events during an
automation write pass.
{
if (_control && line) {
assert(line->the_list() == _control->list());
-
+
_control->alist()->automation_state_changed.connect (
_list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::automation_state_changed, this), gui_context()
);
-
+
_control->alist()->InterpolationChanged.connect (
_list_connections, invalidator (*this), boost::bind (&AutomationTimeAxisView::interpolation_changed, this, _1), gui_context()
);
assert (automatable);
Automatable::Controls& controls (automatable->controls());
-
+
for (Automatable::Controls::iterator i = controls.begin(); i != controls.end(); ++i) {
-
+
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
if (ac && ac->alist()) {
-
+
const XMLNode* gui_node = ac->extra_xml ("GUI");
-
+
if (gui_node) {
const XMLProperty* prop = gui_node->property ("shown");
if (prop) {
virtual std::string name() const = 0;
sigc::signal<void> Hiding;
-
+
void set_old_order_key (uint32_t ok) { _old_order_key = ok; }
uint32_t old_order_key() const { return _old_order_key; }
/* for now, we always return properties in string form.
*/
std::string gui_property (const std::string& property_name) const;
-
+
template<typename T> void set_gui_property (const std::string& property_name, const T& value) {
std::stringstream s;
s << value;
static GUIObjectState& gui_object_state();
void clear_property_cache() { property_hashtable.clear(); }
-
+
protected:
AxisView (ARDOUR::Session* sess);
{
public:
BigClockWindow (AudioClock&);
-
+
private:
AudioClock& clock;
Gtk::Requisition default_size;
-
+
void clock_size_reallocated (Gtk::Allocation&);
void on_realize ();
void on_unmap ();
localedir = "/this/cannot/exist";
} else {
/* force localedir into the bundle */
-
+
vector<string> lpath;
lpath.push_back (bundle_dir);
lpath.push_back ("Resources");
localedir = Glib::build_filename (lpath).c_str();
}
#endif
-
+
export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
/* inside an OS X .app bundle, there is no difference
if (0 == pExeRoot) {
pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0);
}
-
+
if (pExeRoot) {
gchar tmp[PATH_MAX+1];
gchar* p;
#ifdef DEBUG
fonts_conf_file = get_module_folder();
-
+
if (!fonts_conf_file.empty()) {
fonts_conf_file += "\\";
fonts_conf_file += PROGRAM_NAME;
#if defined(DEBUG) || defined(RDC_BUILD)
// Make sure we pick up the debuggable DLLs !!!
pango_modules_file = get_module_folder();
-
+
if (!pango_modules_file.empty()) {
pango_modules_file += "\\";
pango_modules_file += PROGRAM_NAME;
#if defined(DEBUG) || defined(RDC_BUILD)
// Make sure we pick up the debuggable DLLs !!!
gdk_pixbuf_loaders_file = get_module_folder();
-
+
if (!gdk_pixbuf_loaders_file.empty()) {
gdk_pixbuf_loaders_file += "\\";
gdk_pixbuf_loaders_file += PROGRAM_NAME;
#if defined(DEBUG) || defined(RDC_BUILD)
// Make sure we pick up the debuggable DLLs !!!
clearlooks_la_file = get_module_folder();
-
+
if (!clearlooks_la_file.empty()) {
clearlooks_la_file += "\\";
clearlooks_la_file += PROGRAM_NAME;
border_color = UIConfiguration::instance().color (string_compose ("%1: border end", name));
UINT_TO_RGBA (border_color, &r, &g, &b, &a);
-
+
border_r = r/255.0;
border_g = g/255.0;
border_b = b/255.0;
ButtonJoiner::render (cairo_t* cr, cairo_rectangle_t*)
{
double h = get_height();
-
+
if (!get_active()) {
cairo_set_source (cr, inactive_fill_pattern);
} else {
if (!central_link) {
/* outer rect */
-
+
Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, get_width(), h, 8);
cairo_fill_preserve (cr);
-
+
/* outer edge */
-
+
cairo_set_line_width (cr, 1.5);
cairo_set_source_rgb (cr, border_r, border_g, border_b);
cairo_stroke (cr);
-
+
/* inner "edge" */
-
+
Gtkmm2ext::rounded_top_rectangle (cr, 8, 8, get_width() - 16, h - 8, 6);
cairo_stroke (cr);
} else {
if (get_active()) {
Gtkmm2ext::rounded_top_rectangle (cr, 0, 0, (get_width() - 20.0)/2.0 , h, 8);
cairo_fill_preserve (cr);
-
+
Gtkmm2ext::rounded_top_rectangle (cr, (get_width() - 20.)/2.0 + 20.0, 0.0,
(get_width() - 20.0)/2.0 , h, 8);
cairo_fill_preserve (cr);
cairo_set_line_width (cr, 1.5);
cairo_fill_preserve (cr);
cairo_set_source_rgb (cr, border_r, border_g, border_b);
- cairo_stroke (cr);
+ cairo_stroke (cr);
}
}
}
} else {
set_visual_state (Gtkmm2ext::VisualState (visual_state() | Gtkmm2ext::Insensitive));
}
-
+
}
void
if (tact) {
set_active (tact->get_active());
}
-}
+}
void
ButtonJoiner::set_active_state (Gtkmm2ext::ActiveState s)
ButtonJoiner (const std::string&, Gtk::Widget&, Gtk::Widget&, bool central_link = false);
~ButtonJoiner ();
- void set_related_action (Glib::RefPtr<Gtk::Action>);
+ void set_related_action (Glib::RefPtr<Gtk::Action>);
void set_active_state (Gtkmm2ext::ActiveState);
protected:
} else {
PAINT_VERTA_GR(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, fill_max, wave_middle, wave_top);
}
-
+
}
if((prev_pymin > pymin && next_pymin > pymin) ||
PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymax, pymax + (clip_length - 1));
}
- if (clip_min) {
+ if (clip_min) {
PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a , x, pymin - clip_length, pymin);
PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x + 1, pymin - (clip_length - 1), pymin);
PAINT_VERTA(buf, waveview->clip_r, waveview->clip_g, waveview->clip_b, waveview->clip_a >> 1, x - 1, pymin - (clip_length - 1), pymin);
ControlPoint::~ControlPoint ()
{
CatchDeletion (this); /* EMIT SIGNAL */
-
+
delete _item;
}
AutomationLine& line() const { return _line; }
static PBD::Signal1<void, ControlPoint *> CatchDeletion;
-
+
private:
ArdourCanvas::Rectangle* _item;
AutomationLine& _line;
_velocity_all.set_sensitive (false);
_time_all.set_sensitive (false);
_length_all.set_sensitive (false);
-
+
int test_channel = (*_events.begin())->note()->channel ();
int test_pitch = (*_events.begin())->note()->note ();
int test_velocity = (*_events.begin())->note()->velocity ();
Evoral::Beats test_time = (*_events.begin())->note()->time ();
Evoral::Beats test_length = (*_events.begin())->note()->length ();
-
+
for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
if ((*i)->note()->channel() != test_channel) {
_channel_all.set_sensitive (true);
_length_all.set_sensitive (true);
}
}
-
+
get_vbox()->pack_start (*table);
add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
X: hard to access
Quartz: impossible to access
-
+
so stop that by preventing it from ever getting too narrow. 35
pixels is basically a rough guess at the tab width.
PublicEditor::_instance = this;
_have_idled = false;
-
+
selection = new Selection (this);
cut_buffer = new Selection (this);
_selection_memento = new SelectionMemento ();
signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
-
+
/* allow external control surfaces/protocols to do various things */
ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
/* handles the (static) signal from the ControlProtocol class that
* requests setting the selected track to a given RID
*/
-
+
if (!_session) {
return;
}
sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
)
);
-
+
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
+
items.push_back (
ImageMenuElem (
_("Constant power"),
*(*images)[FadeConstantPower],
sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
));
-
+
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
+
items.push_back (
ImageMenuElem (
_("Symmetric"),
sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
)
);
-
+
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
+
items.push_back (
ImageMenuElem (
_("Slow"),
*(*images)[FadeSlow],
sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
));
-
+
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
+
items.push_back (
ImageMenuElem (
_("Fast"),
*(*images)[FadeFast],
sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
));
-
+
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
}
case SnapToBeatDiv2: {
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
-
+
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
}
for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-
+
std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
-
+
if (r.first) {
return r;
}
if (!ARDOUR::Profile->get_mixbus()) {
mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
}
-
+
if (!ARDOUR::Profile->get_trx()) {
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
if (!ARDOUR::Profile->get_trx()) {
_zoom_tearoff = manage (new TearOff (_zoom_box));
-
+
_zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
&_zoom_tearoff->tearoff_window()));
_zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
Editor::build_edit_mode_menu ()
{
using namespace Menu_Helpers;
-
+
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
// edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
The user has undone some selection ops and then made a new one,
making anything earlier in the list invalid.
*/
-
+
list<XMLNode *>::iterator it = selection_op_history.begin();
list<XMLNode *>::iterator e_it = it;
advance (e_it, selection_op_history_it);
-
+
for ( ; it != e_it; ++it) {
delete *it;
}
temporal_zoom_session();
return;
}
-
+
ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
}
allocation happens, we will get called again and then we can do the
real work.
*/
-
+
if (_visible_canvas_height <= 1) {
return;
}
int h;
string str;
DisplaySuspender ds;
-
+
if (_visible_track_count > 0) {
h = trackviews_height() / _visible_track_count;
std::ostringstream s;
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
(*i)->set_height (h, TimeAxisView::HeightPerLane);
}
-
+
if (str != visible_tracks_selector.get_text()) {
visible_tracks_selector.set_text (str);
}
ARDOUR::TempoMap::BBTPointList::const_iterator begin;
ARDOUR::TempoMap::BBTPointList::const_iterator end;
-
+
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
draw_measures (begin, end);
}
void
Editor::clear_playlists (TimeAxisView* v)
{
- begin_reversible_command (_("clear playlists"));
+ begin_reversible_command (_("clear playlists"));
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
_session->playlists->get (playlists);
mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
vs->leftmost_frame = leftmost_frame;
vs->zoom_focus = zoom_focus;
- if (with_tracks) {
+ if (with_tracks) {
*vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
}
set_zoom_focus (vs.zoom_focus);
reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
-
+
if (vs.gui_state) {
*ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
-
- for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
(*i)->clear_property_cache();
(*i)->reset_visual_state ();
}
pending_visual_change.idle_handler_id = -1;
pending_visual_change.being_handled = true;
-
+
VisualChange vc = pending_visual_change;
pending_visual_change.pending = (VisualChange::Type) 0;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
-
+
compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
{
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
RouteTimeAxisView* rtav;
-
+
if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
boost::shared_ptr<Playlist> pl;
std::vector<boost::shared_ptr<Region> > results;
boost::shared_ptr<Track> tr;
-
+
if ((tr = rtav->track()) == 0) {
/* bus */
continue;
}
-
+
if ((pl = (tr->playlist())) != 0) {
boost::shared_ptr<Region> r = pl->region_by_id (id);
if (r) {
mtav->get_per_region_note_selection (selection);
}
}
-
+
}
void
Editor::first_idle ()
{
MessageDialog* dialog = 0;
-
+
if (track_views.size() > 1) {
dialog = new MessageDialog (
*this,
} else {
framepos_t l = 0;
-
+
if (frame < leftmost_frame) {
/* moving left */
if (_session->transport_rolling()) {
if (l < 0) {
l = 0;
}
-
+
center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
}
}
clear_marker_display ();
stop_step_editing ();
-
+
/* get rid of any existing editor mixer strip */
WindowTitle title(Glib::get_application_name());
_fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
_fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
_fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
-
+
_xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
_xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
_xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
{
using namespace Menu_Helpers;
-
+
MenuList& items = _control_point_context_menu.items ();
items.clear ();
-
+
items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
if (!can_remove_control_point (item)) {
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
void remove_tracks ();
-
+
/* tempo */
void set_show_measures (bool yn);
void scroll_tracks_down_line ();
void scroll_tracks_up_line ();
-
+
bool scroll_up_one_track (bool skip_child_views = false);
bool scroll_down_one_track (bool skip_child_views = false);
TimeAxisView* stepping_axis_view () {
return _stepping_axis_view;
}
-
+
void set_stepping_axis_view (TimeAxisView* v) {
_stepping_axis_view = v;
}
void split_regions_at (framepos_t, RegionSelection&);
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
RegionSelection get_regions_from_selection_and_mouse (framepos_t);
-
+
void mouse_add_new_tempo_event (framepos_t where);
void mouse_add_new_meter_event (framepos_t where);
void edit_tempo_section (ARDOUR::TempoSection*);
void mapped_use_new_playlist (RouteTimeAxisView&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_use_copy_playlist (RouteTimeAxisView&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_clear_playlist (RouteTimeAxisView&, uint32_t);
-
+
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
bool button_release_can_deselect;
bool _mouse_changed_selection;
QuantizeDialog* quantize_dialog;
MainMenuDisabler* _main_menu_disabler;
-
+
friend class Drag;
friend class RegionDrag;
friend class RegionMoveDrag;
Glib::RefPtr<ActionGroup> mouse_mode_actions = ActionGroup::create (X_("MouseMode"));
RadioAction::Group mouse_mode_group;
- act = ActionManager::register_toggle_action (mouse_mode_actions, "set-mouse-mode-object-range", _("Smart Object Mode"), sigc::mem_fun (*this, &Editor::mouse_mode_object_range_toggled));
+ act = ActionManager::register_toggle_action (mouse_mode_actions, "set-mouse-mode-object-range", _("Smart Object Mode"), sigc::mem_fun (*this, &Editor::mouse_mode_object_range_toggled));
smart_mode_action = Glib::RefPtr<ToggleAction>::cast_static (act);
smart_mode_button.set_related_action (smart_mode_action);
smart_mode_button.set_text (_("Smart"));
mouse_move_button.set_icon (Gtkmm2ext::ArdourIcon::ToolGrab);
mouse_move_button.set_name ("mouse mode button");
- act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-range", _("Range Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
+ act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-range", _("Range Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
mouse_select_button.set_related_action (act);
mouse_select_button.set_icon (Gtkmm2ext::ArdourIcon::ToolRange);
mouse_select_button.set_name ("mouse mode button");
- act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-draw", _("Note Drawing Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseDraw));
+ act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-draw", _("Note Drawing Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseDraw));
mouse_draw_button.set_related_action (act);
mouse_draw_button.set_icon (Gtkmm2ext::ArdourIcon::ToolDraw);
mouse_draw_button.set_name ("mouse mode button");
- act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-audition", _("Audition Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
+ act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-audition", _("Audition Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
mouse_audition_button.set_related_action (act);
mouse_audition_button.set_icon (Gtkmm2ext::ArdourIcon::ToolAudition);
mouse_audition_button.set_name ("mouse mode button");
- act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Time FX Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
+ act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-timefx", _("Time FX Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
mouse_timefx_button.set_related_action (act);
mouse_timefx_button.set_icon (Gtkmm2ext::ArdourIcon::ToolStretch);
mouse_timefx_button.set_name ("mouse mode button");
- act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-content", _("Content Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseContent));
+ act = ActionManager::register_radio_action (mouse_mode_actions, mouse_mode_group, "set-mouse-mode-content", _("Content Tool"), sigc::bind (sigc::mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseContent));
mouse_content_button.set_related_action (act);
mouse_content_button.set_icon (Gtkmm2ext::ArdourIcon::ToolContent);
mouse_content_button.set_name ("mouse mode button");
mouse_cut_button.set_icon (Gtkmm2ext::ArdourIcon::ToolCut);
mouse_cut_button.set_name ("mouse mode button");
}
-
+
ActionManager::register_action (editor_actions, "step-mouse-mode", _("Step Mouse Mode"), sigc::bind (sigc::mem_fun(*this, &Editor::step_mouse_mode), true));
RadioAction::Group edit_point_group;
/* set defaults here */
no_ruler_shown_update = true;
-
+
if (Profile->get_trx()) {
ruler_marker_action->set_active (true);
ruler_meter_action->set_active (false);
ruler_cd_marker_action->set_active (false);
ruler_timecode_action->set_active (false);
ruler_minsec_action->set_active (true);
- } else {
+ } else {
ruler_marker_action->set_active (true);
ruler_meter_action->set_active (true);
ruler_tempo_action->set_active (true);
Editor::load_bindings ()
{
/* XXX move this to a better place */
-
+
key_bindings.set_action_map (editor_action_map);
std::string binding_file;
Editor::toggle_sound_midi_notes ()
{
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("sound-midi-notes"));
-
+
if (act) {
bool s = UIConfiguration::instance().get_sound_midi_notes();
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
_trackview_group = new ArdourCanvas::Container (hv_scroll_group);
CANVAS_DEBUG_NAME (_trackview_group, "Canvas TrackViews");
-
+
// used as rubberband rect
rubberband_rect = new ArdourCanvas::Rectangle (hv_scroll_group, ArdourCanvas::Rect (0.0, 0.0, 0.0, 0.0));
rubberband_rect->hide();
CANVAS_DEBUG_NAME (_drag_motion_group, "Canvas Drag Motion");
/* TIME BAR CANVAS */
-
+
_time_markers_group = new ArdourCanvas::Container (h_scroll_group);
CANVAS_DEBUG_NAME (_time_markers_group, "time bars");
cd_marker_bar->set_outline_what (ArdourCanvas::Rectangle::BOTTOM);
ARDOUR_UI::instance()->video_timeline = new VideoTimeLine(this, videotl_group, (timebar_height * videotl_bar_height));
-
+
cd_marker_bar_drag_rect = new ArdourCanvas::Rectangle (cd_marker_group, ArdourCanvas::Rect (0.0, 0.0, 100, timebar_height));
CANVAS_DEBUG_NAME (cd_marker_bar_drag_rect, "cd marker drag");
cd_marker_bar_drag_rect->set_outline (false);
Editor::drop_paths_part_two (const vector<string>& paths, framepos_t frame, double ypos, bool copy)
{
RouteTimeAxisView* tv;
-
+
/* MIDI files must always be imported, because we consider them
* writable. So split paths into two vectors, and follow the import
* path on the MIDI part.
frame = 0;
InstrumentSelector is; // instantiation builds instrument-list and sets default.
do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, frame, is.selected_instrument());
-
+
if (Profile->get_sae() || UIConfiguration::instance().get_only_copy_imported_files() || copy) {
do_import (audio_paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, SrcBest, frame);
} else {
if (from_headers) {
alloc = controls_layout.get_allocation ();
- } else {
+ } else {
alloc = _track_canvas_viewport->get_allocation ();
/* reduce height by the height of the timebars, which happens
to correspond to the position of the hv_scroll_group.
*/
-
+
alloc.set_height (alloc.get_height() - hv_scroll_group->position().y);
alloc.set_y (alloc.get_y() + hv_scroll_group->position().y);
/* the effective width of the autoscroll boundary so
that we start scrolling before we hit the edge.
-
+
this helps when the window is slammed up against the
right edge of the screen, making it hard to scroll
effectively.
*/
-
+
if (alloc.get_width() > 20) {
alloc.set_width (alloc.get_width() - 20);
alloc.set_x (alloc.get_x() + 10);
}
}
-
+
scrolling_boundary = ArdourCanvas::Rect (alloc.get_x(), alloc.get_y(), alloc.get_x() + alloc.get_width(), alloc.get_y() + alloc.get_height());
-
+
int x, y;
Gdk::ModifierType mask;
no_stop = true;
} else if (x < autoscroll_boundary.x0) {
-
+
dx = autoscroll_boundary.x0 - x;
dx += 10 + (2 * (autoscroll_cnt/2));
no_stop = true;
}
-
+
if (new_frame != leftmost_frame) {
vc.time_origin = new_frame;
vc.add (VisualChange::TimeOrigin);
}
if (autoscroll_vertical_allowed) {
-
+
// const double vertical_pos = vertical_adjustment.get_value();
const int speed_factor = 10;
/* vertical */
-
+
if (y < autoscroll_boundary.y0) {
/* scroll to make higher tracks visible */
ev.type = GDK_MOTION_NOTIFY;
ev.state = Gdk::BUTTON1_MASK;
-
+
/* the motion handler expects events in canvas coordinate space */
/* we asked for the mouse position above (::get_pointer()) via
ev.y = d.y;
motion_handler (0, (GdkEvent*) &ev, true);
-
+
} else if (no_stop) {
/* not changing visual state but pointer is outside the scrolling boundary
ev.type = GDK_MOTION_NOTIFY;
ev.state = Gdk::BUTTON1_MASK;
-
+
/* the motion handler expects events in canvas coordinate space */
/* first convert from Editor window coordinates to canvas
ev.y = d.y;
motion_handler (0, (GdkEvent*) &ev, true);
-
+
} else {
stop_canvas_autoscroll ();
return false;
autoscroll_cnt++;
return true; /* call me again */
-}
+}
void
Editor::start_canvas_autoscroll (bool allow_horiz, bool allow_vert, const ArdourCanvas::Rect& boundary)
samples_ruler->set_outline_color (text);
bbt_ruler->set_fill_color (base);
bbt_ruler->set_outline_color (text);
-
+
playhead_cursor->set_color (UIConfiguration::instance().color ("play head"));
meter_bar->set_fill_color (UIConfiguration::instance().color_mod ("meter bar", "marker bar"));
}
Trimmable::CanTrim ct = entered_regionview->region()->can_trim ();
-
+
if (left) {
-
+
if (ct & Trimmable::FrontTrimEarlier) {
return _cursors->left_side_trim;
} else {
case MouseCut:
mode_cursor = _cursors->scissors;
break;
-
+
case MouseObject:
case MouseContent:
/* don't use mode cursor, pick a grabber cursor based on the item */
get_pointer_position (x, y);
if (x >= 0 && y >= 0) {
-
+
vector<ArdourCanvas::Item const *> items;
/* Note how we choose a specific scroll group to get
* items from. This could be problematic.
*/
-
+
hv_scroll_group->add_items_at_point (ArdourCanvas::Duple (x,y), items);
-
+
// first item will be the upper most
-
+
if (!items.empty()) {
const ArdourCanvas::Item* i = items.front();
-
+
if (i && i->parent() && i->parent()->get_data (X_("timeselection"))) {
pair<TimeAxisView*, int> tvp = trackview_by_y_position (_last_motion_y);
if (dynamic_cast<AutomationTimeAxisView*> (tvp.first)) {
break;
}
}
-
+
if ((mouse_mode == MouseObject || get_smart_mode ()) ||
mouse_mode == MouseContent) {
}
} else if (mouse_mode == MouseDraw) {
-
+
/* ControlPointItem is not really specific to region gain mode
but it is the same cursor so don't worry about this for now.
The result is that we'll see the fader cursor if we enter
if (Keyboard::some_magic_widget_has_focus()) {
return false;
}
-
+
framepos_t xdelta;
int direction = ev->direction;
}
return ret;
-}
+}
bool
bool handled = false;
if (event->type == GDK_SCROLL) {
-
+
/* scroll events in the rulers are handled a little differently from
scrolling elsewhere in the canvas.
*/
}
handled = true;
break;
-
+
case GDK_SCROLL_DOWN:
if (Profile->get_mixbus()) {
//for mouse-wheel zoom, force zoom-focus to mouse
}
handled = true;
break;
-
+
case GDK_SCROLL_LEFT:
xdelta = (current_page_samples() / 2);
if (leftmost_frame > xdelta) {
}
handled = true;
break;
-
+
case GDK_SCROLL_RIGHT:
xdelta = (current_page_samples() / 2);
if (max_framepos - xdelta > leftmost_frame) {
}
handled = true;
break;
-
+
default:
/* what? */
break;
bool
Editor::canvas_drop_zone_event (GdkEvent* event)
{
- GdkEventScroll scroll;
+ GdkEventScroll scroll;
ArdourCanvas::Duple winpos;
-
+
switch (event->type) {
case GDK_BUTTON_RELEASE:
if (event->button.button == 1) {
std::pair<TimeAxisView*, int> const tv = trackview_by_y_position (py, false);
bool can_drop = false;
-
+
if (tv.first != 0) {
/* over a time axis view of some kind */
rtav = dynamic_cast<RouteTimeAxisView*> (tv.first);
-
+
if (rtav != 0 && rtav->is_track ()) {
/* over a track, not a bus */
can_drop = true;
}
-
+
} else {
/* not over a time axis view, so drop is possible */
if (can_drop) {
region = _regions->get_dragged_region ();
-
+
if (region) {
if (tv.first == 0
context->drag_status (context->get_suggested_action(), time);
return true;
}
-
+
if ((boost::dynamic_pointer_cast<AudioRegion> (region) != 0 &&
dynamic_cast<AudioTimeAxisView*> (tv.first) != 0) ||
(boost::dynamic_pointer_cast<MidiRegion> (region) != 0 &&
dynamic_cast<MidiTimeAxisView*> (tv.first) != 0)) {
-
+
/* audio to audio
OR
midi to midi
*/
-
+
context->drag_status (context->get_suggested_action(), time);
return true;
}
_track_canvas_item->set_y1 (ArdourCanvas::COORD_MAX);
_track_canvas_item->set_x (0);
-
+
_current_frame = 1; /* force redraw at 0 */
}
_track_canvas_item->set_show_head (1, false);
_track_canvas_item->set_y1 (ArdourCanvas::COORD_MAX);
_track_canvas_item->set_ignore_events (true);
-
+
_track_canvas_item->set_x (0);
_current_frame = 1; /* force redraw at 0 */
PBD::Signal1<void, framepos_t> PositionChanged;
- private:
+ private:
Editor& _editor;
ArdourCanvas::Arrow* _track_canvas_item;
framepos_t _current_frame;
s->clear_range_selection ();
}
}
-
+
} else {
/* just a click, no pointer movement.
*/
bool initially_vertical() const {
return _initially_vertical;
}
-
+
/** Set up the _pointer_frame_offset */
virtual void setup_pointer_frame_offset () {
_pointer_frame_offset = 0;
private:
double y_to_region (double) const;
ARDOUR::framecnt_t grid_frames (framepos_t) const;
-
+
MidiRegionView* _region_view;
ArdourCanvas::Rectangle* _drag_rect;
framepos_t _note[2];
private:
Operation _operation;
-
+
bool _preserve_fade_anchor;
bool _jump_position_when_done;
};
* @param drag_in_progress true if the drag is currently happening.
*/
virtual void select_things (int button_state, framepos_t x1, framepos_t x2, double y1, double y2, bool drag_in_progress) = 0;
-
+
virtual void deselect_things () = 0;
protected:
RangeMarkerBarDrag (Editor *, ArdourCanvas::Item *, Operation);
~RangeMarkerBarDrag ();
-
+
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool);
void motion (GdkEvent*, bool);
void finished (GdkEvent*, bool);
void aborted (bool);
-
+
bool y_movement_matters () const {
return false;
}
boost::shared_ptr<Region> r = selection->regions.front()->region();
boost::shared_ptr<AudioRegion> audio_region = boost::dynamic_pointer_cast<AudioRegion>(r);
boost::shared_ptr<MidiRegion> midi_region = boost::dynamic_pointer_cast<MidiRegion>(r);
-
+
if (audio_region) {
-
+
RouteTimeAxisView & rtv (dynamic_cast<RouteTimeAxisView &> (selection->regions.front()->get_time_axis_view()));
AudioTrack & track (dynamic_cast<AudioTrack &> (*rtv.route()));
-
+
ExportRegionDialog dialog (*this, *(audio_region.get()), track);
dialog.set_session (_session);
dialog.run ();
-
+
} else if (midi_region) {
MidiExportDialog dialog (*this, midi_region);
true,
Gtk::MESSAGE_WARNING,
Gtk::BUTTONS_NONE);
-
+
checker.set_title (_("File Exists!"));
checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
checker.add_button (_("Overwrite Existing File"), RESPONSE_ACCEPT);
checker.set_default_response (RESPONSE_CANCEL);
-
+
checker.set_wmclass (X_("midi_export_file_exists"), PROGRAM_NAME);
checker.set_position (Gtk::WIN_POS_MOUSE);
default:
return;
}
-
+
}
(void) midi_region->clone (path);
{
double const arc_radius = get_width();
double r, g, b, a;
-
+
if (tab.group && tab.group->is_active()) {
ArdourCanvas::color_to_rgba (tab.color, r, g, b, a);
} else {
framepos_t start = selection->time.start();
framepos_t end;
-
+
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
end = _session->audible_frame();
} else {
//snap the selection start/end
snap_to(start);
-
+
//if no tracks are selected and we're working from the keyboard, enable all tracks (_something_ has to be selected for any range selection)
if ( (_edit_point == EditAtPlayhead) && selection->tracks.empty() )
select_all_tracks();
} else {
start = get_preferred_edit_position();
}
-
+
//snap the selection start/end
snap_to(start);
-
+
//if there's not already a sensible selection endpoint, go "forever"
if ( start > end ) {
end = max_framepos;
}
-
+
//if no tracks are selected and we're working from the keyboard, enable all tracks (_something_ has to be selected for any range selection)
if ( selection->tracks.empty() )
select_all_tracks();
-
+
selection->set (start, end);
//if session is playing a range, cancel that
/* Do a full update of the markers in this group */
update_marker_labels (group);
-
+
if (location->is_auto_punch()) {
update_punch_range_view ();
}
if (!loop_or_punch_or_session || !session) {
items.push_back (SeparatorElem());
}
-
+
items.push_back (MenuElem (_("Separate Regions in Range"), sigc::mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
if (!Profile->get_sae()) {
// nothing for now
} else {
-
+
if (!selection->time.empty()) {
l->set (selection->time.start(), selection->time.end_frame());
} else if (!selection->regions.empty()) {
if (a >= extra) {
a -= extra;
}
-
+
framepos_t b = l->end ();
if (b < (max_framepos - extra)) {
b += extra;
transport_loop_range_rect->set_x1 (x2);
transport_loop_range_rect->show();
-
+
} else {
transport_loop_range_rect->hide();
}
double pixel_start;
double pixel_end;
-
+
if (_session->config.get_punch_in()) {
pixel_start = sample_to_pixel (tpl->start());
} else {
} else {
pixel_end = sample_to_pixel (max_framepos);
}
-
+
transport_punch_range_rect->set_x0 (pixel_start);
- transport_punch_range_rect->set_x1 (pixel_end);
+ transport_punch_range_rect->set_x1 (pixel_end);
transport_punch_range_rect->show();
} else {
if (yn) {
Glib::RefPtr<Gdk::Window> win = get_window ();
Glib::RefPtr<Gdk::Screen> screen;
-
+
if (win) {
screen = win->get_screen();
} else {
current_mixer_strip->WidthChanged.connect (sigc::mem_fun(*this, &Editor::ensure_all_elements_drawn));
#endif
current_mixer_strip->set_embedded (true);
-
+
}
void
Editor::mouse_mode_object_range_toggled()
{
MouseMode m = mouse_mode;
-
+
Glib::RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-range"));
assert (act);
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
}
set_gain_envelope_visibility ();
-
+
update_time_selection_display ();
update_all_enter_cursors ();
case TempoMarkerItem: {
ArdourMarker* marker;
TempoMarker* tempo_marker;
-
+
if ((marker = reinterpret_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
abort(); /*NOTREACHED*/
}
-
+
if ((tempo_marker = dynamic_cast<TempoMarker*> (marker)) == 0) {
fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
abort(); /*NOTREACHED*/
}
-
+
edit_tempo_marker (*tempo_marker);
break;
}
case MeterMarkerItem: {
ArdourMarker* marker;
MeterMarker* meter_marker;
-
+
if ((marker = reinterpret_cast<ArdourMarker *> (item->get_data ("marker"))) == 0) {
fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
abort(); /*NOTREACHED*/
}
-
+
if ((meter_marker = dynamic_cast<MeterMarker*> (marker)) == 0) {
fatal << _("programming error: marker for meter is not a meter marker!") << endmsg;
abort(); /*NOTREACHED*/
case SelectionItem:
popup_track_context_menu (1, event->button.time, item_type, true);
break;
-
+
case AutomationTrackItem:
popup_track_context_menu (1, event->button.time, item_type, false);
break;
case MouseDraw:
return true;
-
+
case MouseRange:
// x_style_paste (where, 1.0);
return true;
current_stepping_trackview = 0;
step_timeout.disconnect ();
}
-
+
if (_session && _session->actively_recording()) {
/* Sorry. no dragging stuff around while we record */
return true;
}
-
+
update_join_object_range_location (event->motion.y);
-
+
if (_drags->active ()) {
return _drags->motion_handler (event, from_autoscroll);
}
}
selection->time.clear ();
clicked_selection = 0;
-}
+}
void
Editor::point_trim (GdkEvent* event, framepos_t new_bound)
} else if (entered_track) {
RouteTimeAxisView* entered_route_view = dynamic_cast<RouteTimeAxisView*> (entered_track);
-
+
if (entered_route_view) {
double cx = 0;
if (_drags->active ()) {
_drags->abort ();
}
-
+
if (_session) {
_session->undo (n);
if (_session->undo_depth() == 0) {
if (_drags->active ()) {
_drags->abort ();
}
-
+
if (_session) {
_session->redo (n);
if (_session->redo_depth() == 0) {
for (list<RouteTimeAxisView*>::iterator i = used_trackviews.begin(); i != used_trackviews.end(); ++i) {
region_added_connections.push_back ((*i)->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view)));
}
-
+
while (used_playlists.size() > 0) {
list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
(*i)->thaw();
TimeAxisView *ontrack = 0;
TrackViewList tlist;
-
+
if (!selection->tracks.empty()) {
tlist = selection->tracks.filter_to_unique_playlists ();
} else {
}
/* move to the track below the first one that covers the */
-
+
if (next != track_views.rend()) {
ensure_time_axis_view_is_visible (**next, true);
return true;
}
return false;
-}
+}
bool
Editor::scroll_up_one_track (bool skip_child_views)
{
TrackViewList::iterator prev = track_views.end();
double top_of_trackviews = vertical_adjustment.get_value ();
-
+
for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
if ((*t)->hidden()) {
* Note that covers_y_position() is recursive and includes child views
*/
std::pair<TimeAxisView*,double> res = (*t)->covers_y_position (top_of_trackviews);
-
+
if (res.first) {
if (skip_child_views) {
break;
prev = t;
}
-
+
if (prev != track_views.end()) {
// move to bottom-most automation-lane of the previous track
TimeAxisView::Children kids = (*prev)->get_child_list();
} else {
ts = &selection->tracks;
}
-
+
for (TrackViewList::iterator i = ts->begin(); i != ts->end(); ++i) {
TimeAxisView *tv = (static_cast<TimeAxisView*>(*i));
tv->step_height (coarser);
} else {
ts = &selection->tracks;
}
-
+
for (TrackViewList::iterator i = ts->begin(); i != ts->end(); ++i) {
TimeAxisView *tv = (static_cast<TimeAxisView*>(*i));
uint32_t h = tv->current_height ();
if ( !get_selection_extents(start, end) )
return;
-
+
calc_extra_zoom_edges (start, end);
/* if we're zooming on both axes we need to save track heights etc.
PBD::Unwinder<bool> nsv (no_save_visual, true);
temporal_zoom_by_frame (start, end);
-
+
if (both_axes) {
uint32_t per_track_height = (uint32_t) floor ((_visible_canvas_height - 10.0) / tracks.size());
start = max_framepos;
end = 0;
bool ret = true;
-
+
//ToDo: if notes are selected, set extents to that selection
//ToDo: if control points are selected, set extents to that selection
if ((start == 0 && end == 0) || end < start) {
ret = false;
}
-
- return ret;
+
+ return ret;
}
calc_extra_zoom_edges(start, end);
temporal_zoom_by_frame (start, end);
}
-
+
if (both_axes)
fit_selection();
}
framepos_t range = end - start;
const framecnt_t new_fpp = (framecnt_t) ceil ((double) range / (double) _visible_canvas_width);
-
+
framepos_t new_page = range;
framepos_t middle = (framepos_t) floor ((double) start + ((double) range / 2.0f));
framepos_t new_leftmost = (framepos_t) floor ((double) middle - ((double) new_page / 2.0f));
/* zoom focus is automatically taken as @param frame when this
method is used.
*/
-
+
framepos_t new_leftmost = frame - (framepos_t)range_before;
if (new_leftmost > frame) {
Location *location = new Location (*_session, start, end, rangename, Location::IsRangeMarker);
begin_reversible_command (_("add marker"));
-
+
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
-
+
commit_reversible_command ();
}
}
Location *location = new Location (*_session, where, where, markername, Location::IsMark);
begin_reversible_command (_("add marker"));
-
+
XMLNode &before = _session->locations()->get_state();
_session->locations()->add (location, true);
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
-
+
commit_reversible_command ();
}
{
if (!_session)
return;
-
+
Location* loc;
if ((loc = _session->locations()->session_range_location()) == 0) { //should never happen
_session->set_session_extents ( _session->audible_frame(), _session->audible_frame() );
XMLNode &after = loc->get_state();
begin_reversible_command (_("Set session start"));
-
+
_session->add_command (new MementoCommand<Location>(*loc, &before, &after));
commit_reversible_command ();
{
if (!_session)
return;
-
+
Location* loc;
if ((loc = _session->locations()->session_range_location()) == 0) { //should never happen
_session->set_session_extents ( _session->audible_frame(), _session->audible_frame() );
removed = true;
}
}
-
+
//store undo
if (removed) {
begin_reversible_command (_("remove marker"));
return;
}
bool commit = false;
-
+
XMLNode &before = _session->locations()->get_state();
for (RegionSelection::iterator i = rs.begin (); i != rs.end (); ++i) {
if (pos < 0) {
return;
}
-
+
_session->request_locate (pos, _session->transport_rolling());
}
{
if (_session) {
begin_reversible_command (_("clear markers"));
-
+
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear_markers ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
-
+
commit_reversible_command ();
}
}
{
if (_session) {
begin_reversible_command (_("clear ranges"));
-
+
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear_ranges ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
-
+
commit_reversible_command ();
}
}
Editor::clear_locations ()
{
begin_reversible_command (_("clear locations"));
-
+
XMLNode &before = _session->locations()->get_state();
_session->locations()->clear ();
XMLNode &after = _session->locations()->get_state();
_session->add_command(new MementoCommand<Locations>(*(_session->locations()), &before, &after));
-
+
commit_reversible_command ();
}
return;
location -= get_preroll();
-
+
//don't try to locate before the beginning of time
if ( location < 0 )
location = 0;
-
+
//if follow_playhead is on, keep the playhead on the screen
if ( _follow_playhead )
if ( location < leftmost_frame )
{
{
framepos_t preroll = get_preroll();
-
+
framepos_t start, end;
if (!get_selection_extents ( start, end))
return;
if (start > preroll)
start = start - preroll;
-
+
end = end + preroll; //"post-roll"
-
+
AudioRange ar (start, end, 0);
list<AudioRange> lar;
lar.push_back (ar);
begin_reversible_command (_("raise region to top"));
}
break;
-
+
case Lower:
if (multiple) {
begin_reversible_command (_("lower regions"));
begin_reversible_command (_("lower region"));
}
break;
-
+
case LowerToBottom:
if (multiple) {
begin_reversible_command (_("lower regions to bottom"));
for (set<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
(*i)->clear_owned_changes ();
}
-
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
boost::shared_ptr<Region> r = (*i)->region ();
switch (op) {
(*i)->rdiff (cmds);
_session->add_commands (cmds);
}
-
+
commit_reversible_command ();
}
/* stop transport before we start. this is important */
_session->request_transport_speed (0.0);
-
+
/* wait for just a little while, because the above call is asynchronous */
Glib::usleep (250000);
if (!selection->regions.empty()) {
cut_copy_regions (op, selection->regions);
-
+
if (op == Cut || op == Delete) {
selection->clear_regions ();
}
}
-
+
if (!selection->points.empty()) {
cut_copy_points (op);
-
+
if (op == Cut || op == Delete) {
selection->clear_points ();
}
did_edit = true;
cut_copy_ranges (op);
-
+
if (op == Cut || op == Delete) {
selection->clear_time ();
}
}
-
+
if (did_edit) {
/* reset repeated paste state */
paste_count = 0;
last_paste_pos = 0;
- commit_reversible_command ();
+ commit_reversible_command ();
}
-
+
if (op == Delete || op == Cut || op == Clear) {
_drags->abort ();
}
struct AutomationRecord {
AutomationRecord () : state (0) , line(NULL) {}
AutomationRecord (XMLNode* s, const AutomationLine* l) : state (s) , line (l) {}
-
+
XMLNode* state; ///< state before any operation
const AutomationLine* line; ///< line this came from
boost::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
cut_buffer->add (i->second.copy);
}
}
-
+
if (op == Delete || op == Cut) {
/* This operation needs to remove things from the main AutomationList, so do that now */
-
+
for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
i->first->freeze ();
}
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command(new StatefulDiffCommand (playlist));
commit_reversible_command ();
}
vector<Command*> cmds;
(*pl)->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command(new StatefulDiffCommand (*pl));
}
if (op != Delete) {
vector<PlaylistMapping>::iterator z;
-
+
for (z = pmap.begin(); z != pmap.end(); ++z) {
if ((*z).tv == &tv) {
break;
}
}
-
+
assert (z != pmap.end());
-
+
if (!(*z).pl) {
npl = PlaylistFactory::create (pl->data_type(), *_session, "cutlist", true);
npl->freeze();
if (Config->get_edit_mode() == Ripple)
pl->ripple (r->position(), -r->length(), boost::shared_ptr<Region>());
break;
-
+
case Cut:
_xx = RegionFactory::create (r);
npl->add_region (_xx, r->position() - first_position);
if (op != Delete) {
list<boost::shared_ptr<Playlist> > foo;
-
+
/* the pmap is in the same order as the tracks in which selected regions occured */
-
+
for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
if ((*i).pl) {
(*i).pl->thaw();
foo.push_back ((*i).pl);
}
}
-
+
if (!foo.empty()) {
cut_buffer->set (foo);
}
-
+
if (pmap.empty()) {
_last_cut_copy_source_track = 0;
} else {
vector<Command*> cmds;
(*pl)->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command (new StatefulDiffCommand (*pl));
}
}
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command(new StatefulDiffCommand (playlist));
}
}
bool in_command = false;
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
}
begin_reversible_command (_("toggle region lock"));
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_locked (!(*i)->region()->locked());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
-
+
commit_reversible_command ();
}
}
begin_reversible_command (_("Toggle Video Lock"));
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_video_locked (!(*i)->region()->video_locked());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
-
+
commit_reversible_command ();
}
}
begin_reversible_command (_("region lock style"));
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
PositionLockStyle const ns = (*i)->region()->position_lock_style() == AudioTime ? MusicTime : AudioTime;
(*i)->region()->set_position_lock_style (ns);
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
-
+
commit_reversible_command ();
}
}
begin_reversible_command (_("change region opacity"));
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
(*i)->region()->clear_changes ();
(*i)->region()->set_opaque (!(*i)->region()->opaque());
_session->add_command (new StatefulDiffCommand ((*i)->region()));
}
-
+
commit_reversible_command ();
}
if (_ignore_region_action) {
return;
}
-
+
boost::shared_ptr<AudioRegion> ar;
bool yn = false;
//if no range was selected, try to find some regions to split
if (current_mouse_mode() == MouseObject) { //don't try this for Internal Edit, Stretch, Draw, etc.
-
+
RegionSelection rs = get_regions_from_selection_and_edit_point ();
framepos_t where = get_preferred_edit_position ();
if (_session == 0) {
return;
}
-
+
framepos_t start, end;
if (!get_selection_extents ( start, end))
return;
framepos_t start = 0;
framepos_t end = max_framepos;
-
+
//use the existing punch end, if any
Location* tpl = transport_punch_location();
if (tpl) {
end = tpl->end();
}
-
+
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
start = _session->audible_frame();
} else {
start = get_preferred_edit_position();
}
-
+
//snap the selection start/end
snap_to(start);
-
+
//if there's not already a sensible selection endpoint, go "forever"
if ( start > end ) {
end = max_framepos;
}
-
+
set_punch_range (start, end, _("set punch start from EP"));
}
framepos_t start = 0;
framepos_t end = max_framepos;
-
+
//use the existing punch start, if any
Location* tpl = transport_punch_location();
if (tpl) {
start = tpl->start();
}
-
+
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
end = _session->audible_frame();
} else {
//snap the selection start/end
snap_to(end);
-
+
set_punch_range (start, end, _("set punch end from EP"));
}
framepos_t start = 0;
framepos_t end = max_framepos;
-
+
//use the existing loop end, if any
Location* tpl = transport_loop_location();
if (tpl) {
end = tpl->end();
}
-
+
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
start = _session->audible_frame();
} else {
start = get_preferred_edit_position();
}
-
+
//snap the selection start/end
snap_to(start);
-
+
//if there's not already a sensible selection endpoint, go "forever"
if ( start > end ) {
end = max_framepos;
framepos_t start = 0;
framepos_t end = max_framepos;
-
+
//use the existing loop start, if any
Location* tpl = transport_loop_location();
if (tpl) {
start = tpl->start();
}
-
+
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
end = _session->audible_frame();
} else {
//snap the selection start/end
snap_to(end);
-
+
set_loop_range (start, end, _("set loop end from EP"));
}
}
}
begin_reversible_command (_("split regions"));
-
+
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ) {
RegionSelection::iterator tmp;
i = tmp;
}
-
+
commit_reversible_command ();
}
vector<Command*> cmds;
pl->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command (new StatefulDiffCommand (pl));
if (select_new) {
framepos_t where = get_preferred_edit_position();
begin_reversible_command (_("place transient"));
-
+
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
framepos_t position = (*r)->region()->position();
(*r)->region()->add_transient(where - position);
}
-
+
commit_reversible_command ();
}
}
begin_reversible_command (_("snap regions to grid"));
-
+
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) {
boost::shared_ptr<Playlist> pl = (*r)->region()->playlist();
(*i)->thaw();
used_playlists.pop_front();
}
-
+
commit_reversible_command ();
}
/* Iterate over the region list and make adjacent regions overlap by crossfade_len_ms */
begin_reversible_command (_("close region gaps"));
-
+
int idx = 0;
boost::shared_ptr<Region> last_region;
(*i)->thaw();
used_playlists.pop_front();
}
-
+
commit_reversible_command ();
}
if (!_session) {
return;
}
-
+
framepos_t pos = playhead_cursor->current_frame ();
if (pos < max_framepos - 1) {
pos += 2;
if (!_session) {
return;
}
-
+
framepos_t pos = playhead_cursor->current_frame ();
if (pos > 2) {
pos -= 2;
trackstr = P_("track", "tracks", ntracks);
busstr = P_("bus", "busses", nbusses);
-
+
if (ntracks) {
if (nbusses) {
prompt = string_compose (_("Do you really want to remove %1 %2 and %3 %4?\n"
pl.insert ((*x)->playlist ());
}
}
-
+
for (set<boost::shared_ptr<Playlist> >::iterator i = pl.begin(); i != pl.end(); ++i) {
(*i)->clear_changes ();
if (response != RESPONSE_OK) {
return;
}
-
+
framecnt_t distance = d.distance();
if (distance == 0) {
for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
/* regions */
boost::shared_ptr<Playlist> pl = (*x)->playlist();
-
+
if (pl) {
XMLNode &before = pl->get_state();
-
+
std::list<AudioRange> rl;
AudioRange ar(pos, pos+frames, 0);
rl.push_back(ar);
pl->cut (rl);
pl->shift (pos, -frames, true, ignore_music_glue);
-
+
if (!in_command) {
begin_reversible_command (_("cut time"));
in_command = true;
}
XMLNode &after = pl->get_state();
-
+
_session->add_command (new MementoCommand<Playlist> (*pl, &before, &after));
}
-
+
/* automation */
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*x);
if (rtav) {
}
std::list<Location*> loc_kill_list;
-
+
/* markers */
if (markers_too) {
bool moved = false;
for (list<Location*>::iterator i = loc_kill_list.begin(); i != loc_kill_list.end(); ++i) {
_session->locations()->remove( *i );
}
-
+
if (moved) {
if (!in_command) {
begin_reversible_command (_("cut time"));
_session->add_command (new MementoCommand<Locations>(*_session->locations(), &before, &after));
}
}
-
+
if (tempo_too) {
XMLNode& before (_session->tempo_map().get_state());
_session->add_command (new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
}
}
-
+
if (in_command) {
commit_reversible_command ();
}
Editor::start_visual_state_op (uint32_t n)
{
save_visual_state (n);
-
+
PopUp* pup = new PopUp (WIN_POS_MOUSE, 1000, true);
char buf[32];
snprintf (buf, sizeof (buf), _("Saved view %u"), n+1);
onoff = !mt->input_active();
}
}
-
+
_session->set_exclusive_input_active (rl, onoff, flip_others);
}
b->set_text (_("Click to unlock"));
b->signal_clicked.connect (sigc::mem_fun (*this, &Editor::unlock));
lock_dialog->get_vbox()->pack_start (*b);
-
+
lock_dialog->get_vbox()->show_all ();
lock_dialog->set_size_request (200, 200);
}
delete _main_menu_disabler;
_main_menu_disabler = new MainMenuDisabler;
-
+
lock_dialog->present ();
}
Editor::unlock ()
{
lock_dialog->hide ();
-
+
delete _main_menu_disabler;
if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
ArdourDialog w (_("Moving embedded files into session folder"));
w.get_vbox()->pack_start (msg);
w.present ();
-
+
/* flush all pending GUI events because we're about to start copying
* files
*/
-
+
Gtkmm2ext::UI::instance()->flush_pending ();
cerr << " Do it\n";
{ 10, S_("Opaque|O"), _("Region opaque (blocks regions below it from being heard)?") },
{ -1, 0, 0 }
};
-
+
for (int i = 0; ci[i].index >= 0; ++i) {
col = _display.get_column (ci[i].index);
l = manage (new Label (ci[i].label));
*/
row = *(_model->insert (subrows.end()));
-
+
} else {
row = *(_model->append());
}
_change_connection.block (false);
}
}
-
+
}
} else {
_editor->get_selection().clear_regions ();
TreeViewColumn* color_column = manage (new TreeViewColumn ("", *color_renderer));
color_column->add_attribute (color_renderer->property_color(), _columns.gdkcolor);
-
+
_display.append_column (*color_column);
_display.append_column ("", _columns.text);
CellRendererText* name_cell = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (1));
name_cell->property_editable() = true;
name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRouteGroups::name_edit));
-
+
for (int i = 1; ci[i].index >= 0; ++i) {
CellRendererToggle* active_cell = dynamic_cast <CellRendererToggle*> (_display.get_column_cell_renderer (i));
c = color_dialog.get_colorsel()->get_current_color();
GroupTabs::set_group_color (group, gdk_color_to_rgba (c));
break;
-
+
default:
break;
-
+
}
color_dialog.hide ();
ret = true;
break;
-
+
case 3:
val = (*iter)[_columns.active_state];
group->set_active (!val, this);
row[_columns.active_shared] = group->is_route_active ();
row[_columns.active_state] = group->is_active ();
row[_columns.is_visible] = !group->is_hidden();
-
+
Gdk::Color c;
set_color_from_rgba (c, GroupTabs::group_color (group));
row[_columns.gdkcolor] = c;
-
+
_in_row_change = true;
row[_columns.routegroup] = group;
break;
}
}
-
+
_in_row_change = false;
for (TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) {
}
bool visible = tv->marked_for_display ();
-
+
/* show or hide the TimeAxisView */
if (visible) {
position += tv->show_at (position, n, &_editor->edit_controls_vbox);
for (ri = rows.begin(); ri != rows.end(); ++ri) {
/* skip two special values */
-
+
if (rid == Route::MasterBusRemoteControlID) {
rid++;
}
-
+
if (rid == Route::MonitorBusRemoteControlID) {
rid++;
}
}
RouteList r (*_session->get_routes());
-
+
r.sort (EditorOrderRouteSorter ());
_editor->add_routes (r);
}
(*i)[_columns.active] = route->active ();
if (boost::dynamic_pointer_cast<Track> (route)) {
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
-
+
if (route->record_enabled()) {
if (_session->record_status() == Session::Recording) {
(*i)[_columns.rec_state] = 1;
} else {
(*i)[_columns.rec_state] = 0;
}
-
+
(*i)[_columns.name_editable] = !route->record_enabled ();
}
}
_bbt_metric = new BBTMetric (this);
_minsec_metric = new MinsecMetric (this);
_samples_metric = new SamplesMetric (this);
-
+
timecode_ruler = new ArdourCanvas::Ruler (_time_markers_group, *_timecode_metric,
ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, timebar_height));
timecode_ruler->set_font_description (font);
minsec_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), minsec_ruler, MinsecRulerItem));
bbt_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), bbt_ruler, BBTRulerItem));
samples_ruler->Event.connect (sigc::bind (sigc::mem_fun (*this, &Editor::canvas_ruler_event), samples_ruler, SamplesRulerItem));
-
+
visible_timebars = 0; /*this will be changed below */
}
} else {
bbt_ruler_scale = bbt_show_ticks_detail;
}
-
+
if ((bbt_ruler_scale == bbt_show_ticks_detail) && (lower_beat.beats == upper_beat.beats) && (upper_beat.ticks - lower_beat.ticks <= Timecode::BBT_Time::ticks_per_beat / 4)) {
bbt_ruler_scale = bbt_show_ticks_super_detail;
}
copy.label = newlabel;
marks.pop_back ();
marks.push_back (copy);
-}
+}
void
Editor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdouble lower, gdouble upper, gint /*maxchars*/)
bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
-
+
// could do marks.assign() here to preallocate
mark.label = "";
RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
if (v && v->route()->route_group() == group) {
-
+
boost::shared_ptr<Track> t = v->track();
if (t) {
if (playlists.insert (t->playlist()).second) {
ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
/* notify control protocols */
-
+
ControlProtocol::TrackSelectionChanged (routes);
if (sfbrowser && _session && !_session->deletion_in_progress()) {
if (have_active_fade_out && have_inactive_fade_out) {
// a->set_inconsistent ();
}
-
+
bool const have_active_fade = have_active_fade_in || have_active_fade_out;
bool const have_inactive_fade = have_inactive_fade_in || have_inactive_fade_out;
if (have_active_fade && have_inactive_fade) {
// a->set_inconsistent ();
}
-
+
_ignore_region_action = false;
_all_region_actions_sensitized = false;
/* find all the tracks that have selected regions */
set<TimeAxisView*> tracks;
-
+
for (RegionSelection::const_iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
tracks.insert (&(*r)->get_time_axis_view());
}
selection->set (selection->regions.start(), selection->regions.end_frame());
/* and select the tracks */
-
+
selection->set (tvl);
-
+
if (!Profile->get_sae()) {
set_mouse_mode (Editing::MouseRange, false);
}
end = 0;
return false;
}
-
+
// if (!mouse_frame (m, ignored)) {
// /* mouse is not in a canvas, try playhead+selected marker.
// this is probably most true when using menus.
}
cairo_push_group (cr);
-
+
/* Fill with the background image */
cairo_rectangle (cr, 0, 0, get_width(), get_height());
EditorSummary::on_button_press_event (GdkEventButton* ev)
{
_old_follow_playhead = _editor->follow_playhead ();
-
+
if (ev->button == 1) {
pair<double, double> xr;
get_editor (&_pending_editor_x, &_pending_editor_y);
_pending_editor_changed = false;
}
-
+
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
/* secondary-modifier-click: locate playhead */
/* We are dragging, and configured not to update the editor window during drags,
so just return where the editor will be when the drag finishes.
*/
-
+
*x = _pending_editor_x;
*y = _pending_editor_y;
x->first = (_editor->leftmost_sample () - _start) * _x_scale;
x->second = x->first + _editor->current_page_samples() * _x_scale;
-
+
y->first = editor_y_to_summary (_editor->vertical_adjustment.get_value ());
y->second = editor_y_to_summary (_editor->vertical_adjustment.get_value () + _editor->visible_canvas_height() - _editor->get_trackview_group()->canvas_origin().y);
}
EditorSummary::on_button_release_event (GdkEventButton*)
{
bool const was_suspended = suspending_editor_updates ();
-
+
_move_dragging = false;
_zoom_dragging = false;
_editor->_dragging_playhead = false;
if (was_suspended && _pending_editor_changed) {
set_editor (_pending_editor_x, _pending_editor_y);
}
-
+
return true;
}
as it also means that we won't change these variables if an idle handler
is merely pending but not executing. But c'est la vie.
*/
-
+
return;
}
set_dirty ();
} else {
_editor->reset_x_origin (x.first / _x_scale + _start);
-
+
double const nx = (
((x.second - x.first) / _x_scale) /
_editor->sample_to_pixel (_editor->current_page_samples())
);
-
+
if (nx != _editor->get_current_zoom ()) {
_editor->reset_zoom (nx);
}
if (immediate_redraw) {
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
-
+
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
current_bbt_points_begin, current_bbt_points_end);
draw_measures (current_bbt_points_begin, current_bbt_points_end);
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end); // redraw rulers and measures
-
+
} else {
Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::mem_fun (*this, &Editor::redisplay_tempo), true), false));
}
do_timefx ();
return 0;
}
-
+
switch (current_timefx->run ()) {
case RESPONSE_ACCEPT:
break;
basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
++row;
}
-
+
output_channels.set_name ("OutputChannels");
output_channels.set_flags (Gtk::CAN_FOCUS);
output_channels.set_digits (0);
basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
++row;
}
-
+
input_latency.set_name ("InputLatency");
input_latency.set_flags (Gtk::CAN_FOCUS);
input_latency.set_digits (0);
if (ARDOUR::Profile->get_mixbus()) {
return true;
}
-
+
uint32_t cnt = (uint32_t) sb->get_value();
if (cnt == 0) {
sb->set_text (_("all available channels"));
queue_device_changed = true;
}
}
-
+
//the device name must be set FIRST so ASIO can populate buffersizes and the control panel button
if (backend->use_separate_input_and_output_devices()) {
backend->set_input_device_name (device_name_in);
export_notebook.append_page (*file_format_selector, _("File format"));
export_notebook.append_page (*timespan_selector, _("Time Span"));
export_notebook.append_page (*channel_selector, _("Channels"));
-
+
get_vbox()->pack_start (export_notebook, true, true, 0);
get_vbox()->pack_end (warning_widget, false, false, 0);
get_vbox()->pack_end (progress_widget, false, false, 0);
if (!status->aborted()) {
NagScreen* ns = NagScreen::maybe_nag (_("export"));
-
+
if (ns) {
ns->nag ();
delete ns;
example = profile_manager->get_sample_filename_for_format (
filename_state->filename, format_state->format);
}
-
+
if (example != "") {
filename_selector.set_example_filename(Glib::path_get_basename (example));
} else {
while (true) {
int result = dialog.run();
-
+
if (result == Gtk::RESPONSE_OK) {
std::string filename = dialog.get_filename();
-
+
if (!Glib::file_test (filename, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
Gtk::MessageDialog msg (string_compose (_("%1: this is only the directory/folder name, not the filename.\n\
The filename will be chosen from the information just above the folder selector."), filename));
AudioClock silence_end_clock;
/* Post-export hook */
-
+
Gtk::Label command_label;
Gtk::Entry command_entry;
)
);
option_hbox.pack_start (*b, false, false, 6);
-
+
b = Gtk::manage (new Gtk::Button (_("Deselect All")));
b->signal_clicked().connect (
sigc::bind (
set_name (X_("FloatingTextEntry"));
set_position (Gtk::WIN_POS_MOUSE);
set_border_width (0);
-
+
if (!initial_contents.empty()) {
entry.set_text (initial_contents);
}
max_peak = minus_infinity();
peak_display.set_text (_("-inf"));
peak_display.set_alignment(0.5);
-
+
/* stuff related to the fact that the peak display is not, in
fact, supposed to be a text entry.
*/
ignore_toggle = false;
effective_gain_display ();
-
+
_previous_amp_output_streams = _amp->output_streams ();
}
} else {
value = gain_adjustment.get_value();
}
-
+
if (!ignore_toggle) {
if (_route && _route->amp() == _amp) {
_route->set_gain (value, this);
smaller_hbox->pack_start (delete_button, false, false);
smaller_hbox->pack_start (reset_button, false, false, 4);
smaller_hbox->pack_start (bypass_button, false, true, 4);
-
+
automation_manual_all_button.set_text(_("Manual"));
automation_manual_all_button.set_name (X_("generic button"));
automation_play_all_button.set_text(_("Play"));
automation_write_all_button.set_name (X_("generic button"));
automation_touch_all_button.set_text(_("Touch"));
automation_touch_all_button.set_name (X_("generic button"));
-
+
Label* l = manage (new Label (_("All Automation")));
l->set_alignment (1.0, 0.5);
automation_hbox->pack_start (*l, true, true);
static int match_or_digit(char c1, char c2) {
return c1 == c2 || (isdigit(c1) && isdigit(c2));
-}
+}
static std::size_t matching_chars_at_head(const string s1, const string s2) {
std::size_t length, n = 0;
// Iterate over the list of controls to find which adjacent controls
// are similar enough to be grouped together.
-
+
string label, previous_label = "";
std::vector<int> numbers_in_labels(cui_controls_list.size());
-
+
std::vector<float> similarity_scores(cui_controls_list.size());
float most_similar = 0.0, least_similar = 1.0;
-
+
i = 0;
for (vector<ControlUI*>::iterator cuip = cui_controls_list.begin(); cuip != cui_controls_list.end(); ++cuip, ++i) {
label = (*cuip)->label.get_text();
}
// cerr << "label: " << label << " sim: " << fixed << setprecision(3) << similarity_scores[i] << " num: " << numbers_in_labels[i] << endl;
- previous_label = label;
+ previous_label = label;
}
-
+
// cerr << "most similar: " << most_similar << ", least similar: " << least_similar << endl;
float similarity_threshold;
-
+
if (most_similar > 1.0) {
similarity_threshold = default_similarity_threshold;
} else {
similarity_threshold = most_similar - (1 - default_similarity_threshold);
}
-
+
// Now iterate over the list of controls to display them, placing an
// HSeparator between controls of less than a certain similarity, and
// starting a new column when necessary.
-
+
i = 0;
for (vector<ControlUI*>::iterator cuip = cui_controls_list.begin(); cuip != cui_controls_list.end(); ++cuip, ++i) {
ControlUI* cui = *cuip;
-
+
if (!is_scrollable) {
x++;
}
-
+
if (x > max_controls_per_column || similarity_scores[i] <= similarity_threshold) {
if (x > min_controls_per_column) {
frame = manage (new Frame);
output_table.show_all ();
button_table.show_all ();
-
+
automation_manual_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Off));
automation_play_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Play));
automation_write_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Write));
int const steps = desc.integer_step ? (desc.upper - desc.lower + 1) / desc.step : 0;
if (control_ui->scale_points && ((steps && int (control_ui->scale_points->size()) == steps) || desc.enumeration)) {
-
+
/* Either:
* a) There is a label for each possible value of this input, or
* b) This port is marked as being an enumeration.
ARDOUR::ScalePoints::const_iterator i = control_ui->scale_points->begin();
i != control_ui->scale_points->end();
++i) {
-
+
labels.push_back(i->first);
}
public:
GhostEvent(::NoteBase *, ArdourCanvas::Container *);
virtual ~GhostEvent ();
-
+
NoteBase* event;
ArdourCanvas::Item* item;
};
_session->RouteRemovedFromRouteGroup.connect (
_session_connections, invalidator (*this), boost::bind (&GroupTabs::route_removed_from_route_group, this, _1, _2), gui_context()
);
-
+
_session->route_group_removed.connect (_session_connections, invalidator (*this), boost::bind (&GroupTabs::set_dirty, this), gui_context());
}
}
} else if (ev->button == 3) {
RouteGroup* g = t ? t->group : 0;
-
+
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier) && g) {
/* edit */
RouteGroupDialog d (g, false);
if (_dragging == 0) {
return false;
}
-
+
if (!_drag_moved) {
-
+
if (_dragging->group) {
/* toggle active state */
_dragging->group->set_active (!_dragging->group->is_active (), this);
}
-
+
} else {
/* finish drag */
RouteList routes = routes_for_tab (_dragging);
-
+
if (!routes.empty()) {
if (_dragging_new_tab) {
RouteGroup* g = create_and_add_group ();
} else {
boost::shared_ptr<RouteList> r = _session->get_routes ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
+
bool const was_in_tab = find (
_initial_dragging_routes.begin(), _initial_dragging_routes.end(), *i
) != _initial_dragging_routes.end ();
-
+
bool const now_in_tab = find (routes.begin(), routes.end(), *i) != routes.end();
-
+
if (was_in_tab && !now_in_tab) {
_dragging->group->remove (*i);
} else if (!was_in_tab && now_in_tab) {
}
}
}
-
+
set_dirty ();
queue_draw ();
}
-
+
_dragging = 0;
_initial_dragging_routes.clear ();
cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
cairo_rectangle (cr, 0, 0, get_width(), get_height());
cairo_fill (cr);
-
+
/* tabs */
for (list<Tab>::const_iterator i = _tabs.begin(); i != _tabs.end(); ++i) {
g = 25;
b = 25;
}
-
+
GUIObjectState& gui_state = *ARDOUR_UI::instance()->gui_object_state;
char buf[64];
-
+
/* for historical reasons the colors must be stored as 16 bit color
* values. Ugh.
*/
snprintf (buf, sizeof (buf), "%d:%d:%d", (r<<8), (g<<8), (b<<8));
gui_state.set_property (group_gui_id (group), "color", buf);
-
+
/* the group color change notification */
-
+
PBD::PropertyChange change;
change.add (Properties::color);
group->PropertyChanged (change);
GroupTabs::group_color (RouteGroup* group)
{
assert (group);
-
+
GUIObjectState& gui_state = *ARDOUR_UI::instance()->gui_object_state;
string const gui_id = group_gui_id (group);
bool empty;
*/
emit_gui_changed_for_members (rg);
-
+
set_dirty ();
}
private:
static void emit_gui_changed_for_members (ARDOUR::RouteGroup *);
-
+
/** Compute all the tabs for this widget.
* @return Tabs.
*/
static XMLNode* get_or_add_node (XMLNode *, const std::string &);
void remove_node (const std::string& id);
-
+
private:
XMLNode _state;
};
IOSelectorWindow::io_name_changed (void*)
{
ENSURE_GUI_THREAD (*this, &IOSelectorWindow::io_name_changed, src)
-
+
std::string title;
if (!_selector.find_inputs_for_io_outputs()) {
unbind_button.show ();
}
-
+
reset_button.add (reset_label);
reset_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Reset Bindings to Defaults")));
-
+
reset_box.pack_start (reset_button, true, false);
reset_box.show ();
reset_button.show ();
int TempErrorHandler(Display *display, XErrorEvent *e)
{
LXVST_xerror = true;
-
+
return 0;
}
unsigned char *data;
Atom userType;
LXVST_xerror = false;
-
+
/*Use our own Xerror handler while we're in here - in an
attempt to stop the brain dead default Xerror behaviour of
qutting the entire application because of e.g. an invalid
window ID*/
-
+
XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
-
+
XGetWindowProperty( LXVST_XDisplay, //The display
window, //The Window
atom, //The property
&userCount, //Actual number of items stored in the returned data
&bytes, //Number of bytes remaining if a partial read
&data); //The actual data read
-
+
if(LXVST_xerror == false && userCount == 1)
result = *(int*)data;
-
+
XSetErrorHandler(olderrorhandler);
-
+
/*Hopefully this will return zero if the property is not set*/
-
+
return result;
}
unsigned char *data;
Atom userType;
LXVST_xerror = false;
-
+
/*Use our own Xerror handler while we're in here - in an
attempt to stop the brain dead default Xerror behaviour of
qutting the entire application because of e.g. an invalid
window ID*/
-
+
XErrorHandler olderrorhandler = XSetErrorHandler(TempErrorHandler);
-
+
XGetWindowProperty( LXVST_XDisplay,
window,
atom,
&userCount,
&bytes,
&data);
-
+
if(LXVST_xerror == false && userCount == 1)
result = *(long*)data;
-
+
XSetErrorHandler(olderrorhandler);
-
+
/*Hopefully this will return zero if the property is not set*/
-
+
return result;
}
dispatch_x_events (XEvent* event, VSTState* vstfx)
{
/*Handle some of the Events we might be interested in*/
-
+
switch(event->type)
{
/*Configure event - when the window is resized or first drawn*/
-
+
case ConfigureNotify:
{
Window window = event->xconfigure.event;
-
+
int width = event->xconfigure.width;
int height = event->xconfigure.height;
-
+
/*If we get a config notify on the parent window XID then we need to see
if the size has been changed - some plugins re-size their UI window e.g.
when opening a preset manager (you might think that should be spawned as a new window...) */
-
+
/*if the size has changed, we flag this so that in lxvst_pluginui.cc we can make the
change to the GTK parent window in ardour, from its UI thread*/
-
+
if (window == (Window) (vstfx->linux_window)) {
if (width != vstfx->width || height!=vstfx->height) {
vstfx->width = width;
vstfx->height = height;
vstfx->want_resize = 1;
-
+
/*QUIRK : Loomer plugins not only resize the UI but throw it into some random
position at the same time. We need to re-position the window at the origin of
the parent window*/
-
+
if (vstfx->linux_plugin_ui_window) {
XMoveWindow (LXVST_XDisplay, vstfx->linux_plugin_ui_window, 0, 0);
}
}
}
-
+
break;
-
+
}
-
+
/*Reparent Notify - when the plugin UI is reparented into
our Host Window we will get an event here... probably... */
-
+
case ReparentNotify:
{
Window ParentWindow = event->xreparent.parent;
-
+
/*If the ParentWindow matches the window for the vstfx instance then
the Child window must be the XID of the pluginUI window created by the
plugin, so we need to see if it has a callback stuck to it, and if so
set that up in the vstfx */
-
+
/***********************************************************/
/* 64Bit --- This mechanism is not 64Bit compatible at the */
/* present time */
/***********************************************************/
-
+
if (ParentWindow == (Window) (vstfx->linux_window)) {
Window PluginUIWindowID = event->xreparent.window;
-
+
vstfx->linux_plugin_ui_window = PluginUIWindowID;
#ifdef LXVST_32BIT
int result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
-
+
if (result == 0) {
vstfx->eventProc = NULL;
} else {
#endif
#ifdef LXVST_64BIT
long result = getXWindowProperty(PluginUIWindowID, XInternAtom(LXVST_XDisplay, "_XEventProc", false));
-
+
if(result == 0)
vstfx->eventProc = NULL;
else
}
break;
}
-
+
case ClientMessage:
{
Window window = event->xany.window;
Atom message_type = event->xclient.message_type;
-
+
/*The only client message we are interested in is to signal
that the plugin parent window is now valid and can be passed
to effEditOpen when the editor is launched*/
-
+
if (window == (Window) (vstfx->linux_window)) {
char* message = XGetAtomName(LXVST_XDisplay, message_type);
-
+
if (strcmp(message,"LaunchEditor") == 0) {
if (event->xclient.data.l[0] == 0x0FEEDBAC) {
vstfx_launch_editor (vstfx);
}
}
-
+
XFree(message);
}
break;
}
-
+
default:
break;
}
-
+
/* Some VSTs built with toolkits e.g. JUCE will manager their own UI
autonomously in the plugin, running the UI in its own thread, so once
we have created a parent window for the plugin, its UI takes care of
itself.*/
-
+
/*Other types register a callback as an Xwindow property on the plugin
UI window after they create it. If that is the case, we need to call it
here, passing the XEvent into it*/
-
+
if (vstfx->eventProc == NULL) {
return;
}
-
+
vstfx->eventProc((void*)event);
}
}
vstfx->plugin->dispatcher (vstfx->plugin, effSetProgram, 0, vstfx->want_program, NULL, 0);
-
+
if (vstfx->vst_version >= 2) {
vstfx->plugin->dispatcher (vstfx->plugin, 68 /* effEndSetProgram */, 0, 0, NULL, 0);
}
-
+
vstfx->want_program = -1;
}
int LXVST_sched_timer_interval = 40; //ms, 25fps
XEvent event;
uint64_t clock1, clock2;
-
+
clock1 = g_get_monotonic_time();
/*The 'Forever' loop - runs the plugin UIs etc - based on the FST gui event loop*/
-
+
while (!gui_quit)
{
/* handle window creation requests, destroy requests,
/*Look at the XEvent queue - if there are any XEvents we need to handle them,
including passing them to all the plugin (eventProcs) we are currently managing*/
-
+
bool may_sleep = true;
if(LXVST_XDisplay)
{
/*See if there are any events in the queue*/
-
+
int num_events = XPending(LXVST_XDisplay);
if (num_events > 0) {
// keep dispatching events as fast as possible
may_sleep = false;
}
-
+
/*process them if there are any*/
-
+
while(num_events)
{
XNextEvent(LXVST_XDisplay, &event);
-
+
/*Call dispatch events, with the event, for each plugin in the linked list*/
-
+
for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
- {
+ {
pthread_mutex_lock(&vstfx->lock);
-
+
dispatch_x_events(&event, vstfx);
-
+
pthread_mutex_unlock(&vstfx->lock);
}
-
+
num_events--;
}
}
/*We don't want to use all the CPU.. */
Glib::usleep(1000);
-
+
/*See if its time for us to do a scheduled event pass on all the plugins*/
clock2 = g_get_monotonic_time();
{
//printf("elapsed %d ms ^= %.2f Hz\n", elapsed_time_ms, 1000.0/(double)elapsed_time_ms); // DEBUG
pthread_mutex_lock (&plugin_mutex);
-
+
again:
/*Parse through the linked list of plugins*/
-
+
for (vstfx = vstfx_first; vstfx; vstfx = vstfx->next)
- {
+ {
pthread_mutex_lock (&vstfx->lock);
/*Window scheduled for destruction*/
-
+
if (vstfx->destroy) {
if (vstfx->linux_window) {
vstfx->plugin->dispatcher (vstfx->plugin, effEditClose, 0, 0, NULL, 0.0);
-
+
XDestroyWindow (LXVST_XDisplay, vstfx->linux_window);
/* FIXME - probably safe to assume we never have an XID of 0 but not explicitly true */
vstfx->linux_window = 0;
vstfx->destroy = FALSE;
}
-
+
vstfx_event_loop_remove_plugin (vstfx);
vstfx->been_activated = FALSE;
pthread_cond_signal (&vstfx->window_status_change);
pthread_mutex_unlock (&vstfx->lock);
-
+
goto again;
}
-
+
/*Window does not yet exist - scheduled for creation*/
/* FIXME - probably safe to assume 0 is not a valid XID but not explicitly true */
maybe_set_program (vstfx);
vstfx->want_program = -1;
vstfx->want_chunk = 0;
-
+
/*scheduled call to dispatcher*/
-
+
if (vstfx->dispatcher_wantcall) {
vstfx->dispatcher_retval = vstfx->plugin->dispatcher (
vstfx->plugin,
vstfx->dispatcher_ptr,
vstfx->dispatcher_opt
);
-
+
vstfx->dispatcher_wantcall = 0;
pthread_cond_signal (&vstfx->plugin_dispatcher_called);
}
-
+
/*Call the editor Idle function in the plugin*/
-
+
vstfx->plugin->dispatcher (vstfx->plugin, effEditIdle, 0, 0, NULL, 0);
if(vstfx->wantIdle)
vstfx->plugin->dispatcher (vstfx->plugin, 53, 0, 0, NULL, 0);
-
+
pthread_mutex_unlock (&vstfx->lock);
}
pthread_mutex_unlock (&plugin_mutex);
{
int thread_create_result;
-
+
pthread_attr_t thread_attributes;
-
+
/*Init the attribs to defaults*/
-
+
pthread_attr_init(&thread_attributes);
-
+
/*Make sure the thread is joinable - this should be the default anyway -
so we can join to it on vstfx_exit*/
-
+
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
-
+
/*This is where we need to open a connection to X, and start the GUI thread*/
-
+
/*Open our connection to X - all linuxVST plugin UIs handled by the LXVST engine
will talk to X down this connection - X cannot handle multi-threaded access via
the same Display* */
-
+
if(LXVST_XDisplay==NULL)
LXVST_XDisplay = XOpenDisplay(NULL); //We might be able to make this open a specific screen etc
/*Drop out and report the error if we fail to connect to X */
-
+
if(LXVST_XDisplay==NULL)
{
vstfx_error ("** ERROR ** VSTFX: Failed opening connection to X");
-
+
return -1;
}
-
+
/*We have a connection to X - so start the gui event loop*/
-
+
/*Create the thread - use default attrs for now, don't think we need anything special*/
-
+
thread_create_result = pthread_create(&LXVST_gui_event_thread, NULL, gui_event_loop, NULL);
-
+
if(thread_create_result!=0)
{
/*There was a problem starting the GUI event thread*/
-
+
vstfx_error ("** ERROR ** VSTFX: Failed starting GUI event thread");
-
+
XCloseDisplay(LXVST_XDisplay);
-
+
return -1;
}
-
+
return 0;
}
void vstfx_exit()
{
gui_quit = 1;
-
+
/*We need to pthread_join the gui_thread here so
we know when it has stopped*/
-
+
pthread_join(LXVST_gui_event_thread, NULL);
}
vstfx_first = vstfx;
} else {
VSTState* p = vstfx_first;
-
+
while (p->next) {
p = p->next;
}
p->next = vstfx;
-
+
/* Mark the new end of the list */
-
+
vstfx->next = NULL;
}
/* wait for the plugin editor window to be created (or not) */
pthread_mutex_lock (&vstfx->lock);
-
+
if (!vstfx->linux_window) {
pthread_cond_wait (&vstfx->window_status_change, &vstfx->lock);
}
-
+
pthread_mutex_unlock (&vstfx->lock);
if (!vstfx->linux_window) {
int vstfx_create_editor (VSTState* vstfx)
{
Window parent_window;
-
+
int x_size = 1;
int y_size = 1;
vstfx_error ("** ERROR ** VSTFX: Plugin \"%s\" has no editor", vstfx->handle->name);
return -1;
}
-
-
+
+
/*Create an XWindow for the plugin to inhabit*/
-
+
parent_window = XCreateSimpleWindow (
LXVST_XDisplay,
DefaultRootWindow(LXVST_XDisplay),
0,
0
);
-
+
/*Select the events we are interested in receiving - we need Substructure notify so that
if the plugin resizes its window - e.g. Loomer Manifold then we get a message*/
-
+
XSelectInput(LXVST_XDisplay,
parent_window,
SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask);
-
+
vstfx->linux_window = parent_window;
-
+
vstfx->xid = parent_window; //vstfx->xid will be referenced to connect to GTK UI in ardour later
-
+
/*Because the plugin may be operating on a different Display* to us, and therefore
the two event queues can be asynchronous, although we have created the window on
our display, we can't guarantee it exists in the server yet, which will
cause BadWindow crashes if the plugin tries to use it.
-
+
It would be nice to use CreateNotify events here, but they don't get
through on all window managers, so instead we pass a client message
into out queue, after the XCreateWindow. When this message pops out
in our event handler, it will trigger the second stage of plugin
Editor instantiation, and by then the Window should be valid...*/
-
+
XClientMessageEvent event;
-
+
/*Create an atom to identify our message (only if it doesn't already exist)*/
-
+
Atom WindowActiveAtom = XInternAtom(LXVST_XDisplay, "LaunchEditor", false);
-
+
event.type = ClientMessage;
event.send_event = true;
event.window = parent_window;
event.format = 32; //Data format
event.data.l[0] = 0x0FEEDBAC; //Something we can recognize later
-
+
/*Push the event into the queue on our Display*/
-
+
XSendEvent(LXVST_XDisplay, parent_window, FALSE, NoEventMask, (XEvent*)&event);
return 0;
is now valid in the XServer and can be passed to the plugin in effEditOpen
without generating BadWindow errors when the plugin reparents itself into our
parent window*/
-
+
if(vstfx->been_activated)
return 0;
-
+
Window parent_window;
struct ERect* er;
-
+
int x_size = 1;
int y_size = 1;
-
+
parent_window = vstfx->linux_window;
-
+
/*Open the editor - Bah! we have to pass the int windowID as a void pointer - yuck
it gets cast back to an int as the parent window XID in the plugin - and we have to pass the
Display* as a long */
-
+
/**************************************************************/
/* 64Bit --- parent window is an int passed as a void* so */
/* that should be ok for 64Bit machines */
/* */
/* linuxDSP VSTs don't use the host Display* at all */
/**************************************************************/
-
+
vstfx->plugin->dispatcher (vstfx->plugin, effEditOpen, 0, (long)LXVST_XDisplay, (void*)(parent_window), 0 );
-
+
/*QUIRK - some plugins need a slight delay after opening the editor before you can
ask the window size or they might return zero - specifically discoDSP */
-
+
Glib::usleep(100000);
-
+
/*Now we can find out how big the parent window should be (and try) to resize it*/
-
+
vstfx->plugin->dispatcher (vstfx->plugin, effEditGetRect, 0, 0, &er, 0 );
x_size = er->right - er->left;
y_size = er->bottom - er->top;
-
+
vstfx->width = x_size;
vstfx->height = y_size;
-
+
XResizeWindow(LXVST_XDisplay, parent_window, x_size, y_size);
-
+
XFlush (LXVST_XDisplay);
-
+
/*Not sure if we need to map the window or if the plugin will do it for us
it should be ok because XReparentWindow generates a Map event*/
-
+
/*mark the editor as activated - mainly so that vstfx_get_XID
will know it is valid*/
vstfx->been_activated = TRUE;
-
+
pthread_cond_signal (&vstfx->window_status_change);
return 0;
}
so we don't need to lock here - if we did there would be
a deadlock anyway
*/
-
+
VSTState* p;
VSTState* prev;
-
+
for (p = vstfx_first, prev = NULL; p; prev = p, p = p->next) {
if (p == vstfx) {
if (prev) {
set_tooltip (start_to_playhead_button, _("Set range start from playhead location"));
set_tooltip (end_to_playhead_button, _("Set range end from playhead location"));
-
+
} else {
set_tooltip (remove_button, _("Remove this marker"));
loc.sort (LocationSortByStart ());
LocationEditRow* erow = manage (new LocationEditRow (_session, location));
-
+
erow->set_clock_group (*_clock_group);
erow->remove_requested.connect (sigc::mem_fun (*this, &LocationUI::location_remove_requested));
if (!p) {
return ARDOUR_UI::instance()->secondary_clock->mode();
}
-
+
return (AudioClock::Mode) string_2_enum (p->value (), AudioClock::Mode);
}
LXVSTPluginUI::~LXVSTPluginUI ()
{
- _screen_update_connection.disconnect();
-
+ _screen_update_connection.disconnect();
+
// plugin destructor destroys the custom GUI, via the vstfx engine,
// and then our PluginUIWindow does the rest
}
/* We could maybe use this to resize the plugin GTK parent window
if required
*/
-
+
if (!_vst->state()->want_resize) {
return;
}
int new_height = _vst->state()->height;
int new_width = _vst->state()->width;
-
+
void* gtk_parent_window = _vst->state()->extra_data;
-
+
if (gtk_parent_window) {
((Gtk::Window*) gtk_parent_window)->resize (new_width, new_height + LXVST_H_FIDDLE);
}
-
+
_vst->state()->want_resize = 0;
}
int
LXVSTPluginUI::get_preferred_height ()
-{
+{
/* XXX: FIXME */
-
+
/* We have to return the required height of the plugin UI window + a fiddle factor
because we can't know how big the preset menu bar is until the window is realised
and we can't realise it until we have told it how big we would like it to be
which we can't do until it is realised etc
*/
- // May not be 40 for all screen res etc
+ // May not be 40 for all screen res etc
return VSTPluginUI::get_preferred_height () + LXVST_H_FIDDLE;
}
LXVSTPluginUI::package (Gtk::Window& win)
{
VSTPluginUI::package (win);
-
+
/* Map the UI start and stop updating events to 'Map' events on the Window */
-
+
win.signal_map_event().connect (mem_fun (*this, &LXVSTPluginUI::start_updating));
win.signal_unmap_event().connect (mem_fun (*this, &LXVSTPluginUI::stop_updating));
created and we get bad Window errors when trying
to embed it in the GTK UI
*/
-
+
pthread_mutex_lock (&(_vst->state()->lock));
-
+
/* The Window may be scheduled for creation
but not actually created by the gui_event_loop yet -
spin here until it has been activated. Possible
should not be called here if the window doesn't
exist or will never exist
*/
-
+
while (!(_vst->state()->been_activated)) {
Glib::usleep (1000);
}
-
+
int const id = _vst->state()->xid;
-
+
pthread_mutex_unlock (&(_vst->state()->lock));
-
+
/* Finally it might be safe to return the ID -
problems will arise if we return either a zero ID
and GTK tries to socket it or if we return an ID
which hasn't yet become real to the server
*/
-
+
return id;
}
gtk_xerror_handler (Display*, XErrorEvent*)
{
std::cerr << "** ERROR ** LXVSTPluginUI : Trapped an X Window System Error" << std::endl;
-
+
return 0;
}
~LXVSTPluginUI ();
int get_preferred_height ();
-
+
bool start_updating (GdkEventAny *);
bool stop_updating (GdkEventAny *);
error << _("Could not complete pre-GUI initialization") << endmsg;
exit (1);
}
-
+
try {
ui = new ARDOUR_UI (&argc, &argv, localedir.c_str());
} catch (failed_constructor& err) {
MainClock (const std::string& clock_name, const std::string& widget_name, bool primary);
private:
-
+
// Editor *_editor;
void build_ops_menu ();
group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple (unit_position, 0));
#ifdef CANVAS_DEBUG
group->name = string_compose ("Marker::group for %1", annotation);
-#endif
+#endif
_name_background = new ArdourCanvas::Rectangle (group);
#ifdef CANVAS_DEBUG
_name_background->name = string_compose ("Marker::_name_background for %1", annotation);
-#endif
+#endif
/* adjust to properly locate the tip */
layout->set_font_description (name_font);
Gtkmm2ext::get_ink_pixel_size (layout, width, name_height);
-
+
_name_item = new ArdourCanvas::Text (group);
CANVAS_DEBUG_NAME (_name_item, string_compose ("ArdourMarker::_name_item for %1", annotation));
_name_item->set_font_description (name_font);
group->set_data ("marker", this);
mark->set_data ("marker", this);
-
+
if (handle_events) {
group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this));
}
if (label_on_left ()) {
_name_item->set_x_position (-name_width);
}
-
+
_name_item->clamp_width (name_width);
_name_item->set (_name);
-
+
if (label_on_left ()) {
/* adjust right edge of background to fit text */
_name_background->set_x0 (_name_item->position().x - padding);
void update_button_box ();
void update_name_box ();
void name_changed ();
-
+
void route_color_changed ();
bool _suspend_menu_callbacks;
vpacker->pack_start (capture_all_button);
capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
-
+
vpacker->pack_start (capture_filter_button);
capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
-
+
vpacker->pack_start (capture_force_button);
capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
vpacker->pack_start (capture_mask_box);
-
+
capture_controls = manage (new HBox);
capture_controls->set_spacing (6);
vpacker->pack_start (playback_all_button);
playback_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), AllChannels));
-
+
vpacker->pack_start (playback_filter_button);
playback_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), FilterChannels));
-
+
vpacker->pack_start (playback_force_button);
playback_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), ForceChannel));
track->set_capture_channel_mask (~track->get_capture_channel_mask());
}
}
-
+
void
MidiChannelSelectorWindow::set_playback_selected_channels (uint16_t mask)
{
playback_buttons[i]->set_active ((1<<i) & mask);
}
break;
-
+
case ForceChannel:
/* only set the lowest set channel in the mask as active */
for (uint16_t i = 0; i < 16; i++) {
capture_buttons[i]->set_active ((1<<i) & mask);
}
break;
-
+
case ForceChannel:
/* only set the lowest set channel in the mask as active */
for (uint16_t i = 0; i < 16; i++) {
if (playback_buttons.empty()) {
Gtkmm2ext::container_clear (playback_mask_box);
-
+
ToggleButton* tb;
RadioButtonGroup group;
-
+
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
tb->set_sensitive (false);
}
}
-
+
if (mode != ForceChannel) {
set_playback_selected_channels (track->get_playback_channel_mask());
}
if (capture_buttons.empty()) {
Gtkmm2ext::container_clear (capture_mask_box);
-
+
ToggleButton* tb;
RadioButtonGroup group;
-
+
for (uint32_t n = 0; n < 16; ++n) {
char buf[3];
snprintf (buf, sizeof (buf), "%d", n+1);
tb->set_sensitive (false);
}
}
-
+
if (mode != ForceChannel) {
set_capture_selected_channels (track->get_capture_channel_mask());
}
so we take action only if the button is active (i.e it is the one
just clicked on)
*/
-
+
switch (mode) {
case AllChannels:
if (capture_all_button.get_active()) {
so we take action only if the button is active (i.e it is the one
just clicked on)
*/
-
+
switch (mode) {
case AllChannels:
if (playback_all_button.get_active()) {
char color_normal[8];
char color_active[8];
-
+
snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
snprintf(color_active, 8, "#%x", new_channel_colors[n]);
MidiExportDialog::get_path () const
{
return file_chooser.get_filename ();
-
+
}
if (note_length_map.empty()) {
fill_note_length_map ();
}
-
+
/* We do not handle nested sources/regions. Caller should have tackled this */
if (r->max_source_level() > 0) {
note_length_model = ListStore::create (note_length_columns);
TreeModel::Row row;
-
+
for (std::map<int,string>::iterator i = note_length_map.begin(); i != note_length_map.end(); ++i) {
row = *(note_length_model->append());
row[note_length_columns.ticks] = i->first;
buttons.attach (sound_notes_button, 0, 1, 0, 1);
Glib::RefPtr<Gtk::Action> act = ActionManager::get_action ("Editor", "sound-midi-notes");
if (act) {
- gtk_activatable_set_related_action (GTK_ACTIVATABLE (sound_notes_button.gobj()), act->gobj());
+ gtk_activatable_set_related_action (GTK_ACTIVATABLE (sound_notes_button.gobj()), act->gobj());
}
view.show ();
if (!view.get_path_at_pos (ev->x, ev->y, path, col, cellx, celly)) {
return false;
}
-
+
if (view.get_selection()->count_selected_rows() == 0) {
was_selected = false;
} else if (view.get_selection()->is_selected (path)) {
} else {
was_selected = false;
}
-
+
int colnum = GPOINTER_TO_UINT (col->get_data (X_("colnum")));
switch (colnum) {
if (was_selected) {
/* use selection */
-
+
TreeView::Selection::ListHandle_Path rows = view.get_selection()->get_selected_rows ();
TreeModel::iterator iter;
boost::shared_ptr<NoteType> note;
-
+
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
previous_selection.push_back (*i);
if ((iter = model->get_iter (*i))) {
-
- note = (*iter)[columns._note];
-
+
+ note = (*iter)[columns._note];
+
switch (prop) {
case MidiModel::NoteDiffCommand::StartTime:
if (note->time() + fdelta >= 0) {
} else {
/* just this row */
-
+
TreeModel::iterator iter;
iter = model->get_iter (path);
if (iter) {
boost::shared_ptr<NoteType> note = (*iter)[columns._note];
-
+
switch (prop) {
case MidiModel::NoteDiffCommand::StartTime:
if (note->time() + fdelta >= 0) {
m->apply_command (*_session, cmd);
/* reset selection to be as it was before we rebuilt */
-
+
for (vector<TreeModel::Path>::iterator i = previous_selection.begin(); i != previous_selection.end(); ++i) {
view.get_selection()->select (*i);
}
ret = true;
}
break;
-
+
case GDK_Up:
case GDK_uparrow:
if (edit_column > 0) {
case GDK_Escape:
stop_editing (true);
break;
-
+
}
return ret;
ret = true;
}
break;
-
+
case GDK_r:
if (_session && Gtkmm2ext::Keyboard::modifier_state_contains (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
_session->redo (1);
if (sscanf (text.c_str(), "%lf", &fval) == 1) {
/* numeric value entered */
-
+
if (text.find ('.') == string::npos && text.find (',') == string::npos) {
/* integral => units are ticks */
fval = fval / BBT_Time::ticks_per_beat;
* displaying numeric value ... use new value
* from note length map, and convert to beats.
*/
-
+
for (x = note_length_map.begin(); x != note_length_map.end(); ++x) {
if (x->second == text) {
break;
}
}
-
+
if (x != note_length_map.end()) {
fval = x->first / BBT_Time::ticks_per_beat;
}
fval = -1.0;
if (text != x->second) {
-
+
/* get ticks for the newly selected
* note length
*/
break;
}
}
-
+
if (x != note_length_map.end()) {
/* convert to beats */
fval = (double) x->first / BBT_Time::ticks_per_beat;
MidiModel::NoteDiffCommand* cmd = m->new_note_diff_command (opname);
TreeView::Selection::ListHandle_Path rows = view.get_selection()->get_selected_rows ();
-
+
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
if ((iter = model->get_iter (*i))) {
- note = (*iter)[columns._note];
-
+ note = (*iter)[columns._note];
+
switch (prop) {
case MidiModel::NoteDiffCommand::Velocity:
cmd->change (note, prop, (uint8_t) (note->velocity() + idelta));
/* model has been redisplayed by now */
/* keep selected row(s), move cursor there, don't continue editing */
-
+
TreeViewColumn* col = view.get_column (edit_column);
view.set_cursor (edit_path, *col, 0);
const Evoral::Beats dur = (*i)->end_time() - (*i)->time();
bbt.beats = dur.get_beats ();
bbt.ticks = dur.get_ticks ();
-
+
uint64_t len_ticks = (*i)->length().to_ticks();
std::map<int,string>::iterator x = note_length_map.find (len_ticks);
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
if ((iter = model->get_iter (*i))) {
- note = (*iter)[columns._note];
+ note = (*iter)[columns._note];
player->add (note);
}
}
NoteBase::NoteBaseDeleted.connect (note_delete_connection, MISSING_INVALIDATOR,
boost::bind (&MidiRegionView::maybe_remove_deleted_note_from_selection, this, _1),
gui_context());
-
+
if (wfd) {
Glib::Threads::Mutex::Lock lm(midi_region()->midi_source(0)->mutex());
midi_region()->midi_source(0)->load_model(lm);
}
if (_mouse_state != SelectTouchDragging) {
-
+
_pressed_button = ev->button;
_mouse_state = Pressed;
-
+
return true;
}
grid snap without it overlapping this one.
*/
beats -= Evoral::Beats::tick();
-
+
create_note_at (editor.pixel_to_sample (event_x), event_y, beats, true);
break;
case Pressed:
if (_pressed_button == 1) {
-
+
MouseMode m = editor.current_mouse_mode();
-
+
if (m == MouseDraw || (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()))) {
editor.drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (&editor), group, this), (GdkEvent *) ev);
_mouse_state = AddDragging;
case AddDragging:
editor.drags()->motion_handler ((GdkEvent *) ev, false);
break;
-
+
case SelectTouchDragging:
return false;
*/
bool unmodified = Keyboard::no_modifier_keys_pressed (ev);
-
+
if (unmodified && (ev->keyval == GDK_Alt_L || ev->keyval == GDK_Alt_R)) {
_mouse_state = SelectTouchDragging;
return true;
if (_selection.empty()) {
return;
}
-
+
/* pick a note somewhat at random (since Selection is a set<>) to
* provide the "current" velocity for the dialog.
*/
bool visible;
if (note_in_region_range (note, visible)) {
-
+
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
cne->validate ();
}
} else {
-
+
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
cne->validate ();
cne->hide ();
if (!empty_when_starting) {
for (Events::iterator i = _events.begin(); i != _events.end(); ) {
if (!(*i)->valid ()) {
-
+
for (vector<GhostRegion*>::iterator j = ghosts.begin(); j != ghosts.end(); ++j) {
MidiGhostRegion* gr = dynamic_cast<MidiGhostRegion*> (*j);
if (gr) {
gr->remove_note (*i);
}
}
-
+
delete *i;
i = _events.erase (i);
-
+
} else {
++i;
}
for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) {
const boost::shared_ptr<const Evoral::MIDIEvent<Evoral::Beats> > mev =
boost::static_pointer_cast<const Evoral::MIDIEvent<Evoral::Beats> > (*i);
-
+
if (mev) {
if (mev->is_spp() || mev->is_mtc_quarter() || mev->is_mtc_full()) {
have_periodic_system_messages = true;
}
}
}
-
+
if (have_periodic_system_messages) {
double zoom = trackview.editor().get_current_zoom (); // frames per pixel
-
+
/* get an approximate value for the number of samples per video frame */
-
+
double video_frame = trackview.session()->frame_rate() * (1.0/30);
-
+
/* if we are zoomed out beyond than the cutoff (i.e. more
* frames per pixel than frames per 4 video frames), don't
* show periodic sysex messages.
*/
-
+
if (zoom > (video_frame*4)) {
display_periodic_messages = false;
}
{
return pc->time() <= time && pc->channel() == channel;
}
-
+
void
MidiRegionView::get_patch_key_at (Evoral::Beats time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const
{
uint8_t high_note = 0;
MidiModel::Notes& notes (_model->notes());
_optimization_iterator = _events.begin();
-
+
if (extend && !have_selection) {
extend = false;
}
/* scan existing selection to get note range */
-
+
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
if ((*i)->note()->note() < low_note) {
low_note = (*i)->note()->note();
high_note = (*i)->note()->note();
}
}
-
+
if (!add) {
clear_selection ();
start_note_diff_command (_("move notes"));
for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ++i) {
-
+
framepos_t new_frames = source_beats_to_absolute_frames ((*i)->note()->time()) + dt;
Evoral::Beats new_time = absolute_frames_to_source_beats (new_frames);
/* Get the new x position for this resize, which is in pixels relative
* to the region position.
*/
-
+
double current_x;
if (at_front) {
_note_group->canvas_to_item (x, y);
PublicEditor& editor = trackview.editor ();
-
+
framepos_t const unsnapped_frame = editor.pixel_to_sample (x);
framecnt_t grid_frames;
framepos_t const f = snap_frame_to_grid_underneath (unsnapped_frame, grid_frames);
MidiRegionView::snap_frame_to_grid_underneath (framepos_t p, framecnt_t& grid_frames) const
{
PublicEditor& editor = trackview.editor ();
-
+
const Evoral::Beats grid_beats = get_grid_beats(p);
grid_frames = region_beats_to_region_frames (grid_beats);
Selection selection () const {
return _selection;
}
-
+
void selection_as_notelist (Notes& selected, bool allow_all_if_none_selected = false);
void enable_display (bool);
void clear_selection (bool signal = true) { clear_selection_except (0, signal); }
ARDOUR::InstrumentInfo& instrument_info() const;
-
+
protected:
void region_resized (const PBD::PropertyChange&);
uint8_t _current_range_min;
uint8_t _current_range_max;
-
+
typedef std::list<NoteBase*> Events;
typedef std::vector< boost::shared_ptr<PatchChange> > PatchChanges;
typedef std::vector< boost::shared_ptr<SysEx> > SysExes;
bool _mouse_changed_selection;
framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
-
+
PBD::ScopedConnection _mouse_mode_connection;
boost::shared_ptr<CursorContext> _press_cursor_ctx;
can be put below ghost regions from MIDI underlays
*/
_note_lines = new ArdourCanvas::LineSet (_canvas_group, ArdourCanvas::LineSet::Horizontal);
-
+
_note_lines->Event.connect(
sigc::bind(sigc::mem_fun(_trackview.editor(),
&PublicEditor::canvas_stream_view_event),
double h = y - prev_y;
double mid = y + (h/2.0);
-
+
if (height > 1.0) { // XXX ? should that not be h >= 1 ?
_note_lines->add (mid, h, color);
}
MidiStreamView::resume_updates ()
{
_updates_suspended = false;
-
+
draw_note_lines ();
apply_note_range_to_regions ();
MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
{
_route = rt;
-
+
_view = new MidiStreamView (*this);
if (is_track ()) {
_channel_status_box.set_homogeneous (false);
_channel_status_box.set_spacing (4);
-
+
ArdourButton *channel_selector_button = manage (new ArdourButton(_("Chns")));
channel_selector_button->set_name ("route button");
set_tooltip (channel_selector_button, _("Click to edit channel settings"));
-
+
// Insert expanding space labels to get full width justification
_channel_status_box.pack_start (_playback_channel_status, false, false, 2);
_channel_status_box.pack_start (*Gtk::manage(new Gtk::Label(" ")), true, true);
_channel_status_box.show_all ();
channel_selector_button->signal_clicked.connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_channel_selector));
-
+
_midi_controls_box.pack_start (_channel_status_box, false, false, 10);
if (!patch_manager.all_models().empty()) {
} else {
_midi_controls_box.hide();
}
-
+
if (h >= KEYBOARD_MIN_HEIGHT) {
if (is_track() && _range_scroomer) {
_range_scroomer->show();
if (color_mode_menu) {
items.push_back (MenuElem (_("Color Mode"), *color_mode_menu));
}
-
+
items.push_back (SeparatorElem ());
}
l != device_names->controls().end(); ++l) {
boost::shared_ptr<ControlNameList> name_list = l->second;
Menu* ctl_menu = NULL;
-
+
for (ControlNameList::Controls::const_iterator c = name_list->controls().begin();
c != name_list->controls().end();) {
const uint16_t ctl = c->second->number();
/* Create a new submenu */
ctl_menu = manage (new Menu);
}
-
+
MenuList& ctl_items (ctl_menu->items());
if (chn_cnt > 1) {
add_multi_channel_controller_item(ctl_items, ctl, c->second->name());
if (_color_mode == mode && !force) {
return;
}
-
+
if (_channel_selector) {
if (mode == ChannelColors) {
_channel_selector->set_channel_colors(NoteBase::midi_channel_colors);
_channel_selector->set_default_channel_color();
}
}
-
+
_color_mode = mode;
set_gui_property ("color-mode", enum_2_string(_color_mode));
if (redisplay) {
{
string const c = _port_combo.get_active_text ();
_port_combo.clear ();
-
+
ARDOUR::PortManager::PortList pl;
ARDOUR::AudioEngine::instance()->get_ports (ARDOUR::DataType::MIDI, pl);
mp->set_trace_on (true);
traced_port = mp;
}
-
+
} else {
async->parser()->any.connect_same_thread (_parser_connection, boost::bind (&MidiTracer::tracer, this, _1, _2, _3));
}
Gtk::Label line_count_label;
Gtk::HBox line_count_box;
struct timeval _last_receipt;
-
+
bool autoscroll;
bool show_hex;
bool show_delta_time;
add_button (Stock::CANCEL, RESPONSE_CANCEL);
add_button (Stock::OK, RESPONSE_OK);
-
+
spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &MidiVelocityDialog::response), Gtk::RESPONSE_OK));
}
MixerActor::load_bindings ()
{
/* XXX move this to a better place */
-
+
bindings.set_action_map (myactions);
std::string binding_file;
{
double const arc_radius = get_height();
double r, g, b, a;
-
+
if (tab.group && tab.group->is_active()) {
ArdourCanvas::color_to_rgba (tab.color, r, g, b, a);
} else {
ArdourCanvas::color_to_rgba (UIConfiguration::instance().color ("inactive group tab"), r, g, b, a);
}
-
+
a = 1.0;
cairo_set_source_rgba (cr, r, g, b, a);
cairo_text_extents_t ext;
cairo_text_extents (cr, tab.group->name().c_str(), &ext);
-
+
ArdourCanvas::Color c = ArdourCanvas::contrasting_text_color (ArdourCanvas::rgba_to_color (r, g, b, a));
ArdourCanvas::color_to_rgba (c, r, g, b, a);
if (_mixer_owned) {
t += string_compose (_("\n%1-%2-click to toggle the width of all strips."), Keyboard::primary_modifier_name(), Keyboard::tertiary_modifier_name ());
}
-
+
width_button.set_icon (ArdourIcon::StripWidth);
set_tooltip (width_button, t);
set_tooltip (&hide_button, _("Hide this mixer strip"));
input_button_box.set_spacing(2);
-
+
input_button.set_text (_("Input"));
input_button.set_name ("mixer strip button");
input_button_box.pack_start (input_button, true, true);
meter_point_button.signal_button_press_event().connect (sigc::mem_fun (gpm, &GainMeter::meter_press), false);
meter_point_button.signal_button_release_event().connect (sigc::mem_fun (gpm, &GainMeter::meter_release), false);
-
+
hide_button.set_events (hide_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
solo_isolated_led = manage (new ArdourButton (ArdourButton::led_default_elements));
button_size_group->add_widget (*monitor_input_button);
}
}
-
+
mute_solo_table.set_homogeneous (true);
mute_solo_table.set_spacings (2);
MixerStrip::mixer_strip_enter_event (GdkEventCrossing* /*ev*/)
{
_entered_mixer_strip = this;
-
+
//although we are triggering on the "enter", to the user it will appear that it is happenin on the "leave"
//because the mixerstrip control is a parent that encompasses the strip
deselect_all_processors();
//if we leave this mixer strip we need to clear out any selections
//processor_box.processor_display.select_none(); //but this doesn't work, because it gets triggered when (for example) you open the menu or start a drag
}
-
+
return false;
}
if (group_button.get_parent()) {
bottom_button_table.remove (group_button);
}
-
+
RouteUI::set_route (rt);
/* ProcessorBox needs access to _route so that it can read
/* unpack these from the parent and stuff them into our own
table
*/
-
+
if (gpm.peak_display.get_parent()) {
gpm.peak_display.get_parent()->remove (gpm.peak_display);
}
}
gpm.set_type (rt->meter_type());
-
+
mute_solo_table.attach (gpm.gain_display,0,1,1,2, EXPAND|FILL, EXPAND);
mute_solo_table.attach (gpm.peak_display,1,2,1,2, EXPAND|FILL, EXPAND);
edit_output_configuration ();
break;
}
-
+
return false;
}
)
);
}
-
+
citems.push_back (SeparatorElem());
citems.push_back (MenuElem (_("Routing Grid"), sigc::mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::edit_output_configuration)));
citems.push_back (SeparatorElem());
uint32_t const n_with_separator = citems.size ();
-
+
input_menu_bundles.clear ();
ARDOUR::BundleList current = _route->input()->bundles_connected ();
ostringstream tooltip;
char * tooltip_cstr;
-
+
//to avoid confusion, the button caption should only show connections that match the datatype of the track
DataType dt = DataType::AUDIO;
if ( boost::dynamic_pointer_cast<MidiTrack>(route) != 0 ) {
} else {
port = route->output()->nth (io_index);
}
-
+
port_connections.clear ();
port->get_connections(port_connections);
if (!selection.selected (rtav)) {
selection.set (rtav);
}
-
+
items.push_front (SeparatorElem());
items.push_front (MenuElem (_("Remove"), sigc::mem_fun(PublicEditor::instance(), &PublicEditor::remove_tracks)));
}
/* do not allow rename if the track is record-enabled */
rename_menu_item->set_sensitive (!_route->record_enabled());
route_ops_menu->popup (1, ev->time);
-
+
return true;
}
global_frame.set_name ("MixerStripFrame");
}
global_frame.queue_draw ();
-
+
// if (!yn)
// processor_box.deselect_all_processors();
}
if (ev->button != 1) {
return false;
}
-
+
if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier | Keyboard::TertiaryModifier)) && _mixer_owned) {
switch (_width) {
case Wide:
case MeterInput:
return _("In");
break;
-
+
case MeterPreFader:
return _("Pre");
break;
-
+
case MeterPostFader:
return _("Post");
break;
-
+
case MeterOutput:
return _("Out");
break;
-
+
case MeterCustom:
default:
return _("Custom");
case MeterInput:
return S_("Meter|In");
break;
-
+
case MeterPreFader:
return S_("Meter|Pr");
break;
-
+
case MeterPostFader:
return S_("Meter|Po");
break;
-
+
case MeterOutput:
return S_("Meter|O");
break;
-
+
case MeterCustom:
default:
return S_("Meter|C");
if (_route && _route->is_master ()) {
return boost::optional<bool> (false);
}
-
+
return boost::optional<bool> ();
}
RadioMenuItem::Group& group, string const & name, MeterPoint point)
{
using namespace Menu_Helpers;
-
+
items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (*this, &MixerStrip::set_meter_point), point)));
RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
i->set_active (_route->meter_point() == point);
RadioMenuItem::Group& group, string const & name, MeterType type)
{
using namespace Menu_Helpers;
-
+
items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (*this, &MixerStrip::set_meter_type), type)));
RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
i->set_active (_route->meter_type() == type);
ms->parameter_changed (X_("mixer-element-visibility"));
}
}
-
+
/* force focus into main area */
scroller_base.grab_focus ();
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
boost::shared_ptr<Route> route = (*x);
-
+
if (route->is_auditioner()) {
continue;
}
-
+
if (route->is_monitor()) {
-
+
if (!_monitor_section) {
_monitor_section = new MonitorSection (_session);
-
+
XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section"));
if (mnode) {
_monitor_section->tearoff().set_state (*mnode);
}
}
-
+
out_packer.pack_end (_monitor_section->tearoff(), false, false);
_monitor_section->set_session (_session);
_monitor_section->tearoff().show_all ();
-
+
route->DropReferences.connect (*this, invalidator(*this), boost::bind (&Mixer_UI::monitor_section_going_away, this), gui_context());
-
+
/* no regular strip shown for control out */
-
+
continue;
}
-
+
strip = new MixerStrip (*this, _session, route);
strips.push_back (strip);
UIConfiguration::instance().get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide;
-
+
if (strip->width_owner() != strip) {
strip->set_width_enum (_strip_width, this);
}
-
+
show_strip (strip);
-
+
TreeModel::Row row = *(track_model->insert(insert_iter));
row[track_columns.text] = route->name();
row[track_columns.visible] = strip->route()->is_master() ? true : strip->marked_for_display();
if (!from_scratch) {
_selection.add (strip);
}
-
+
route->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::strip_property_changed, this, _1, strip), gui_context());
-
+
strip->WidthChanged.connect (sigc::mem_fun(*this, &Mixer_UI::strip_width_changed));
strip->signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::strip_button_release_event), strip));
}
no_track_list_redisplay = false;
track_display.set_model (track_model);
-
+
sync_order_keys_from_treeview ();
redisplay_track_list ();
}
TreeModel::Children rows = track_model->children();
TreeModel::Children::iterator ri;
list<MixerStrip *>::iterator i;
-
+
if ((i = find (strips.begin(), strips.end(), strip)) != strips.end()) {
strips.erase (i);
}
-
+
for (ri = rows.begin(); ri != rows.end(); ++ri) {
if ((*ri)[track_columns.strip] == strip) {
PBD::Unwinder<bool> uw (_route_deletion_in_progress, true);
}
TreeModel::Children rows = track_model->children();
-
+
if (rows.empty()) {
return;
}
for (ri = rows.begin(); ri != rows.end(); ++ri) {
/* skip two special values */
-
+
if (rid == Route::MasterBusRemoteControlID) {
rid++;
}
-
+
if (rid == Route::MonitorBusRemoteControlID) {
rid++;
}
bool visible = (*ri)[track_columns.visible];
if (!route->is_master() && !route->is_monitor()) {
-
+
uint32_t new_rid = (visible ? rid : invisible_key--);
-
+
if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
+ route->set_remote_control_id_explicit (new_rid);
rid_change = true;
}
-
+
if (visible) {
rid++;
}
}
TreeModel::Children rows = track_model->children();
-
+
if (rows.empty()) {
return;
}
uint32_t new_rid = (visible ? rid : invisible_key--);
if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
+ route->set_remote_control_id_explicit (new_rid);
rid_change = true;
}
-
+
if (visible) {
rid++;
}
neworder.assign (sorted_routes.size(), 0);
uint32_t n = 0;
-
+
for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
neworder[n] = sr->old_display_order;
_following_editor_selection = true;
_selection.block_routes_changed (true);
-
+
TrackSelection& s (PublicEditor::instance().get_selection().tracks);
_selection.clear_routes ();
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
if (!_selection.selected(strip)) {
-
+
/* extend selection */
-
+
vector<MixerStrip*> tmp;
bool accumulate = false;
bool found_another = false;
-
+
tmp.push_back (strip);
for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
{
Unwinder<bool> uw (no_track_list_redisplay, true);
-
+
for (i = rows.begin(); i != rows.end(); ++i) {
MixerStrip *strip = (*i)[track_columns.strip];
(*i)[track_columns.visible] = strip->marked_for_display ();
}
-
+
/* force route order keys catch up with visibility changes
*/
-
+
sync_order_keys_from_treeview ();
}
{
Unwinder<bool> uw (no_track_list_redisplay, true);
-
+
for (i = rows.begin(); i != rows.end(); ++i) {
-
+
TreeModel::Row row = (*i);
MixerStrip* strip = row[track_columns.strip];
-
+
if (strip == 0) {
continue;
}
-
+
if (strip->route()->is_master() || strip->route()->is_monitor()) {
continue;
}
-
+
(*i)[track_columns.visible] = yn;
}
}
{
Unwinder<bool> uw (no_track_list_redisplay, true);
-
+
for (i = rows.begin(); i != rows.end(); ++i) {
TreeModel::Row row = (*i);
MixerStrip* strip = row[track_columns.strip];
-
+
if (strip == 0) {
continue;
}
-
+
if (strip->route()->is_master() || strip->route()->is_monitor()) {
continue;
}
-
+
boost::shared_ptr<AudioTrack> at = strip->audio_track();
boost::shared_ptr<MidiTrack> mt = strip->midi_track();
-
+
switch (tracks) {
case 0:
(*i)[track_columns.visible] = yn;
break;
-
+
case 1:
if (at) { /* track */
(*i)[track_columns.visible] = yn;
}
break;
-
+
case 2:
if (!at && !mt) { /* bus */
(*i)[track_columns.visible] = yn;
{
TreeModel::Children rows = track_model->children();
TreeModel::Children::iterator i;
-
+
if (no_track_list_redisplay) {
return;
}
track_model->clear ();
add_strips (copy);
}
-
+
_session->sync_order_keys ();
redisplay_track_list ();
}
KeyboardKey k (ev->state, ev->keyval);
-
+
if (bindings.activate (k, Bindings::Release)) {
return true;
}
{
if (_session) {
string n;
-
+
if (_session->snap_name() != _session->name()) {
n = _session->snap_name ();
} else {
if (_session->dirty ()) {
n = "*" + n;
}
-
+
WindowTitle title (n);
title += S_("Window|Mixer");
title += Glib::get_application_name ();
set_title (title.get_string());
} else {
-
+
WindowTitle title (S_("Window|Mixer"));
title += Glib::get_application_name ();
set_title (title.get_string());
onoff = !mt->input_active();
}
}
-
+
_session->set_exclusive_input_active (rl, onoff, flip_others);
}
MonitorSelectorWindow::io_name_changed (void*)
{
ENSURE_GUI_THREAD (*this, &MonitorSelectorWindow::io_name_changed, src)
-
+
std::string title;
if (!_selector.find_inputs_for_io_outputs()) {
MonoPanner::~MonoPanner ()
{
-
+
}
void
private:
PannerEditor* editor ();
boost::shared_ptr<ARDOUR::PannerShell> _panner_shell;
-
+
boost::shared_ptr<PBD::Controllable> position_control;
PBD::ScopedConnectionList panvalue_connections;
PBD::ScopedConnectionList panshell_connections;
t->set_spacings (6);
int n = 0;
-
+
t->attach (*manage (left_aligned_label (_("Left"))), 0, 1, n, n + 1);
t->attach (_left, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
-
+
t->attach (*manage (left_aligned_label (_("Right"))), 0, 1, n, n + 1);
t->attach (_right, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
if (!_panner) {
return;
}
-
+
float const v = _panner->get_controllable()->get_value();
_ignore_changes = true;
}
float const v = _right.get_value () / 100;
-
+
_ignore_changes = true;
_left.set_value (100 * (1 - v));
_panner->get_controllable()->set_value (v);
void update_editor ();
void left_changed ();
void right_changed ();
-
+
MonoPanner* _panner;
Gtk::SpinButton _left;
Gtk::SpinButton _right;
}
/* these will throw exceptions if their images cannot be found.
-
+
the default hotspot coordinates will be overridden by any
data found by Gtkmm2ext::Cursors::load_cursor_info(). the values
here from the set of cursors used by Ardour; new cursor/icon
is actually a valid value for a Gdk::Cursor - it indicates
"use the parent window's cursor"
*/
-
+
static bool is_invalid (Gdk::Cursor* c) { if (!_invalid) { create_invalid(); } return c == _invalid; }
static Gdk::Cursor* invalid_cursor() { if (!_invalid) { create_invalid(); } return _invalid; }
// Essential!! Make sure that any files used by Ardour
// will be created or opened in BINARY mode!
_fmode = O_BINARY;
-
+
GetModuleFileName (NULL, (LPSTR)szPathToProgram, (DWORD)sizeof(szPathToProgram));
argv[0] = new char[(strlen(szPathToProgram) + 1)];
if (!_note.empty ()) {
++m;
}
-
+
p->table.resize (m, 3);
p->table.attach (*wa, 1, 2, n, n + 1, FILL);
p->table.attach (*wb, 2, 3, n, n + 1, FILL | EXPAND);
-
+
maybe_add_note (p, n + 1);
}
_combo->append_text (f);
/* and option 1 is the true */
_combo->append_text (t);
-
+
_combo->signal_changed().connect (sigc::mem_fun (*this, &BoolComboOption::changed));
}
{
_combo->set_sensitive (yn);
}
-
-
+
+
FaderOption::FaderOption (string const & i, string const & n, sigc::slot<gain_t> g, sigc::slot<bool, gain_t> s)
: Option (i, n)
, _db_adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
private:
void maybe_add_note (OptionEditorPage *, int);
-
+
std::string _note;
};
private:
void selection_changed ();
-
+
sigc::slot<std::string> _get; ///< slot to get the configuration variable's value
sigc::slot<bool, std::string> _set; ///< slot to set the configuration variable's value
Gtk::FileChooserButton _file_chooser;
void add_option (std::string const &, OptionEditorComponent *);
void add_page (std::string const &, Gtk::Widget& page_widget);
-
+
void set_current_page (std::string const &);
protected:
virtual void parameter_changed (std::string const &);
-
+
PBD::Configuration* _config;
private:
private:
bool _dragging;
};
-
+
/** Parent class for some panner UI classes that contains some common code */
class PannerInterface : public Gtk::DrawingArea, public PBD::Destructible
virtual void set_tooltip () = 0;
void value_change ();
-
+
bool on_enter_notify_event (GdkEventCrossing *);
bool on_leave_notify_event (GdkEventCrossing *);
bool on_key_release_event (GdkEventKey *);
UIConfiguration::instance().color_mod ("midi patch change fill", "midi patch change fill"),
ArdourCanvas::Duple (x, y),
true);
-
+
CANVAS_DEBUG_NAME (_flag, text);
_flag->Event.connect (sigc::mem_fun (*this, &PatchChange::event_handler));
++bank) {
Glib::RefPtr<Glib::Regex> underscores = Glib::Regex::create("_");
std::string replacement(" ");
-
+
Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
-
+
const PatchNameList& patches = (*bank)->patch_name_list();
Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
-
+
for (PatchNameList::const_iterator patch = patches.begin();
patch != patches.end();
++patch) {
const PatchNameList& patches = patch_banks.front()->patch_name_list();
Gtk::Menu::MenuList& patch_menus = _popup.items();
-
+
for (PatchNameList::const_iterator patch = patches.begin();
patch != patches.end();
++patch) {
std::string name = (*patch)->name();
boost::replace_all (name, "_", " ");
-
+
patch_menus.push_back (
Gtk::Menu_Helpers::MenuElem (
name,
{
/* XXX: icky dcast */
Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor());
-
+
if (!e->internal_editing()) {
return false;
}
_region.edit_patch_change (this);
return true;
-
+
} else if (ev->button.button == 1) {
e->drags()->set (new PatchChangeDrag (e, this, &_region), ev);
return true;
int r = 0;
if (_time_converter) {
-
+
l = manage (left_aligned_label (_("Time")));
t->attach (*l, 0, 1, r, r + 1);
t->attach (_time, 1, 2, r, r + 1);
t->attach (*l, 0, 1, r, r + 1);
t->attach (_patch_combo, 1, 2, r, r + 1);
++r;
-
+
_patch_combo.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::patch_combo_changed));
l = manage (left_aligned_label (_("Channel")));
PatchChangeDialog::set_active_bank_combo ()
{
_current_patch_bank.reset ();
-
+
boost::shared_ptr<MIDI::Name::ChannelNameSet> cns = _info.get_patches (_channel.get_value_as_int() - 1);
if (!cns) {
if (_ignore_signals) {
return;
}
-
+
_current_patch_bank.reset ();
boost::shared_ptr<MIDI::Name::ChannelNameSet> cns = _info.get_patches (_channel.get_value_as_int() - 1);
_ignore_signals = false;
return;
}
-
+
const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
string n = (*j)->name ();
_ignore_signals = true;
_patch_combo.set_active (-1);
_ignore_signals = false;
-}
+}
/** Set _program from the current state of _patch_combo */
void
if (_dragging) {
if ( false /*editor().current_mouse_mode() == Editing::MouseRange*/ ) { //ToDo: fix this. this mode is buggy, and of questionable utility anyway
-
+
/* select note range */
if (Keyboard::no_modifiers_active (ev->state)) {
if (_clicked_note != NO_MIDI_NOTE && _clicked_note != note) {
_active_notes[_clicked_note] = false;
send_note_off(_clicked_note);
-
+
_clicked_note = note;
-
+
if (!_active_notes[note]) {
_active_notes[note] = true;
send_note_on(note);
} else if (ev->button == 1 && note >= 0 && note < 128) {
add_modal_grab();
_dragging = true;
-
+
if (!_active_notes[note]) {
_active_notes[note] = true;
_clicked_note = note;
send_note_on(note);
-
+
invalidate_note_range(note, note);
} else {
reset_clicked_note(note);
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
ExtendNoteSelection (note); // EMIT SIGNAL
}
-
+
} else {
if (_dragging) {
curl_global_init (CURL_GLOBAL_NOTHING);
c = curl_easy_init ();
-
+
curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, curl_write_data);
curl_easy_setopt (c, CURLOPT_WRITEDATA, &return_str);
char errbuf[CURL_ERROR_SIZE];
std::cerr << "Announcement string is too long (probably behind a proxy)." << std::endl;
} else {
std::cerr << "Announcement is: " << return_str << std::endl;
-
+
//write announcements to local file, even if the
//announcement is empty
for (TrackPlaylistMap::iterator x = trpl_map.begin(); x != trpl_map.end(); ++x) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (_session->route_by_id (x->first));
-
+
/* legacy sessions stored the diskstream ID as the original
* playlist owner. so try there instead.
*/
{
/* Allocate some thread-local buffers so that Plugin::connect_and_run can use them */
ARDOUR_UI::instance()->get_process_buffers ();
-
+
uint32_t inputs = _plugin->get_info()->n_inputs.n_audio();
uint32_t outputs = _plugin->get_info()->n_outputs.n_audio();
: ArdourDialog (_("Plugin Manager"), true, false)
, filter_button (Stock::CLEAR)
, manager (mgr)
-
+
{
set_name ("PluginSelectorWindow");
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
newrow[plugin_columns.audio_ins] = buf;
snprintf (buf, sizeof(buf), "%d", (*i)->n_inputs.n_midi());
newrow[plugin_columns.midi_ins] = buf;
-
+
snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_audio());
newrow[plugin_columns.audio_outs] = buf;
snprintf (buf, sizeof(buf), "%d", (*i)->n_outputs.n_midi());
case ARDOUR::Windows_VST:
have_gui = create_windows_vst_editor (insert);
break;
-
+
case ARDOUR::LXVST:
have_gui = create_lxvst_editor (insert);
break;
PlugUIBase::bypass_button_release (GdkEventButton*)
{
bool view_says_bypassed = (bypass_button.active_state() != 0);
-
+
if (view_says_bypassed != insert->active()) {
if (view_says_bypassed) {
insert->activate ();
description_expander.add(*label);
description_expander.show_all();
}
-
+
if (!description_expander.get_expanded()) {
description_expander.remove();
}
ArdourButton automation_write_all_button;
/** a button which sets all controls' automation setting to Touch */
ArdourButton automation_touch_all_button;
-
+
void set_latency_label ();
LatencyGUI* latency_gui;
sub.push_back (MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::add_channel_proxy), w, *i)));
}
}
-
+
/* Now add other ones */
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
if (!should_show (*i)) {
/* we're looking just at bundles, or our bundle has only one channel, so just offer
to disassociate all on the bundle.
*/
-
+
snprintf (buf, sizeof (buf), _("%s all"), disassociation_verb().c_str());
sub.push_back (
MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_bundle), w, dim))
);
-
+
} else if (c != 0) {
if (bc[dim].channel != -1) {
items.push_back (MenuElem (_("Flip"), sigc::mem_fun (*this, &PortMatrix::flip)));
items.back().set_sensitive (can_flip ());
-
+
_menu->popup (1, t);
}
/* Avoid a deadlock by calling this in an idle handler: see IOSelector::io_changed_proxy
for a discussion.
*/
-
+
Glib::signal_idle().connect_once (sigc::mem_fun (*this, &PortMatrix::setup_global_ports));
}
the TOP_TO_RIGHT arrangement we reverse the order of the vertical
tabs in setup_notebooks ().
*/
-
+
int n = 0;
if (d == _row_index) {
if (_arrangement == LEFT_TO_BOTTOM) {
if (!_session) {
return;
}
-
+
for (int i = 0; i < 2; ++i) {
Gtk::Notebook* notebook = row_index() == i ? &_vnotebook : &_hnotebook;
-
+
PortGroupList const * gl = ports (i);
int p = 0;
for (PortGroupList::List::const_iterator j = gl->begin(); j != gl->end(); ++j) {
PortMatrix::check_flip () const
{
/* Look for the row's port group name in the columns */
-
+
int new_column = 0;
boost::shared_ptr<const PortGroup> r = visible_ports (_row_index);
PortGroupList::List::const_iterator i = _ports[_column_index].begin();
}
/* Look for the column's port group name in the rows */
-
+
int new_row = 0;
boost::shared_ptr<const PortGroup> c = visible_ports (_column_index);
i = _ports[_row_index].begin();
(*i)->bundle,
(*i)->bundle->type_channel_to_overall (_matrix->type (), j)
);
-
+
render_channel_name (cr, background_colour (), c, x, 0, bc);
x += grid_spacing();
}
if (!_matrix->should_show (w.bundle->channel_type (i))) {
continue;
}
-
+
ARDOUR::BundleChannel const bc (w.bundle, i);
n.push_back (PortMatrixNode (ARDOUR::BundleChannel (), bc));
}
cairo_line_to (cr, _width, y);
cairo_stroke (cr);
}
-
+
/* ASSOCIATION INDICATORS and NON-CONNECTABLE INDICATORS */
/* we draw a grey square in a matrix box if the two ports that intersect at that box
*/
draw_non_connectable_indicator (cr, x, y);
}
-
+
x += grid_spacing();
}
(*i)->bundle,
(*i)->bundle->type_channel_to_overall (_matrix->type (), j)
);
-
+
render_channel_name (cr, background_colour (), c, 0, y, bc);
y += grid_spacing();
++M;
if (N == 0) {
y += grid_spacing ();
}
-
+
} else {
y += grid_spacing();
}
, _output_icon(false)
{
_vbox.show ();
-
+
_button.set_distinct_led_click (true);
_button.set_fallthrough_to_parent(true);
_button.set_led_left (true);
set<Evoral::Parameter> p = _processor->what_can_be_automated ();
for (set<Evoral::Parameter>::iterator i = p.begin(); i != p.end(); ++i) {
-
+
std::string label = _processor->describe_parameter (*i);
if (boost::dynamic_pointer_cast<Send> (_processor)) {
}
Control* c = new Control (_processor->automation_control (*i), label);
-
+
_controls.push_back (c);
if (boost::dynamic_pointer_cast<Amp> (_processor) == 0) {
items.push_back (
MenuElem (_("Show All Controls"), sigc::mem_fun (*this, &ProcessorEntry::show_all_controls))
);
-
+
items.push_back (
MenuElem (_("Hide All Controls"), sigc::mem_fun (*this, &ProcessorEntry::hide_all_controls))
);
if (!_controls.empty ()) {
items.push_back (SeparatorElem ());
}
-
+
for (list<Control*>::iterator i = _controls.begin(); i != _controls.end(); ++i) {
items.push_back (CheckMenuElem ((*i)->name ()));
Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
//c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
} else {
-
+
_slider.set_name ("ProcessorControlSlider");
_slider.set_text (_name);
_adjustment.set_step_increment (smallstep);
_adjustment.set_page_increment (largestep);
_slider.set_default_value (normal);
-
+
_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &Control::slider_adjusted));
// dup. currently timers are used :(
//c->Changed.connect (_connection, MISSING_INVALIDATOR, boost::bind (&Control::control_changed, this), gui_context ());
// yuck, do we really need to do this?
// according to c404374 this is only needed for send automation
timer_connection = Timers::rapid_connect (sigc::mem_fun (*this, &Control::control_changed));
-
+
control_changed ();
set_tooltip ();
if (_ignore_ui_adjustment) {
return;
}
-
+
boost::shared_ptr<AutomationControl> c = _control.lock ();
if (!c) {
if (c->toggled ()) {
_button.set_active (c->get_value() > 0.5);
-
+
} else {
// as long as rapid timers are used, only update the tooltip
// if the value has changed.
set_tooltip ();
}
}
-
+
_ignore_ui_adjustment = false;
}
} else {
box.hide ();
}
-
+
_visible = v;
}
if ( (op == ProcessorsDelete) && targets.empty() )
return false; //nothing to delete. return false so the editor-mixer, because the user was probably intending to delete something in the editor
-
+
switch (op) {
case ProcessorsSelectAll:
processor_display.select_all ();
default:
break;
}
-
+
return true;
}
} else if (Keyboard::is_context_menu_event (ev)) {
show_processor_menu (ev->time);
-
+
ret = true;
} else if (processor && ev->button == 1 && selected) {
if (ui_xml) {
wp->set_state (*ui_xml);
}
-
+
void* existing_ui = p->get_ui ();
if (existing_ui) {
}
boost::shared_ptr<PluginInsert> plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor);
-
+
ProcessorEntry* e = 0;
if (plugin_insert) {
e = new PluginInsertProcessorEntry (this, plugin_insert, _width);
boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
boost::shared_ptr<PortInsert> ext = boost::dynamic_pointer_cast<PortInsert> (processor);
boost::shared_ptr<UnknownProcessor> stub = boost::dynamic_pointer_cast<UnknownProcessor> (processor);
-
+
//faders and meters are not deletable, copy/paste-able, so they shouldn't be selectable
if (!send && !plugin_insert && !ext && !stub)
e->set_selectable(false);
continue;
} else if (type->value() == "intsend") {
-
+
/* aux sends are OK, but those used for
* other purposes, are not.
*/
-
+
assert (role);
if (role->value() != "Aux") {
Send* s = new Send (*_session, _route->pannable(), _route->mute_master());
IOProcessor::prepare_for_reset (n, s->name());
-
+
if (s->set_state (n, Stateful::loading_state_version)) {
delete s;
return;
XMLNode n (**niter);
PortInsert* pi = new PortInsert (*_session, _route->pannable (), _route->mute_master ());
-
+
IOProcessor::prepare_for_reset (n, pi->name());
-
+
if (pi->set_state (n, Stateful::loading_state_version)) {
return;
}
-
+
p.reset (pi);
} else {
}
GUIObjectState& st = _parent_strip->gui_object_state ();
-
+
XMLNode* strip = st.get_or_add_node (_parent_strip->state_id ());
assert (strip);
return st.get_or_add_node (strip, entry->state_id());
if (!create) {
return 0;
}
-
+
is_custom = want_custom;
_window = _processor_box->get_editor_window (p, is_custom);
bool is_selectable() const {return _selectable;}
void set_selectable(bool s) { _selectable = s; }
-
+
enum Position {
PreFader,
Fader,
std::string name () const {
return _name;
}
-
+
Gtk::Alignment box;
private:
void generic_edit_processor (boost::shared_ptr<ARDOUR::Processor>);
void update_gui_object_state (ProcessorEntry *);
-
+
sigc::signal<void,boost::shared_ptr<ARDOUR::Processor> > ProcessorSelected;
sigc::signal<void,boost::shared_ptr<ARDOUR::Processor> > ProcessorUnselected;
virtual void set_show_measures (bool yn) = 0;
virtual bool show_measures () const = 0;
virtual void remove_tracks () = 0;
-
+
virtual Editing::MouseMode effective_mouse_mode () const = 0;
/** Import existing media */
*/
ActionManager::disable_active_actions ();
}
-
+
~MainMenuDisabler () {
ActionManager::enable_active_actions ();
}
_click_emphasis_browse_button.signal_clicked ().connect (
sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
t->attach (_click_emphasis_browse_button, 2, 3, 2, 3, FILL);
-
+
_box->pack_start (*t, false, false);
- _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
+ _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
_click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
if (_rc_config->get_click_sound ().empty() &&
{
click_chosen (_click_path_entry.get_text ());
}
-
+
void click_emphasis_browse_clicked ()
{
SoundFileChooser sfdb (_("Choose Click Emphasis"));
vector<string> presets;
/* these must match the order of the enums for BufferingPreset */
-
+
presets.push_back (_("Small sessions (4-16 tracks)"));
presets.push_back (_("Medium sessions (16-64 tracks)"));
presets.push_back (_("Large sessions (64+ tracks)"));
_box->pack_start (*h, false, false);
_buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
-
+
_playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
l = manage (new Label (_("Playback (seconds of buffering):")));
break;
}
}
-
+
void playback_changed ()
{
_rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
void protocol_status_changed (ControlProtocolInfo* cpi) {
/* find the row */
TreeModel::Children rows = _store->children();
-
+
for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
string n = ((*x)[_model.name]);
*/
_set (_visibility_group->get_state_value ());
}
-
+
OptionEditorHeading _heading;
VisibilityGroup* _visibility_group;
sigc::slot<std::string> _get;
(_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
"<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
add_option (_("Transport"), tsf);
-
+
tsf = new BoolOption (
"stop-recording-on-xrun",
_("Stop recording when an xrun occurs"),
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
);
-
+
add_option (_("Editor"), bo);
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("If enabled, popup a dialog when a new marker is created to allow its name to be set as it is created."
"\n\nYou can always rename markers by right-clicking on them"));
(sics->tip_widget(),
_("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
add_option (S_("Preferences|GUI"), sics);
-
+
/* Lock GUI timeout */
Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
_mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
_mixer_strip_visibility.add (0, X_("Output"), _("Output"));
_mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
-
+
add_option (
S_("Preferences|GUI"),
new VisibilityOption (
* are expressed using subclasses of Option. More complex UI elements are represented
* using individual classes subclassed from OptionEditorBox.
*/
-
+
/** Editor for options which are obtained from and written back to one of the .rc files. */
class RCOptionEditor : public OptionEditor
{
RegionLayeringOrderEditor::~RegionLayeringOrderEditor ()
{
-
+
}
void
if (!iter) {
return;
}
-
+
TreeModel::Row row = *iter;
RegionView* rv = row[layering_order_columns.region_view];
-
+
vector<RegionView*> eq;
editor.get_equivalent_regions (rv, eq, Properties::select.property_id);
/* XXX this should be reversible, really */
-
+
for (vector<RegionView*>::iterator i = eq.begin(); i != eq.end(); ++i) {
boost::shared_ptr<Playlist> pl = (*i)->region()->playlist();
if (pl) {
RegionLayeringOrderEditor::refill ()
{
assert (_time_axis_view);
-
+
regions_at_position = 0;
in_row_change = true;
layering_order_model->clear ();
name_highlight->set_data ("regionview", this);
name_highlight->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
}
-
+
if (frame_handle_start) {
frame_handle_start->set_data ("regionview", this);
frame_handle_start->set_data ("isleft", (void*) 1);
frame_handle_start->Event.connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_frame_handle_event), frame_handle_start, this));
frame_handle_start->raise_to_top();
}
-
+
if (frame_handle_end) {
frame_handle_end->set_data ("regionview", this);
frame_handle_end->set_data ("isleft", (void*) 0);
{
ArdourCanvas::Color f = TimeAxisViewItem::get_fill_color();
char const *modname;
-
+
if (_region->opaque()) {
modname = "opaque region base";
} else {
*/
ArdourCanvas::Item *item = get_canvas_group ();
-
+
if (item->position().x + x_delta < 0) {
x_delta = -item->position().x; /* move it to zero */
}
hbox->pack_start (*l, false, false);
hbox->pack_start (_color, false, false);
top_vbox->pack_start (*hbox, false, false);
-
+
main_vbox->pack_start (*top_vbox, false, false);
_active.set_active (_group->is_active ());
VBox* options_box = manage (new VBox);
options_box->set_spacing (6);
-
+
l = manage (new Label (_("<b>Sharing</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false ));
l->set_use_markup ();
options_box->pack_start (*l, false, true);
_route_active.signal_toggled().connect (sigc::mem_fun (*this, &RouteGroupDialog::update));
_share_color.signal_toggled().connect (sigc::mem_fun (*this, &RouteGroupDialog::update));
_share_monitoring.signal_toggled().connect (sigc::mem_fun (*this, &RouteGroupDialog::update));
-
+
gain_toggled ();
Table* table = manage (new Table (11, 4, false));
plist.add (Properties::monitoring, _share_monitoring.get_active());
_group->apply_changes (plist);
-
+
GroupTabs::set_group_color (_group, gdk_color_to_rgba (_color.get_color ()));
}
r->set_selected (true);
MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
-
+
if (ms) {
ms->CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RouteProcessorSelection::remove, this, _1), gui_context());
}
-
+
if (!_no_route_change_signal) {
RoutesChanged();
}
, old_display_order (ok)
, new_display_order (nk) {}
};
-
+
typedef std::vector<RoutePlusOrderKey> OrderKeySortedRoutes;
struct SortByNewDisplayOrder {
}
rec_enable_button->set_sensitive (_session->writable());
-
+
/* set playlist button tip to the current playlist, and make it update when it changes */
update_playlist_tip ();
track()->PlaylistChanged.connect (*this, invalidator (*this), ui_bind(&RouteTimeAxisView::update_playlist_tip, this), gui_context());
controls_table.attach (route_group_button, 4, 5, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 0, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
}
-
+
set_tooltip(*solo_button,_("Solo"));
set_tooltip(*mute_button,_("Mute"));
set_tooltip(route_group_button, _("Route Group"));
RouteTimeAxisView::~RouteTimeAxisView ()
{
cleanup_gui_properties ();
-
+
for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
delete *i;
}
/* Attach the plugin submenu. It may have previously been used elsewhere,
so it was detached above
*/
-
+
if (!subplugin_menu.items().empty()) {
items.push_back (SeparatorElem ());
items.push_back (MenuElem (_("Processor automation"), subplugin_menu));
*/
_ignore_set_layer_display = true;
-
+
layers_items.push_back (RadioMenuElem (layers_group, _("Overlaid")));
RadioMenuItem* i = dynamic_cast<RadioMenuItem*> (&layers_items.back ());
i->set_active (overlaid != 0 && stacked == 0);
i->set_active (overlaid == 0 && stacked != 0);
i->set_inconsistent (overlaid != 0 && stacked != 0);
i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked, true));
-
+
_ignore_set_layer_display = false;
items.push_back (MenuElem (_("Layers"), *layers_menu));
}
route_group_menu->detach ();
-
+
WeakRouteList r;
for (TrackSelection::iterator i = _editor.get_selection().tracks.begin(); i != _editor.get_selection().tracks.end(); ++i) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
r.push_back (rtv->route ());
}
}
-
+
if (r.empty ()) {
r.push_back (route ());
}
route_group_menu->build (r);
items.push_back (MenuElem (_("Group"), *route_group_menu->menu ()));
-
+
build_automation_action_menu (true);
items.push_back (MenuElem (_("Automation"), *automation_action_menu));
-
+
items.push_back (SeparatorElem());
-
+
int active = 0;
int inactive = 0;
TrackSelection const & s = _editor.get_selection().tracks;
vector<Command*> cmds;
playlist->rdiff (cmds);
_session->add_commands (cmds);
-
+
_session->add_command (new StatefulDiffCommand (playlist));
}
break;
-
+
case Cut:
if ((what_we_got = playlist->cut (time)) != 0) {
_editor.get_cut_buffer().add (what_we_got);
}
track()->use_playlist (pl);
-
+
RouteGroup* rg = route_group();
-
+
if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::select.property_id)) {
std::string group_string = "." + rg->name() + ".";
-
+
std::string take_name = pl->name();
std::string::size_type idx = take_name.find(group_string);
-
+
if (idx == std::string::npos)
return;
-
+
take_name = take_name.substr(idx + group_string.length()); // find the bit containing the take number / name
-
+
boost::shared_ptr<RouteList> rl (rg->route_list());
-
+
for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
if ((*i) == this->route()) {
continue;
}
std::string playlist_name = (*i)->name()+group_string+take_name;
-
+
boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track>(*i);
if (!track) {
continue;
/* Don't change playlists of frozen tracks */
continue;
}
-
+
boost::shared_ptr<Playlist> ipl = session()->playlists->by_name(playlist_name);
if (!ipl) {
// No playlist for this track for this take yet, make it
RouteGroup* rg = route_group ();
if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::select.property_id)) {
string group_string = "." + rg->name() + ".";
-
+
string take_name = track()->playlist()->name();
string::size_type idx = take_name.find(group_string);
-
+
if (idx != string::npos) {
/* find the bit containing the take number / name */
take_name = take_name.substr (idx + group_string.length());
Glib::Markup::escape_text(rg->name()),
Glib::Markup::escape_text(take_name))
);
-
+
return;
}
}
boost::shared_ptr<AutomationControl> control
= boost::dynamic_pointer_cast<AutomationControl>(processor->control(what, true));
-
+
pan->view = boost::shared_ptr<AutomationTimeAxisView>(
new AutomationTimeAxisView (_session, _route, processor, control, control->parameter (),
_editor, *this, false, parent_canvas,
processor->what_has_data (existing);
for (set<Evoral::Parameter>::iterator i = existing.begin(); i != existing.end(); ++i) {
-
+
Evoral::Parameter param (*i);
boost::shared_ptr<AutomationLine> al;
items.push_back (CheckMenuElem (name));
mitem = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
-
+
_subplugin_menu_map[*i] = mitem;
if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
if (pan->view && pan->view->set_marked_for_display (showit)) {
redraw = true;
}
-
+
if (redraw && !no_redraw) {
request_redraw ();
}
if (_ignore_set_layer_display) {
return;
}
-
+
if (apply_to_selection) {
_editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_layer_display, _1, d, false));
} else {
RouteTimeAxisView::remove_child (boost::shared_ptr<TimeAxisView> c)
{
TimeAxisView::remove_child (c);
-
+
boost::shared_ptr<AutomationTimeAxisView> a = boost::dynamic_pointer_cast<AutomationTimeAxisView> (c);
if (a) {
for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
delete input_selector;
delete output_selector;
delete _invert_menu;
-
+
send_blink_connection.disconnect ();
rec_blink_connection.disconnect ();
}
monitor_input_button->set_text (_("In"));
UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
monitor_input_button->set_no_show_all (true);
-
+
monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
monitor_disk_button->set_name ("monitor button");
monitor_disk_button->set_text (_("Disk"));
solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
-
+
monitor_input_button->set_distinct_led_click (false);
monitor_disk_button->set_distinct_led_click (false);
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
-
+
rec_enable_button->show();
rec_enable_button->set_controllable (t->rec_enable_control());
//if this is a binding action, let the ArdourButton handle it
if ( BindingProxy::is_bind_action(ev) )
return false;
-
+
multiple_mute_change = false;
if (Keyboard::is_context_menu_event (ev)) {
}
mute_menu->popup(0,ev->time);
-
+
return true;
} else {
* elements of the list we need to work
* on a copy.
*/
-
+
boost::shared_ptr<RouteList> copy (new RouteList);
*copy = *_session->get_routes ();
if (ev->button == 1) {
if (_route->route_group()) {
-
+
rl = _route->route_group()->route_list();
-
+
if (_mute_release) {
_mute_release->routes = rl;
}
boost::shared_ptr<RouteList> rl (new RouteList);
rl->push_back (_route);
-
+
if (_mute_release) {
_mute_release->routes = rl;
}
//if this is a binding action, let the ArdourButton handle it
if ( BindingProxy::is_bind_action(ev) )
return false;
-
+
multiple_solo_change = false;
if (Keyboard::is_context_menu_event (ev)) {
if (ev->button == 1) {
if (_route->route_group()) {
-
+
rl = _route->route_group()->route_list();
-
+
if (_solo_release) {
_solo_release->routes = rl;
}
//if this is a binding action, let the ArdourButton handle it
if ( BindingProxy::is_bind_action(ev) )
return false;
-
+
if (!_session->engine().connected()) {
MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
msg.run ();
if (is_track() && rec_enable_button) {
if (Keyboard::is_button2_event (ev)) {
-
+
//rec arm does not have a momentary mode
return false;
if (ev->button == 1) {
boost::shared_ptr<RouteList> rl;
-
+
if (_route->route_group()) {
-
+
rl = _route->route_group()->route_list();
-
+
} else {
rl.reset (new RouteList);
rl->push_back (_route);
bool
RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
-{
+{
if (ev->button != 1) {
return false;
}
MonitorChoice mc;
boost::shared_ptr<RouteList> rl;
-
+
/* XXX for now, monitoring choices are orthogonal. cue monitoring
will follow in 3.X but requires mixing the input and playback (disk)
signal together, which requires yet more buffers.
mc = monitor_choice;
}
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
rl = _session->get_routes ();
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
}
DisplaySuspender ds;
- _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
+ _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
return false;
}
char buf[64];
_color = c;
snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
-
+
/* note: we use the route state ID here so that color is the same for both
the time axis view and the mixer strip
*/
-
+
gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
_route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
}
if (name.find (':') == string::npos) {
return true;
}
-
+
MessageDialog colon_msg (
_("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
false, MESSAGE_QUESTION, BUTTONS_NONE
);
-
+
colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
if (Config->get_remote_model() == UserOrdered) {
uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
-
+
HBox* hbox = manage (new HBox);
hbox->set_spacing (6);
hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
spin->set_value (_route->remote_control_id());
hbox->pack_start (*spin);
dialog.get_vbox()->pack_start (*hbox);
-
+
dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
} else {
*/
ArdourButton* b = _invert_buttons.front ();
-
+
if (_route->phase_invert().count() == _route->phase_invert().size()) {
b->set_active_state (Gtkmm2ext::ExplicitActive);
} else if (_route->phase_invert().any()) {
for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
(*i)->set_active (_route->phase_invert (j));
}
-
+
}
}
*/
return false;
}
-
+
delete _invert_menu;
_invert_menu = new Menu;
_invert_menu->set_name ("ArdourContextMenu");
RouteUI::color () const
{
RouteGroup* g = _route->route_group ();
-
+
if (g && g->is_color()) {
Gdk::Color c;
set_color_from_rgba (c, GroupTabs::group_color (g));
static void set_showing_sends_to (boost::shared_ptr<ARDOUR::Route>);
static boost::weak_ptr<ARDOUR::Route> _showing_sends_to;
-
+
static uint32_t _max_invert_buttons;
};
VBox* vbox = get_vbox();
vbox->set_spacing (6);
-
+
HBox* hbox;
Label* label;
VBox* sub_vbox = manage (new VBox);
HBox* sub_hbox = manage (new HBox);
HBox* empty = manage (new HBox);
-
+
sub_vbox->pack_start (copy_media_button, false, false);
sub_vbox->pack_start (copy_external_button, false, false);
vbox->pack_start (no_include_media_button, false, false);
vbox->pack_start (*sub_hbox, false, false);
-
+
switch_to_button.set_active (true);
copy_media_button.set_active (true);
-
+
vbox->show_all ();
add_button (Stock::CANCEL, RESPONSE_CANCEL);
add_button (Stock::OK, RESPONSE_OK);
no_include_media_button.signal_toggled ().connect (sigc::mem_fun (*this, &SaveAsDialog::no_include_toggled));
-
+
new_parent_folder_selector.set_action (FILE_CHOOSER_ACTION_SELECT_FOLDER);
new_parent_folder_selector.set_current_folder (Glib::get_home_dir()); // Why $HOME and not poor_mans_glob (Config->get_default_session_parent_dir ()) ??
new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &SaveAsDialog::name_entry_changed));
std::string new_parent_folder () const;
std::string new_name () const;
-
+
bool switch_to () const;
bool include_media () const;
bool copy_media () const;
void clear_name ();
void set_name (std::string);
-
+
private:
Gtk::CheckButton switch_to_button;
Gtk::CheckButton copy_media_button;
get_vbox()->pack_start (info_frame, false, false);
setup_new_session_page ();
-
+
if (!new_only) {
setup_initial_choice_box ();
get_vbox()->pack_start (ic_vbox, true, true);
} else {
get_vbox()->pack_start (session_new_vbox, true, true);
}
-
+
if (!template_name.empty()) {
use_template_button.set_active (false);
load_template_override = template_name;
}
-
+
get_vbox()->show_all ();
/* fill data models and show/hide accordingly */
if (cnt > 0) {
recent_scroller.show();
recent_label.show ();
-
+
if (cnt > 4) {
recent_scroller.set_size_request (-1, 300);
}
/* Try recent session selection */
TreeIter iter = recent_session_display.get_selection()->get_selected();
-
+
if (iter) {
should_be_new = false;
return (*iter)[recent_session_columns.visible_name];
}
/* Try recent session selection */
-
+
TreeIter iter = recent_session_display.get_selection()->get_selected();
-
+
if (iter) {
string s = (*iter)[recent_session_columns.fullpath];
if (Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
hbox->pack_start (*image, false, false);
}
}
-
+
vbox->pack_start (ic_new_session_button, true, true, 20);
hbox->pack_start (*vbox, true, true, 20);
-
+
centering_vbox->pack_start (*hbox, false, false);
/* Possible update message */
recent_scroller.set_no_show_all (true);
recent_label.set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Recent Sessions")));
-
+
centering_vbox->pack_start (recent_label, false, false, 12);
centering_vbox->pack_start (recent_scroller, true, true);
/* Browse button */
-
+
existing_session_chooser.set_title (_("Select session file"));
existing_session_chooser.signal_file_set().connect (sigc::mem_fun (*this, &SessionDialog::existing_session_selected));
existing_session_chooser.set_current_folder(poor_mans_glob (Config->get_default_session_parent_dir()));
-
+
FileFilter session_filter;
session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
existing_session_chooser.add_filter (session_filter);
existing_session_chooser.set_filter (session_filter);
-
+
#ifdef GTKOSX
existing_session_chooser.add_shortcut_folder ("/Volumes");
#endif
-
+
Label* browse_label = manage (new Label);
browse_label->set_markup (string_compose ("<span weight=\"bold\" size=\"large\">%1</span>", _("Other Sessions")));
-
+
centering_vbox->pack_start (*browse_label, false, false, 12);
centering_vbox->pack_start (existing_session_chooser, false, false);
#endif
vbox1->pack_start (*hbox2, false, false);
-
+
session_new_vbox.pack_start (*vbox1, false, false);
/* --- */
HBox* hbox4a = manage (new HBox);
use_template_button.set_label (_("Use this template"));
-
+
TreeModel::Row row = *template_model->prepend ();
row[session_template_columns.name] = (_("no template"));
row[session_template_columns.path] = string();
-
+
hbox4a->set_spacing (6);
hbox4a->pack_start (use_template_button, false, false);
hbox4a->pack_start (template_chooser, true, true);
-
+
template_chooser.set_model (template_model);
-
+
Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
text_renderer->property_editable() = false;
-
+
template_chooser.pack_start (*text_renderer);
template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
template_chooser.set_active (0);
vbox3->pack_start (*hbox4a, false, false);
/* --- */
-
+
HBox* hbox5 = manage (new HBox);
-
+
hbox5->set_spacing (6);
hbox5->pack_start (more_new_session_options_button, false, false);
-
+
setup_more_options_box ();
more_new_session_options_button.add (more_options_vbox);
-
+
vbox3->pack_start (*hbox5, false, false);
hbox3->pack_start (*vbox3, true, true, 8);
vbox2->pack_start (*hbox3, false, false);
-
+
/* --- */
-
+
session_new_vbox.pack_start (*vbox2, false, false);
session_new_vbox.show_all ();
}
for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
session_directories.push_back ((*i).second);
}
-
+
int session_snapshot_count = 0;
for (vector<std::string>::const_iterator i = session_directories.begin(); i != session_directories.end(); ++i)
s = Glib::build_filename (dirname, *i2 + statefile_suffix);
Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
-
+
child_row[recent_session_columns.visible_name] = *i2;
child_row[recent_session_columns.fullpath] = s;
child_row[recent_session_columns.tip] = Glib::Markup::escape_text (dirname);
if (gsb.st_mtime > most_recent) {
most_recent = gsb.st_mtime;
}
-
+
if (Session::get_info_from_path (s, sr, sf) == 0) {
child_row[recent_session_columns.sample_rate] = rate_as_string (sr);
switch (sf) {
hf->add (BWF, _("Broadcast WAVE (4GB size limit)"));
#ifdef HAVE_RF64_RIFF
hf->add (MBWF, _("Broadcast RF64"));
-#endif
+#endif
hf->add (WAVE, _("WAVE (4GB size limit)"));
hf->add (WAVE64, _("WAVE-64"));
hf->add (CAF, _("CAF"));
}
#endif
}
-
+
//------------------------------------------------------------------------
size_t Mootcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
// sort the results in the requested way.
switch (sort) {
- case sort_duration_desc: return "duration_desc";
+ case sort_duration_desc: return "duration_desc";
case sort_duration_asc: return "duration_asc";
case sort_created_desc: return "created_desc";
case sort_created_asc: return "created_asc";
case sort_downloads_asc: return "downloads_asc";
case sort_rating_desc: return "rating_desc";
case sort_rating_asc: return "rating_asc";
- default: return "";
+ default: return "";
}
}
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
// Allow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
-
+
// Allow connections to time out (without using signals)
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
} else {
url += "api_key=" + api_key + "&format=xml";
}
-
+
curl_easy_setopt(curl, CURLOPT_URL, url.c_str() );
-
+
// perform online request
CURLcode res = curl_easy_perform(curl);
if( res != 0 ) {
if (xml_page.memory) {
result = xml_page.memory;
}
-
+
free (xml_page.memory);
xml_page.memory = NULL;
xml_page.size = 0;
params += "&f=" + std::string(ef);
free(ef);
}
-
+
if (sort)
params += "&s=" + sortMethodString(sort);
res = curl_easy_perform (curl);
fclose (theFile);
curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1); // turn off the progress bar
-
+
if (res != CURLE_OK) {
/* it's not an error if the user pressed the stop button */
if (res != CURLE_ABORTED_BY_CALLBACK) {
fclose (testFile);
return true;
}
-
+
// else file was small, probably an error, delete it
fclose(testFile);
remove( audioFileName.c_str() );
if (!theFile) {
return false;
}
-
+
// create the download url
audioURL += "?api_key=" + api_key;
// and we want access to some private members of Mootcher.
Mootcher *thisMootcher = (Mootcher *) caller;
-
+
if (thisMootcher->cancel_download) {
return -1;
}
//add the file chooser
chooser.set_border_width (12);
-
+
audio_and_midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun (*this, &SoundFileBrowser::on_audio_and_midi_filter));
audio_and_midi_filter.set_name (_("Audio and MIDI files"));
-
+
audio_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_audio_filter));
audio_filter.set_name (_("Audio files"));
-
+
midi_filter.add_custom (FILE_FILTER_FILENAME, sigc::mem_fun(*this, &SoundFileBrowser::on_midi_filter));
midi_filter.set_name (_("MIDI files"));
-
+
matchall_filter.add_pattern ("*.*");
matchall_filter.set_name (_("All files"));
-
+
chooser.add_filter (audio_and_midi_filter);
chooser.add_filter (audio_filter);
chooser.add_filter (midi_filter);
/* some broken redraw behaviour - this is a bandaid */
chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
#endif
-
+
if (!persistent_folder.empty()) {
chooser.set_current_folder (persistent_folder);
}
notebook.append_page (chooser, _("Browse Files"));
-
+
hpacker.set_spacing (6);
hpacker.pack_start (notebook, true, true);
hpacker.pack_start (preview, false, false);
VBox* vbox;
HBox* hbox;
-
-
+
+
hbox = manage(new HBox);
hbox->pack_start (found_entry);
hbox->pack_start (found_search_btn);
-
+
Gtk::ScrolledWindow *scroll = manage(new ScrolledWindow);
scroll->add(found_list_view);
scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
-
+
vbox = manage(new VBox);
vbox->pack_start (*hbox, PACK_SHRINK);
vbox->pack_start (*scroll);
-
+
found_list_view.append_column(_("Paths"), found_list_columns.pathname);
-
+
found_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
-
+
found_list_view.signal_row_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
-
+
found_search_btn.signal_clicked().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
found_entry.signal_activate().connect(sigc::mem_fun(*this, &SoundFileBrowser::found_search_clicked));
-
+
notebook.append_page (*vbox, _("Search Tags"));
//add freesound search
HBox* passbox;
Label* label;
-
+
passbox = manage(new HBox);
passbox->set_spacing (6);
-
+
label = manage (new Label);
label->set_text (_("Tags:"));
passbox->pack_start (*label, false, false);
passbox->pack_start (freesound_entry, true, true);
-
+
label = manage (new Label);
label->set_text (_("Sort:"));
passbox->pack_start (*label, false, false);
passbox->pack_start (freesound_sort, false, false);
freesound_sort.clear_items();
-
+
// Order of the following must correspond with enum sortMethod
- // in sfdb_freesound_mootcher.h
+ // in sfdb_freesound_mootcher.h
freesound_sort.append_text(_("None"));
freesound_sort.append_text(_("Longest"));
freesound_sort.append_text(_("Shortest"));
freesound_sort.append_text(_("Highest rated"));
freesound_sort.append_text(_("Lowest rated"));
freesound_sort.set_active(0);
-
+
passbox->pack_start (freesound_search_btn, false, false);
passbox->pack_start (freesound_more_btn, false, false);
freesound_more_btn.set_label(_("More"));
passbox->pack_start (freesound_similar_btn, false, false);
freesound_similar_btn.set_label(_("Similar"));
freesound_similar_btn.set_sensitive(false);
-
+
scroll = manage(new ScrolledWindow);
scroll->add(freesound_list_view);
scroll->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
-
+
vbox = manage(new VBox);
vbox->set_spacing (3);
vbox->pack_start (*passbox, PACK_SHRINK);
freesound_list_view.get_column(3)->set_alignment(0.5);
freesound_list_view.get_column(4)->set_alignment(0.5);
freesound_list_view.get_column(5)->set_alignment(0.5);
-
+
freesound_list_view.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SoundFileBrowser::freesound_list_view_selected));
freesound_list_view.set_tooltip_column(1);
prev_cursor = gdk_window_get_cursor (get_window()->gobj());
gdk_window_set_cursor (get_window()->gobj(), gdk_cursor_new(GDK_WATCH));
gdk_flush();
-
+
std::string theString = mootcher.searchSimilar(id);
-
+
gdk_window_set_cursor (get_window()->gobj(), prev_cursor);
handle_freesound_results(theString);
}
if (selected_audio_track_cnt > 0) {
if (channel_combo.get_active_text().length()) {
ImportDisposition id = get_channel_disposition();
-
+
switch (id) {
case Editing::ImportDistinctFiles:
if (selected_audio_track_cnt == paths.size()) {
action_strings.push_back (importmode2string (ImportToTrack));
}
break;
-
+
case Editing::ImportDistinctChannels:
/* XXX it would be nice to allow channel-per-selected track
but its too hard we don't want to deal with all the
different per-file + per-track channel configurations.
*/
break;
-
+
default:
action_strings.push_back (importmode2string (ImportToTrack));
break;
}
}
}
-
+
} else {
/* MIDI ONLY */
/* We must copy MIDI files or those from Freesound
* or any file if we are under nsm control */
bool const must_copy = _session->get_nsm_state() || have_a_midi_file || notebook.get_current_page() == 2;
-
+
if (UIConfiguration::instance().get_only_copy_imported_files()) {
if (selection_can_be_embedded_with_links && !must_copy) {
if (must_copy) {
copy_files_btn.set_active (true);
- }
+ }
copy_files_btn.set_sensitive (!must_copy);
}
}
/* lets do it */
-
+
vector<string> paths = get_paths ();
ImportPosition pos = get_position ();
ImportMode mode = get_mode ();
ImportDisposition chns = get_channel_disposition ();
PluginInfoPtr instrument = instrument_combo.selected_instrument();
framepos_t where;
-
+
switch (pos) {
case ImportAtEditPoint:
where = PublicEditor::instance().get_preferred_edit_position ();
where = _session->current_start_frame();
break;
}
-
+
SrcQuality quality = get_src_quality();
-
+
if (copy_files_btn.get_active()) {
PublicEditor::instance().do_import (paths, chns, mode, quality, where, instrument);
} else {
PublicEditor::instance().do_embed (paths, chns, mode, where, instrument);
}
}
-
+
void freesound_search();
void refresh_display(std::string ID, std::string file);
-
+
protected:
bool resetting_ourselves;
int matches;
void freesound_more_clicked ();
void freesound_similar_clicked ();
int freesound_page;
-
+
void chooser_file_activated ();
std::string freesound_get_audio_file(Gtk::TreeIter iter);
shuttle_grabbed = false;
remove_modal_grab ();
gdk_pointer_ungrab (GDK_CURRENT_TIME);
-
+
if (Config->get_shuttle_behaviour() == Sprung) {
if (shuttle_speed_on_grab == 0 ) {
_session->request_stop ();
default:
return false;
}
-
+
if (semis) {
float lower_side_of_dead_zone = semitones_as_fract (-24, true);
Gtk::CheckButton soundcloud_download_checkbox;
bool soundcloud_cancel;
Gtk::ProgressBar progress_bar;
-
+
};
#endif // __soundcloud_export_selector_h__
Splash::Splash ()
{
assert (the_splash == 0);
-
+
std::string splash_file;
if (!find_file (ardour_data_search_path(), "splash.png", splash_file)) {
Splash::display ()
{
bool was_mapped = is_mapped ();
-
+
if (!was_mapped) {
expose_done = false;
expose_is_the_one = false;
pop_front ();
present ();
-
+
if (!was_mapped) {
while (!expose_done) {
gtk_main_iteration ();
layout->set_markup (str);
Glib::RefPtr<Gdk::Window> win = darea.get_window();
-
+
if (win) {
expose_done = false;
{
set_position (WIN_POS_CENTER);
set_border_width (12);
-
+
if ((icon_pixbuf = ::get_icon ("ardour_icon_48px")) == 0) {
throw failed_constructor();
}
-
+
list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
Glib::RefPtr<Gdk::Pixbuf> icon;
-
+
if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
window_icons.push_back (icon);
}
if (!window_icons.empty ()) {
set_default_icon_list (window_icons);
}
-
+
setup_new_user_page ();
setup_first_time_config_page ();
setup_monitoring_choice_page ();
*/
const int current_version = atoi (PROGRAM_VERSION);
-
+
for (int v = current_version; v != 0; --v) {
if (Glib::file_test (ARDOUR::been_here_before_path (v), Glib::FILE_TEST_EXISTS)) {
if (v != current_version) {
{
Config->set_default_session_parent_dir (default_dir_chooser->get_filename());
// make new session folder chooser point to the new default
- new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
+ new_folder_chooser.set_current_folder (Config->get_default_session_parent_dir());
config_changed ();
}
PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
}
-
+
_response = RESPONSE_OK;
gtk_main_quit ();
}
if (_panner_shell->bypassed()) {
return true;
}
-
+
drag_start_x = ev->x;
last_drag_x = ev->x;
if (PannerInterface::on_button_release_event (ev)) {
return true;
}
-
+
if (ev->button != 1) {
return false;
}
if (dragging_left) {
delta = -delta;
}
-
+
if (dragging_left || dragging_right) {
if (Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier)) {
*/
_panner->freeze ();
-
+
double pv = position_control->get_value();
if (dragging_left) {
} else {
/* maintain position as invariant as we change the width */
-
+
/* create a detent close to the center */
-
+
if (!detented && fabs (current_width) < 0.02) {
detented = true;
/* snap to zero */
width_control->set_value (0);
}
-
+
if (detented) {
-
+
accumulated_delta += delta;
-
+
/* have we pulled far enough to escape ? */
-
+
if (fabs (accumulated_delta) >= 0.025) {
width_control->set_value (current_width + accumulated_delta);
detented = false;
accumulated_delta = false;
}
-
+
} else {
/* width needs to change by 2 * delta because both L & R move */
width_control->set_value (current_width + (delta * 2.0));
private:
PannerEditor* editor ();
boost::shared_ptr<ARDOUR::PannerShell> _panner_shell;
-
+
boost::shared_ptr<PBD::Controllable> position_control;
boost::shared_ptr<PBD::Controllable> width_control;
PBD::ScopedConnectionList panvalue_connections;
t->set_spacings (6);
int n = 0;
-
+
t->attach (*manage (left_aligned_label (_("Position"))), 0, 1, n, n + 1);
t->attach (_position, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
++n;
-
+
t->attach (*manage (left_aligned_label (_("Width"))), 0, 1, n, n + 1);
t->attach (_width, 1, 2, n, n + 1);
t->attach (*manage (left_aligned_label (_("%"))), 2, 3, n, n + 1);
_panner->get_width_controllable()->Changed.connect (
_connections, invalidator (*this), boost::bind (&StereoPannerEditor::update_editor, this), gui_context ()
);
-
+
_panner->DropReferences.connect (_connections, invalidator (*this), boost::bind (&StereoPannerEditor::panner_going_away, this), gui_context ());
_position.signal_value_changed().connect (sigc::mem_fun (*this, &StereoPannerEditor::position_changed));
_width.signal_value_changed().connect (sigc::mem_fun (*this, &StereoPannerEditor::width_changed));
if (!_panner) {
return;
}
-
+
_ignore_changes = true;
_position.set_value (100 * _panner->get_position_controllable()->get_value ());
_width.set_value (100 * _panner->get_width_controllable()->get_value ());
pair<double, double> const wr = _panner->panner()->width_range ();
_width.set_range (wr.first * 100, wr.second * 100);
}
-
+
void width_changed ();
void set_position_range ();
void set_width_range ();
-
+
StereoPanner* _panner;
Gtk::SpinButton _position;
Gtk::SpinButton _width;
, last_rec_data_frame(0)
{
CANVAS_DEBUG_NAME (_canvas_group, string_compose ("SV canvas group %1", _trackview.name()));
-
+
/* set_position() will position the group */
canvas_rect = new ArdourCanvas::Rectangle (_canvas_group);
layer_t const l = (*i)->region()->layer ();
layer_ok = (min_layer <= l && l <= max_layer);
}
-
+
if (within) {
if ((*i)->region()->coverage (start, end) == Evoral::OverlapExternal && layer_ok) {
results.push_back (*i);
results.push_back (*i);
}
}
-
+
}
}
case Expanded:
return height / (_layers * 2 + 1);
}
-
+
abort(); /* NOTREACHED */
return height;
}
if (_layer_display == Overlaid) {
layer_regions ();
}
-
+
update_contents_height ();
update_coverage_frames ();
}
void check_record_layers (boost::shared_ptr<ARDOUR::Region>, ARDOUR::framepos_t);
virtual void playlist_layered (boost::weak_ptr<ARDOUR::Track>);
-
+
sigc::signal<void, RegionView*> RegionViewAdded;
sigc::signal<void> RegionViewRemoved;
/** Emitted when the height of regions has changed */
UIConfiguration::instance().color_mod ("midi sysex fill", "midi sysex fill"),
ArdourCanvas::Duple (x, y)
);
-
+
_flag->set_text (text);
}
ArdourCanvas::Item& item() const { return *_flag; }
-private:
+private:
bool event_handler (GdkEvent* ev);
ArdourCanvas::Flag* _flag;
if (x == note_types.end()) {
pulse_selector.set_active_text (strings[3]); // "quarter"
}
-
+
Table* table;
if (UIConfiguration::instance().get_allow_non_quarter_pulse()) {
TempoDialog::get_note_type ()
{
NoteTypes::iterator x = note_types.find (pulse_selector.get_active_text());
-
+
if (x == note_types.end()) {
error << string_compose(_("incomprehensible pulse note type (%1)"), pulse_selector.get_active_text()) << endmsg;
return 0;
break;
}
}
-
+
if (x == note_types.end()) {
note_type.set_active_text (strings[3]); // "quarter"
}
MeterDialog::get_note_type ()
{
NoteTypes::iterator x = note_types.find (note_type.get_active_text());
-
+
if (x == note_types.end()) {
error << string_compose(_("incomprehensible meter note type (%1)"), note_type.get_active_text()) << endmsg;
return 0;
, palette_window (0)
{
/* Now the alias list */
-
+
alias_list = TreeStore::create (alias_columns);
alias_display.set_model (alias_list);
alias_display.append_column (_("Object"), alias_columns.name);
-
+
Gtkmm2ext::CellRendererColorSelector* color_renderer = manage (new Gtkmm2ext::CellRendererColorSelector);
TreeViewColumn* color_column = manage (new TreeViewColumn (_("Color"), *color_renderer));
color_column->add_attribute (color_renderer->property_color(), alias_columns.color);
alias_display.append_column (*color_column);
-
+
alias_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
alias_display.get_column (0)->set_expand (true);
alias_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
alias_scroller.add (alias_display);
/* various buttons */
-
+
RadioButton::Group group = dark_button.get_group();
light_button.set_group(group);
theme_selection_hbox.set_homogeneous(false);
pack_start (*hbox, PACK_SHRINK);
}
-
+
hbox = Gtk::manage (new Gtk::HBox());
hbox->set_spacing (6);
hbox->pack_start (waveform_gradient_depth, true, true);
palette_scroller.add (palette_viewport);
modifier_scroller.add (modifier_vbox);
-
+
notebook.append_page (alias_scroller, _("Items"));
notebook.append_page (palette_scroller, _("Palette"));
notebook.append_page (modifier_scroller, _("Transparency"));
-
+
pack_start (notebook);
show_all ();
waveform_gradient_depth.set_update_policy (Gtk::UPDATE_DELAYED);
timeline_item_gradient_depth.set_update_policy (Gtk::UPDATE_DELAYED);
-
+
color_dialog.get_colorsel()->set_has_opacity_control (true);
color_dialog.get_colorsel()->set_has_palette (true);
-
+
set_ui_to_state();
color_dialog.get_ok_button()->signal_clicked().connect (sigc::bind (sigc::mem_fun (color_dialog, &Gtk::Dialog::response), RESPONSE_ACCEPT));
/* no need to call setup_palette() here, it will be done when its size is allocated */
setup_aliases ();
setup_modifiers ();
-
+
UIConfiguration::instance().ColorsChanged.connect (sigc::mem_fun (*this, &ThemeManager::colors_changed));
}
Gtk::HBox* mod_hbox;
Gtk::Label* mod_label;
Gtk::HScale* mod_scale;
-
+
Gtkmm2ext::container_clear (modifier_vbox);
for (UIConfiguration::Modifiers::const_iterator m = modifiers.begin(); m != modifiers.end(); ++m) {
mod_label = manage (new Label (m->first));
mod_label->set_alignment (1.0, 0.5);
mod_label->set_size_request (150, -1); /* 150 pixels should be enough for anyone */
-
+
mod_hbox->pack_start (*mod_label, false, true, 12);
mod_hbox->pack_start (*mod_scale, true, true);
ThemeManager::modifier_edited (Gtk::Range* range, string name)
{
using namespace ArdourCanvas;
-
+
double alpha = range->get_value();
SVAModifier svam (SVAModifier::Assign, -1.0, -1.0, alpha);
UIConfiguration::instance().set_modifier (name, svam);
ThemeManager::colors_changed ()
{
setup_palette ();
- setup_aliases ();
- setup_modifiers ();
+ setup_aliases ();
+ setup_modifiers ();
}
int
if (!dark_button.get_active()) return;
UIConfiguration* uic (&UIConfiguration::instance());
-
+
uic->set_color_file("dark");
}
if (!light_button.get_active()) return;
UIConfiguration* uic (&UIConfiguration::instance());
-
+
uic->set_color_file("light");
}
canvas.set_background_color (rgba_to_color (0.0, 0.0, 1.0, 0.0));
/* bi-directional scroll group */
-
+
ScrollGroup* scroll_group = new ScrollGroup (canvas.root(), ScrollGroup::ScrollSensitivity (ScrollGroup::ScrollsVertically|ScrollGroup::ScrollsHorizontally));
canvas.add_scroller (*scroll_group);
}
SortByHue sorter;
sort (nc.begin(), nc.end(), sorter);
-
+
const uint32_t color_limit = nc.size();
const double box_size = 20.0;
const double width = canvas.width();
uint32_t color_num = 0;
/* clear existing rects and delete them */
-
+
group.clear (true);
-
+
for (uint32_t y = 0; y < height - box_size && color_num < color_limit; y += box_size) {
for (uint32_t x = 0; x < width - box_size && color_num < color_limit; x += box_size) {
ArdourCanvas::Rectangle* r = new ArdourCanvas::Rectangle (&group, ArdourCanvas::Rect (x, y, x + box_size, y + box_size));
req->height = (int) floor (c * box_size);
/* add overflow row if necessary */
-
+
if (fmod (ncolors, c) != 0.0) {
req->height += box_size;
}
using namespace ArdourCanvas;
color_dialog_connection.disconnect ();
-
+
UIConfiguration* uic (&UIConfiguration::instance());
Gdk::Color gdkcolor;
double r,g, b, a;
r = gdkcolor.get_red_p();
g = gdkcolor.get_green_p();
b = gdkcolor.get_blue_p();
-
+
uic->set_color (name, rgba_to_color (r, g, b, a));
break;
-
+
default:
break;
}
palette_window = new ArdourDialog (_("Color Palette"));
palette_window->add_button (Stock::CANCEL, RESPONSE_REJECT); /* using CANCEL causes confusion if dialog is closed via CloseAllDialogs */
palette_window->add_button (Stock::OK, RESPONSE_OK);
-
+
ArdourCanvas::GtkCanvas* canvas = new ArdourCanvas::GtkCanvas ();
ArdourCanvas::Container* group = initialize_palette_canvas (*canvas);
-
+
canvas->signal_size_request().connect (sigc::mem_fun (*this, &ThemeManager::palette_size_request));
canvas->signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &ThemeManager::palette_canvas_allocated), group, canvas,
sigc::bind (sigc::mem_fun (*this, &ThemeManager::alias_palette_event), name)));
-
+
palette_window->get_vbox()->pack_start (*canvas);
palette_window->show_all ();
ThemeManager::setup_aliases ()
{
using namespace ArdourCanvas;
-
+
UIConfiguration* uic (&UIConfiguration::instance());
UIConfiguration::ColorAliases& aliases (uic->color_aliases);
row = *(alias_list->append());
row[alias_columns.name] = parent;
row[alias_columns.alias] = "";
-
+
/* now add the child as a child of this one */
row = *(alias_list->insert (row->children().end()));
private:
Gtk::Notebook notebook;
-
+
struct BasicColorDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
BasicColorDisplayModelColumns() {
add (name);
add (gdkcolor);
}
-
+
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<Gdk::Color> gdkcolor;
};
-
+
Gtk::ColorSelectionDialog color_dialog;
sigc::connection color_dialog_connection;
-
+
Gtk::HBox theme_selection_hbox;
Gtk::RadioButton dark_button;
Gtk::RadioButton light_button;
Gtk::ScrolledWindow palette_scroller;
ArdourCanvas::GtkCanvasViewport palette_viewport;
ArdourCanvas::Container* palette_group;
-
+
/* these methods create and manage a canvas for use in either the
palette tab or in a separate dialog. Different behaviour is
accomplished by changing the event handler passed into the
on it inside the palette tab.
*/
void edit_palette_color (std::string);
-
+
struct ColorAliasModelColumns : public Gtk::TreeModel::ColumnRecord {
ColorAliasModelColumns() {
add (name);
add (color);
add (key);
}
-
+
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<std::string> alias;
Gtk::TreeModelColumn<Gdk::Color> color;
ArdourDialog* palette_window;
sigc::connection palette_response_connection;
-
+
void choose_color_from_palette (std::string const &target_name);
-
+
bool alias_palette_event (GdkEvent*, std::string, std::string);
void alias_palette_response (int, std::string, std::string);
Gtk::ScrolledWindow modifier_scroller;
Gtk::VBox modifier_vbox;
-
+
void setup_modifiers ();
void modifier_edited (Gtk::Range*, std::string);
-
+
void colors_changed ();
void set_ui_to_state ();
};
CANVAS_DEBUG_NAME (selection_group, "selection for TAV");
selection_group->set_data (X_("timeselection"), (void *) 1);
selection_group->hide();
-
+
_ghost_group = new ArdourCanvas::Container (_canvas_display);
CANVAS_DEBUG_NAME (_ghost_group, "ghost for TAV");
_ghost_group->lower_to_bottom();
_canvas_display->raise_to_top ();
_canvas_display->show ();
-
+
_hidden = false;
_effective_height = current_height ();
}
_ebox_release_can_act = true;
-
+
if (maybe_set_cursor (event->y) > 0) {
_resize_drag_start = event->y_root;
}
if (can_edit_name()) {
name_entry = manage (new Gtkmm2ext::FocusEntry);
-
+
name_entry->set_width_chars(8); // min width, entry expands
name_entry->set_name ("EditorTrackNameDisplay");
if (name_label.is_ancestor (name_hbox)) {
name_hbox.remove (name_label);
}
-
+
name_hbox.pack_end (*name_entry, true, true);
name_entry->show ();
*/
return;
}
-
+
PBD::Unwinder<bool> uw (ending_name_edit, true);
-
+
bool edit_next = false;
bool edit_prev = false;
TrackViewList const & allviews = _editor.get_track_views ();
TrackViewList::const_iterator i = find (allviews.begin(), allviews.end(), this);
-
+
if (i != allviews.end()) {
-
+
do {
if (++i == allviews.end()) {
return;
}
-
+
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*>(*i);
-
+
if (rtav && rtav->route()->record_enabled()) {
continue;
}
-
+
if (!(*i)->hidden()) {
break;
}
-
+
} while (true);
}
TrackViewList const & allviews = _editor.get_track_views ();
TrackViewList::const_iterator i = find (allviews.begin(), allviews.end(), this);
-
+
if (i != allviews.begin()) {
do {
if (i == allviews.begin()) {
return;
}
-
+
--i;
-
+
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*>(*i);
-
+
if (rtav && rtav->route()->record_enabled()) {
continue;
}
-
+
if (!(*i)->hidden()) {
break;
}
-
+
} while (true);
}
-
+
if ((i != allviews.end()) && (*i != this) && !(*i)->hidden()) {
_editor.ensure_time_axis_view_is_visible (**i, false);
(*i)->begin_name_edit ();
(*i)->start_trim->set_fill_color (UIConfiguration::instance().color ("selection"));
(*i)->start_trim->set_outline_color (UIConfiguration::instance().color ("selection"));
-
+
(*i)->end_trim->set_fill_color (UIConfiguration::instance().color ("selection"));
(*i)->end_trim->set_outline_color (UIConfiguration::instance().color ("selection"));
}
-
+
for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) {
-
+
(*i)->rect->set_fill_color (UIConfiguration::instance().color_mod ("selection rect", "selection rect"));
(*i)->rect->set_outline_color (UIConfiguration::instance().color ("selection"));
-
+
(*i)->start_trim->set_fill_color (UIConfiguration::instance().color ("selection"));
(*i)->start_trim->set_outline_color (UIConfiguration::instance().color ("selection"));
-
+
(*i)->end_trim->set_fill_color (UIConfiguration::instance().color ("selection"));
(*i)->end_trim->set_outline_color (UIConfiguration::instance().color ("selection"));
}
/* if either the top or bottom of the axisview is in the vertical
* range, we cover it.
*/
-
+
if ((y0 < _y_position && y1 < _y_position) ||
(y0 >= _y_position + height && y1 >= _y_position + height)) {
return false;
/* this method is not required to trigger a global redraw */
string str = gui_property ("height");
-
+
if (!str.empty()) {
set_height (atoi (str));
} else {
/* share the other's parent, but still create a new group */
ArdourCanvas::Item* parent = other.group->parent();
-
+
_selected = other._selected;
-
+
init (parent, other.samples_per_pixel, other.fill_color, other.frame_position,
other.item_duration, other.visibility, other.wide_enough_for_name, other.high_enough_for_name);
}
ArdourCanvas::Rect (0.0, 0.0,
trackview.editor().sample_to_pixel(duration),
trackview.current_height()));
-
+
frame->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::LEFT|ArdourCanvas::Rectangle::RIGHT));
CANVAS_DEBUG_NAME (frame, string_compose ("frame for %1", get_item_name()));
frame->set_outline_color (UIConfiguration::instance().color ("time axis frame"));
}
}
-
+
if (UIConfiguration::instance().get_show_name_highlight() && (visibility & ShowNameHighlight)) {
/* rectangle size will be set in ::manage_name_highlight() */
if (_selected == yn) {
return;
}
-
+
Selectable::set_selected (yn);
set_frame_color ();
set_name_text_color ();
}
if (frame) {
-
+
frame->set_y0 (0.0);
frame->set_y1 (height);
name_highlight->show();
// name_highlight->set_x_position (1.0);
name_highlight->set (ArdourCanvas::Rect (0.0, (double) _height - NAME_HIGHLIGHT_SIZE, _width - 2.0, _height));
-
+
} else {
name_highlight->hide();
}
if (!name_text) {
return;
}
-
+
uint32_t f;
-
+
if (UIConfiguration::instance().get_show_name_highlight()) {
/* name text will always be on top of name highlight, which
will always use our fill color.
frame->set_gradient (ArdourCanvas::Fill::StopList (), 0);
return;
}
-
+
ArdourCanvas::Fill::StopList stops;
double r, g, b, a;
double h, s, v;
/* need to get alpha value */
ArdourCanvas::color_to_rgba (f, r, g, b, a);
-
+
stops.push_back (std::make_pair (0.0, f));
-
+
/* now a darker version */
-
+
ArdourCanvas::color_to_hsv (f, h, s, v);
v = min (1.0, v * (1.0 - UIConfiguration::instance().get_timeline_item_gradient_depth()));
-
+
ArdourCanvas::Color darker = ArdourCanvas::hsva_to_color (h, s, v, a);
stops.push_back (std::make_pair (1.0, darker));
-
+
frame->set_gradient (stops, true);
}
name_text->hide ();
return;
}
-
+
if (name_text->text().empty()) {
name_text->hide ();
}
}
set_default_response (Gtk::RESPONSE_ACCEPT);
-
+
VBox* progress_box = manage (new VBox);
progress_box->set_spacing (6);
gint delete_in_progress (GdkEventAny*);
private:
-
+
void update_progress_gui (float);
};
syncing_punch = false;
}
}
-
+
void
TimeInfoBox::set_session (Session* s)
if (s) {
Location* punch = s->locations()->auto_punch_location ();
-
+
if (punch) {
watch_punch (punch);
}
-
+
punch_changed (punch);
_session->auto_punch_location_changed.connect (_session_connections, MISSING_INVALIDATOR,
Glib::RefPtr<Action> act = ActionManager::get_action ("MouseMode", "set-mouse-mode-object-range");
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
- if (tact && tact->get_active() && !selection.regions.empty()) {
+ if (tact && tact->get_active() && !selection.regions.empty()) {
/* show selected regions */
s = selection.regions.start();
e = selection.regions.end_frame();
default:
selection_start->set_off (true);
selection_end->set_off (true);
- selection_length->set_off (true);
+ selection_length->set_off (true);
break;
}
}
punch_start->set (loc->start());
punch_end->set (loc->end());
-}
+}
UIConfiguration::parameter_changed (string param)
{
_dirty = true;
-
+
if (param == "ui-rc-file") {
load_rc_file (true);
} else if (param == "color-file") {
stringstream ss;
ss << "gtk_color_scheme = \"" << hex;
-
+
for (ColorAliases::iterator g = color_aliases.begin(); g != color_aliases.end(); ++g) {
-
+
if (g->first.find ("gtk_") == 0) {
const string gtk_name = g->first.substr (4);
ss << gtk_name << ":#" << std::setw (6) << setfill ('0') << (color (g->second) >> 8) << ';';
{
std::string rcfile;
int ret = -1;
-
+
if (find_file (ardour_config_search_path(), default_ui_config_file_name, rcfile) ) {
XMLTree tree;
if (!found) {
basename = color_file.get();
basename += ".colors";
-
+
if (find_file (ardour_config_search_path(), basename, cfile)) {
found = true;
}
if (found) {
XMLTree tree;
-
+
info << string_compose (_("Loading color file %1"), cfile) << endmsg;
if (!tree.read (cfile.c_str())) {
parent->add_child_nocopy (*node);
}
root->add_child_nocopy (*parent);
-
+
parent = new XMLNode (X_("ColorAliases"));
for (ColorAliases::const_iterator i = color_aliases.begin(); i != color_aliases.end(); ++i) {
XMLNode* node = new XMLNode (X_("ColorAlias"));
XMLTree tree;
std::string colorfile = Glib::build_filename (user_config_directory(), (string ("my-") + color_file.get() + ".colors"));
-
+
tree.set_root (root);
if (!tree.write (colorfile.c_str())){
if (_dirty) {
std::string rcfile = Glib::build_filename (user_config_directory(), ui_config_file_name);
-
+
XMLTree tree;
tree.set_root (&get_state());
colors_modified = false;
modifiers_modified = false;
}
-
+
return 0;
}
XMLNodeConstIterator niter;
XMLProperty const *name;
XMLProperty const *alias;
-
+
color_aliases.clear ();
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
XMLNodeConstIterator niter;
XMLProperty const *name;
XMLProperty const *color;
-
+
colors.clear ();
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
XMLNodeConstIterator niter;
XMLProperty const *name;
XMLProperty const *mod;
-
+
modifiers.clear ();
-
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() != X_("Modifier")) {
continue;
if (failed) {
*failed = false;
}
-
+
if (e != color_aliases.end ()) {
Colors::const_iterator rc = colors.find (e->second);
if (rc != colors.end()) {
return rc->second;
}
}
-
+
if (!failed) {
/* only show this message if the caller wasn't interested in
the fail status.
if (failed) {
*failed = true;
}
-
+
return rgba_to_color ((g_random_int()%256)/255.0,
(g_random_int()%256)/255.0,
(g_random_int()%256)/255.0,
void set_alias (std::string const & name, std::string const & alias);
void set_color (const std::string& name, ArdourCanvas::Color);
void set_modifier (std::string const &, ArdourCanvas::SVAModifier svam);
-
+
std::string color_as_alias (ArdourCanvas::Color c);
ArdourCanvas::Color quantized (ArdourCanvas::Color) const;
void set_pango_fontsize ();
float get_ui_scale ();
-
+
sigc::signal<void> DPIReset;
sigc::signal<void,std::string> ParameterChanged;
/** called after the GUI toolkit has been initialized.
*/
UIConfiguration* post_gui_init ();
-
+
#undef UI_CONFIG_VARIABLE
#define UI_CONFIG_VARIABLE(Type,var,name,value) \
Type get_##var () const { return var.get(); } \
bool aliases_modified;
bool colors_modified;
bool modifiers_modified;
-
+
int store_color_theme ();
void load_color_aliases (XMLNode const &);
void load_colors (XMLNode const &);
ev->keyval, fakekey));
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tmodified modifier was %1\n", show_gdk_event_state (modifier)));
-
+
if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, modifier)) {
DEBUG_TRACE (DEBUG::Accelerators, "\taccel group activated by fakekey\n");
return true;
Searchpath spath(ARDOUR::ardour_data_search_path());
spath.add_subdirectory_to_paths ("icons");
vector<string> r;
-
+
r.push_back (_("default"));
for (vector<string>::iterator s = spath.begin(); s != spath.end(); ++s) {
/* add "icons/icon_set" but .. not allowed to add both of these at once */
spath.add_subdirectory_to_paths ("icons");
spath.add_subdirectory_to_paths (icon_set);
-
+
find_file (spath, name, data_file_path);
} else {
spath.add_subdirectory_to_paths ("icons");
find_file (spath, name, data_file_path);
}
-
+
if (is_image && data_file_path.empty()) {
-
+
if (!icon_set.empty() && icon_set != _("default")) {
warning << string_compose (_("icon \"%1\" not found for icon set \"%2\", fallback to default"), cname, icon_set) << endmsg;
}
-
+
Searchpath def (ARDOUR::ardour_data_search_path());
def.add_subdirectory_to_paths ("icons");
-
+
if (!find_file (def, name, data_file_path)) {
fatal << string_compose (_("cannot find icon image for %1 using %2"), name, spath.to_string()) << endmsg;
abort(); /*NOTREACHED*/
void show ();
void hide ();
-
+
private:
Editor* _editor;
ArdourCanvas::TrackingText* _canvas_item;
m.name = name;
m.visible = visible;
m.override = override;
-
+
_members.push_back (m);
}
}
v = v.substr (comma + 1);
-
+
} while (1);
update ();
if (!_model) {
return;
}
-
+
_ignore_list_view_change = true;
_model->clear ();
-
+
for (vector<Member>::iterator i = _members.begin(); i != _members.end(); ++i) {
Gtk::TreeModel::iterator j = _model->append ();
Gtk::TreeModel::Row row = *j;
if (_ignore_list_view_change) {
return;
}
-
+
Gtk::TreeModel::iterator i = _model->get_iter (path);
if (!i) {
return;
{
public:
VisibilityGroup (std::string const &);
-
+
void add (
Gtk::Widget *,
std::string const &,
bool visible = false,
boost::function<boost::optional<bool> ()> = 0
);
-
+
Gtk::Menu* menu ();
Gtk::Widget* list_view ();
bool button_press_event (GdkEventButton *);
std::string get_state_value () const;
PBD::Signal0<void> VisibilityChanged;
-
+
private:
struct Member {
VolumeController::dB_printer (char buf[32], const boost::shared_ptr<PBD::Controllable>& c)
{
if (c) {
-
+
if (_linear) {
double val = accurate_coefficient_to_dB (c->get_value());
}
} else {
-
+
double dB = accurate_coefficient_to_dB (c->get_value());
if (step_inc < 1.0) {
_vst->state()->width + _vst->state()->hoffset,
_vst->state()->height + _vst->state()->voffset);
#endif
-
+
return 0;
}
virtual int package (Gtk::Window &);
bool non_gtk_gui () const { return true; }
-
+
protected:
virtual int get_XID () = 0;
-
+
boost::shared_ptr<ARDOUR::VSTPlugin> _vst;
Gtk::Socket _socket;
}
}
}
-
+
current_transient_parent = parent;
#endif
}
ProxyBase::get_state () const
{
XMLNode* node = new XMLNode (X_("Window"));
- char buf[32];
+ char buf[32];
node->add_property (X_("name"), _name);
if (_window && vistracker) {
-
+
/* we have a window, so use current state */
_visible = vistracker->partially_visible ();
}
node->add_property (X_("visible"), _visible? X_("yes") : X_("no"));
-
+
snprintf (buf, sizeof (buf), "%d", _x_off);
node->add_property (X_("x-off"), buf);
snprintf (buf, sizeof (buf), "%d", _y_off);
}
set_session(_session);
}
-
+
void
ProxyBase::show ()
{
static Manager* _instance;
};
-
+
class ProxyBase : public ARDOUR::SessionHandlePtr, public sigc::trackable {
public:
ProxyBase (const std::string& name, const std::string& menu_name);
void setup ();
};
-
+
class ProxyTemporary: public ProxyBase {
public:
ProxyTemporary (const std::string& name, Gtk::Window* win);
ARDOUR::SessionHandlePtr* session_handle ();
};
-
+
template<typename T>
class ProxyWithConstructor: public ProxyBase {
public:
ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c)
: ProxyBase (name, menu_name) , creator (c) {}
-
+
ProxyWithConstructor (const std::string& name, const std::string& menu_name, const boost::function<T*()>& c, const XMLNode* node)
: ProxyBase (name, menu_name, *node) , creator (c) {}
-
+
Gtk::Window* get (bool create = false) {
if (!_window) {
if (!create) {
if (_window) {
setup ();
- }
+ }
}
return _window;
Proxy (const std::string& name, const std::string& menu_name, const XMLNode* node)
: ProxyBase (name, menu_name, *node) {}
-
+
Gtk::Window* get (bool create = false) {
if (!_window) {
if (!create) {
if (_window) {
setup ();
- }
+ }
}
return _window;
/* buffer full */
return;
}
-
+
int special_windows_key = 0;
int character_windows_key = 0;
-
+
switch (ev->keyval) {
case GDK_Left:
special_windows_key = 0x25;
character_windows_key = ev->keyval;
break;
}
-
+
fst->pending_keys[fst->n_pending_keys].special = special_windows_key;
fst->pending_keys[fst->n_pending_keys].character = character_windows_key;
fst->n_pending_keys++;
-
+
pthread_mutex_unlock (&fst->lock);
}
void forward_key_event (GdkEventKey *);
private:
-
+
int get_XID ();
-
+
};
}
Session* s = 0;
-
+
try {
s = load_session (argv[optind], argv[optind+1]);
} catch (failed_constructor& e) {
}
s->request_transport_speed (1.0);
-
+
sleep (-1);
AudioEngine::instance()->remove_session ();
TestReceiver::receive (Transmitter::Channel chn, const char * str)
{
const char *prefix = "";
-
+
switch (chn) {
case Transmitter::Error:
prefix = ": [ERROR]: ";
/* this isn't supposed to happen */
abort ();
}
-
+
/* note: iostreams are already thread-safe: no external
lock required.
*/
-
+
std::cout << prefix << str << std::endl;
-
+
if (chn == Transmitter::Fatal) {
::exit (9);
}
*/
/*=============================================================================
AUOutputBL.h
-
+
=============================================================================*/
#include "AUOutputBL.h"
void AUOutputBL::Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated)
{
UInt32 channelsPerBuffer = mFormat.IsInterleaved() ? mFormat.NumberChannels() : 1;
-
+
if (mBufferMemory == NULL || inWantNullBufferIfAllocated)
{
mBufferList->mNumberBuffers = mNumberBuffers;
UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
if ((nBytes * mNumberBuffers) > AllocatedBytes())
throw OSStatus(-10874);//(kAudioUnitErr_TooManyFramesToProcess);
-
+
mBufferList->mNumberBuffers = mNumberBuffers;
AudioBuffer *buf = &mBufferList->mBuffers[0];
Byte* p = mBufferMemory;
if (inNumFrames)
{
UInt32 nBytes = mFormat.FramesToBytes (inNumFrames);
-
+
if (nBytes <= AllocatedBytes())
return;
-
+
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
if (mNumberBuffers > 1)
nBytes = (nBytes + (0x10 - (nBytes & 0xF))) | 0x10;
-
+
mBufferSize = nBytes;
-
+
UInt32 memorySize = mBufferSize * mNumberBuffers;
Byte *newMemory = new Byte[memorySize];
memset(newMemory, 0, memorySize); // make buffer "hot"
-
+
Byte *oldMemory = mBufferMemory;
mBufferMemory = newMemory;
delete[] oldMemory;
-
+
mFrames = inNumFrames;
}
else
*/
/*=============================================================================
AUOutputBL.h
-
+
=============================================================================*/
#ifndef __AUOutputBL_h__
class AUOutputBL {
public:
-
+
// you CANNOT use one of these - it will crash!
// AUOutputBL ();
-
+
// this is the constructor that you use
// it can't be reset once you've constructed it
AUOutputBL (const CAStreamBasicDescription &inDesc, UInt32 inDefaultNumFrames = 512);
{
Prepare (mFrames);
}
-
+
// this version can throw if this is an allocted ABL and inNumFrames is > AllocatedFrames()
// you can set the bool to true if you want a NULL buffer list even if allocated
// inNumFrames must be a valid number (will throw if inNumFrames is 0)
void Prepare (UInt32 inNumFrames, bool inWantNullBufferIfAllocated = false);
-
+
AudioBufferList* ABL() { return mBufferList; }
-
+
// You only need to call this if you want to allocate a buffer list
// if you want an empty buffer list, just call Prepare()
// if you want to dispose previously allocted memory, pass in 0
// then you either have an empty buffer list, or you can re-allocate
// Memory is kept around if an Allocation request is less than what is currently allocated
void Allocate (UInt32 inNumberFrames);
-
+
UInt32 AllocatedFrames() const { return mFrames; }
-
+
const CAStreamBasicDescription& GetFormat() const { return mFormat; }
#if DEBUG
void Print();
#endif
-
+
private:
UInt32 AllocatedBytes () const { return (mBufferSize * mNumberBuffers); }
*/
/*=============================================================================
AUParamInfo.cpp
-
+
=============================================================================*/
#include "AUParamInfo.h"
#include "CAXException.h"
UInt32 size;
OSStatus result = AudioUnitGetPropertyInfo(mAU, kAudioUnitProperty_ParameterList, inScope, mElement, &size, NULL);
if (size == 0 || result) return;
-
+
int nparams = size / sizeof(AudioUnitPropertyID);
mParamListID = new AudioUnitParameterID[nparams];
memset (mParamListID, 0xFF, size);
AudioUnitParameterID *paramList = new AudioUnitParameterID[nparams];
-
+
result = AudioUnitGetProperty(mAU, kAudioUnitProperty_ParameterList, mScope, mElement, paramList, &size);
if (result) {
delete [] mParamListID;
mParamListID = NULL;
return;
}
-
+
ParameterMap params;
for (int i = 0; i < nparams; ++i)
{
CAAUParameter auvp (mAU, paramList[i], mScope, mElement); // took out only using global scope in CAAUParameter creation
const AudioUnitParameterInfo ¶mInfo = auvp.ParamInfo();
-
+
// don't include if parameter can't be read or written
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
&& !(paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
// only include if expert params wanted
if (!inIncludeExpert && auvp.IsExpert())
continue;
-
+
// only include if read only params are wanted
if (!(paramInfo.flags & kAudioUnitParameterFlag_IsWritable)
&& (paramInfo.flags & kAudioUnitParameterFlag_IsReadable))
- {
+ {
if (!inIncludeReadOnly)
continue;
}
-
+
mParamListID[mNumParams] = paramList[i];
mNumParams++;
-
+
// ok - if we're here, then we have a parameter we are going to display.
UInt32 clump = 0;
auvp.GetClumpID (clump);
*/
/*=============================================================================
AUParamInfo.h
-
+
=============================================================================*/
#include <map>
#include <vector>
The ParameterMap returned by the Map() method is a map where
- the key is the clumpID
- the value is a ParameterList (vector<CAAUParameter>)
-
+
If you have parameters on multiple scopes (or elements within a scope), then you should create one of these
for each scope-element pair
*/
bool inIncludeReadOnly,
AudioUnitScope inScope = kAudioUnitScope_Global,
AudioUnitElement inElement = 0);
-
+
~AUParamInfo();
-
+
const ParameterMap& Map () const { return mParams; }
-
+
// some convenience methods
UInt32 NumParams () const { return mNumParams; }
-
+
AudioUnitParameterID ParamID (UInt32 inIndex) const
{
if (inIndex < mNumParams) return mParamListID[inIndex];
return 0xFFFFFFFF;
}
-
+
UInt32 NumClumps () const { return mParams.size(); }
UInt32 NumParamsForClump (UInt32 inClump) const;
-
+
// returns NULL if there's no info for the parameter
const CAAUParameter* GetParamInfo (AudioUnitParameterID inParamID) const;
-
+
AudioUnitScope GetScope () const { return mScope; }
AudioUnitElement GetElement () const { return mElement; }
-
+
private:
AudioUnit mAU;
UInt32 mNumParams;
AudioUnitParameterID * mParamListID;
-
+
ParameterMap mParams;
AudioUnitScope mScope;
AudioUnitElement mElement;
-
+
// disallow
AUParamInfo () {}
AUParamInfo (const AUParamInfo &) {}
*/
/*=============================================================================
CAAUParameter.cpp
-
+
=============================================================================*/
#include "CAAUParameter.h"
if (mParamName) CFRelease(mParamName);
if (mParamTag) CFRelease(mParamTag);
if (mNamedParams) CFRelease(mNamedParams);
-
+
memcpy(this, &a, sizeof(CAAUParameter));
if (mParamName) CFRetain(mParamName);
if (mParamTag) CFRetain(mParamTag);
if (mNamedParams) CFRetain(mNamedParams);
-
+
return *this;
}
mParameterID = param;
mScope = scope;
mElement = element;
-
+
UInt32 propertySize = sizeof(mParamInfo);
OSStatus err = AudioUnitGetProperty(au, kAudioUnitProperty_ParameterInfo,
scope, param, &mParamInfo, &propertySize);
CFRetain (mParamName);
} else
mParamName = CFStringCreateWithCString(NULL, mParamInfo.name, kCFStringEncodingUTF8);
-
+
char* str = 0;
switch (mParamInfo.unit)
{
str = NULL;
break;
}
-
+
if (str)
mParamTag = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
else
stringValue.inValue = value;
stringValue.outString = NULL;
UInt32 propertySize = sizeof(stringValue);
-
+
OSStatus err = AudioUnitGetProperty (mAudioUnit,
kAudioUnitProperty_ParameterStringFromValue,
mScope,
mParameterID,
&stringValue,
&propertySize);
-
+
if (err == noErr && stringValue.outString != NULL)
return stringValue.outString;
}
-
+
Float32 val = (value == NULL ? GetValue() : *value);
char valstr[32];
AUParameterFormatValue (val, this, valstr, 4);
valueString.inParamID = mParameterID;
valueString.inString = str;
UInt32 propertySize = sizeof(valueString);
-
+
OSStatus err = AudioUnitGetProperty (mAudioUnit,
kAudioUnitProperty_ParameterValueFromString,
mScope,
mParameterID,
&valueString,
&propertySize);
-
+
if (err == noErr) {
return valueString.outValue;
}
}
-
+
Float32 paramValue = mParamInfo.defaultValue;
char valstr[32];
CFStringGetCString(str, valstr, sizeof(valstr), kCFStringEncodingUTF8);
{
UInt32 clump = 0;
GetClumpID (clump);
-
+
UInt32 len = CFStringGetLength(mParamName);
char* chars = (char*)malloc (len * 2); // give us plenty of room for unichar chars
if (!CFStringGetCString (mParamName, chars, len * 2, kCFStringEncodingUTF8))
chars[0] = 0;
-
+
printf ("ID: %ld, Clump: %ld, Name: %s\n", mParameterID, clump, chars);
free (chars);
}
*/
/*=============================================================================
CAAUParameter.h
-
+
=============================================================================*/
#ifndef __CAAUParameter_h__
CAAUParameter(const CAAUParameter &a);
/*! @dtor ~CAAUParameter */
~CAAUParameter();
-
+
/*! @method operator <@ */
bool operator < (const CAAUParameter &a) const
{
{
return !memcmp(this, &a, sizeof(AudioUnitParameter));
}
-
+
/*! @method operator =@ */
CAAUParameter & operator = (const CAAUParameter &a);
-
+
/*! @method GetValue */
Float32 GetValue() const;
/*! @method SetValue */
void SetValue( AUParameterListenerRef inListener,
void * inObject,
Float32 inValue) const;
-
+
/*! @method GetName */
CFStringRef GetName() const { return mParamName; }
// borrowed reference!
/*! @method GetStringFromValueCopy */
- CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
+ CFStringRef GetStringFromValueCopy(const Float32 *value = NULL) const;
// returns a copy of the name of the current parameter value
// or null if there is no name associated
// caller must release
{
return (mParamInfo.flags & kAudioUnitParameterFlag_ValuesHaveStrings) != 0;
}
-
+
/*! @method GetValueFromString */
- Float32 GetValueFromString (CFStringRef str) const;
+ Float32 GetValueFromString (CFStringRef str) const;
// caller must release
/*! @method ParamInfo */
- const AudioUnitParameterInfo &
+ const AudioUnitParameterInfo &
ParamInfo() const { return mParamInfo; }
/*! @method GetParamTag */
? (CFStringRef) CFArrayGetValueAtIndex(mNamedParams, inIndex)
: 0;
}
-
+
/*! @method GetNumIndexedParams */
int GetNumIndexedParams () const { return mNumIndexedParams; }
-
+
/*! @method IsIndexedParam */
bool IsIndexedParam () const { return mNumIndexedParams != 0; }
-
+
/*! @method HasNamedParams */
bool HasNamedParams () const { return IsIndexedParam() && mNamedParams; }
-
+
/*! @method GetClumpID */
bool GetClumpID (UInt32 &outClumpID) const
{
}
return false;
}
-
+
/*! @method HasDisplayTransformation */
bool HasDisplayTransformation () const
{
#if DEBUG
void Print () const;
#endif
-
+
// these methods are defined in CAPersistence.cpp
// they will persist and restore only the scope, element and param ID's of the AudioUnitParameter
// however, this is sufficient to be able to save/restore a CAAUParameter object
void Save (CFPropertyListRef &outData) const;
-
+
static void Save (const AudioUnitParameter &inParam, CFPropertyListRef &outData);
-
+
static OSStatus Restore (const CFPropertyListRef inData, AudioUnitParameter &outParam);
protected:
short mNumIndexedParams;
/*! @var mNamedParams */
CFArrayRef mNamedParams;
-
+
private:
void Init (AudioUnit au, AudioUnitParameterID param, AudioUnitScope scope, AudioUnitElement element);
// (this may be too strict a comparison if all you care about are matching layout tags)
UInt32 theSize1 = CAAudioChannelLayout::CalculateByteSize(x.mNumberChannelDescriptions);
UInt32 theSize2 = CAAudioChannelLayout::CalculateByteSize(y.mNumberChannelDescriptions);
-
+
if (theSize1 != theSize2)
return false;
-
+
return !memcmp (&x, &y, theSize1);
}
{
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions)
return inLayout.mNumberChannelDescriptions;
-
+
if (inLayout.mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelBitmap)
return CountOnes (inLayout.mChannelBitmap);
}
static void SetAllToUnknown(AudioChannelLayout& outChannelLayout, UInt32 inNumberChannelDescriptions);
static UInt32 NumberChannels(const AudioChannelLayout& inLayout);
-
+
#if !HAL_Build
-// object methods
+// object methods
public:
CAAudioChannelLayout ();
CAAudioChannelLayout (const CAAudioChannelLayout &c);
CAAudioChannelLayout (const AudioChannelLayout* inChannelLayout);
~CAAudioChannelLayout();
-
+
CAAudioChannelLayout& operator= (const AudioChannelLayout* inChannelLayout);
CAAudioChannelLayout& operator= (const CAAudioChannelLayout& c);
bool operator== (const CAAudioChannelLayout &c) const;
bool IsValid() const { return NumberChannels() > 0; }
UInt32 Size() const { return mLayoutHolder ? mLayoutHolder->Size() : 0; }
-
+
UInt32 NumberChannels() const { return NumberChannels(Layout()); }
-
+
AudioChannelLayoutTag Tag() const { return Layout().mChannelLayoutTag; }
const AudioChannelLayout& Layout() const { return mLayoutHolder->Layout(); }
operator const AudioChannelLayout *() const { return &Layout(); }
-
+
void Print () const { Print (stdout); }
void Print (FILE* file) const;
OSStatus Save (CFPropertyListRef *outData) const;
OSStatus Restore (CFPropertyListRef &inData);
-
+
private:
class ACLRefCounter : public CAReferenceCounted {
public:
{
if (inDataSize < offsetof(AudioChannelLayout, mChannelDescriptions))
inDataSize = offsetof(AudioChannelLayout, mChannelDescriptions);
-
+
mLayout = static_cast<AudioChannelLayout*>(malloc (inDataSize));
memset (mLayout, 0, inDataSize);
mByteSize = inDataSize;
}
-
+
const AudioChannelLayout & Layout() const { return *mLayout; }
-
+
UInt32 Size () const { return mByteSize; }
-
+
private:
AudioChannelLayout *mLayout;
UInt32 mByteSize;
-
+
// only the constructors can change the actual state of the layout
friend CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround);
friend OSStatus CAAudioChannelLayout::Restore (CFPropertyListRef &inData);
friend CAAudioChannelLayout& CAAudioChannelLayout::operator= (const AudioChannelLayout* inChannelLayout);
friend void CAAudioChannelLayout::SetWithTag(AudioChannelLayoutTag inTag);
-
+
AudioChannelLayout * GetLayout() { return mLayout; }
~ACLRefCounter() { if (mLayout) { free(mLayout); mLayout = NULL; } }
-
+
private:
ACLRefCounter () : mLayout(NULL) { }
ACLRefCounter(const ACLRefCounter& other) : CAReferenceCounted (other), mLayout(NULL) { }
ACLRefCounter& operator=(const ACLRefCounter&) { return *this; }
};
-
+
ACLRefCounter *mLayoutHolder;
#endif // HAL_Build
// CAAudioChannelLayout::CAAudioChannelLayout
//=============================================================================
CAAudioChannelLayout::CAAudioChannelLayout (UInt32 inNumberChannels, bool inChooseSurround)
-{
+{
// this chooses default layouts based on the number of channels...
UInt32 theSize = CalculateByteSize (inNumberChannels);
-
+
mLayoutHolder = new ACLRefCounter (theSize);
-
+
AudioChannelLayout* layout = mLayoutHolder->GetLayout();
layout->mNumberChannelDescriptions = inNumberChannels;
-
+
switch (inNumberChannels)
{
case 1:
if (mLayoutHolder != c.mLayoutHolder) {
if (mLayoutHolder)
mLayoutHolder->release();
-
+
if ((mLayoutHolder = c.mLayoutHolder) != NULL)
mLayoutHolder->retain();
}
-
+
return *this;
}
mLayoutHolder->release();
UInt32 theSize = CalculateByteSize (inChannelLayout->mNumberChannelDescriptions);
-
+
mLayoutHolder = new ACLRefCounter (theSize);
-
+
memcpy(mLayoutHolder->mLayout, inChannelLayout, theSize);
return *this;
}
{
if (mLayoutHolder)
mLayoutHolder->release();
-
+
mLayoutHolder = new ACLRefCounter(offsetof(AudioChannelLayout, mChannelDescriptions[0]));
AudioChannelLayout* layout = mLayoutHolder->GetLayout();
layout->mChannelLayoutTag = inTag;
*/
/*=============================================================================
CAAudioFile.cpp
-
+
=============================================================================*/
#include "CAAudioFile.h"
if (sIndent == 0)
printf("\n");
}
-
+
static void Indent() {
for (int i = sIndent; --i >= 0; ) {
putchar(' '); putchar(' ');
}
}
-
+
const char *mName;
static int sIndent;
};
mMode(kClosed),
mFileDataOffset(-1),
mFramesToSkipFollowingSeek(0),
-
+
mClientOwnsIOBuffer(false),
mPacketDescs(NULL),
mNumPacketDescs(0),
{
LOG_FUNCTION("CAAudioFile::CreateNew", "%p", this);
XThrowIf(mMode != kClosed, kExtAudioFileError_InvalidOperationOrder, "file already open");
-
+
mFileDataFormat = dataFormat;
if (layout) {
mFileChannelLayout = layout;
{
LOG_FUNCTION("CAAudioFile::FileFormatChanged", "%p", this);
XThrowIf(mMode != kPreparingToCreate && mMode != kPreparingToWrite, kExtAudioFileError_InvalidOperationOrder, "new file not prepared");
-
+
UInt32 propertySize;
OSStatus err;
AudioStreamBasicDescription saveFileDataFormat = mFileDataFormat;
-
+
#if VERBOSE_CONVERTER
mFileDataFormat.PrintFormat(stdout, "", "Specified file data format");
#endif
-
+
// Find out the actual format the converter will produce. This is necessary in
// case the bitrate has forced a lower sample rate, which needs to be set correctly
// in the stream description passed to AudioFileCreate.
free(layout);
}
}
-
+
// create the output file
if (mMode == kPreparingToCreate) {
CAStreamBasicDescription newFileDataFormat = mFileDataFormat;
if (mConverter != NULL) {
// encoder
- // get the magic cookie, if any, from the converter
+ // get the magic cookie, if any, from the converter
delete[] mMagicCookie; mMagicCookie = NULL;
mMagicCookieSize = 0;
err = AudioConverterGetPropertyInfo(mConverter, kAudioConverterCompressionMagicCookie, &propertySize, NULL);
-
+
// we can get a noErr result and also a propertySize == 0
// -- if the file format does support magic cookies, but this file doesn't have one.
if (err == noErr && propertySize > 0) {
XThrowIfError(AudioFileSetProperty(mAudioFile, kAudioFilePropertyMagicCookieData, mMagicCookieSize, mMagicCookie), "set audio file's magic cookie");
}
}
-
+
// get maximum packet size
propertySize = sizeof(UInt32);
XThrowIfError(AudioConverterGetProperty(mConverter, kAudioConverterPropertyMaximumOutputPacketSize, &propertySize, &mFileMaxPacketSize), "get audio converter's maximum output packet size");
} else {
InitFileMaxPacketSize();
}
-
+
if (mFileChannelLayout.IsValid() && mFileChannelLayout.NumberChannels() > 2) {
// don't bother tagging mono/stereo files
UInt32 isWritable;
#endif
}
}
-
+
UpdateClientMaxPacketSize(); // also sets mFrame0Offset
mPacketMark = 0;
mFrameMark = 0;
LOG_FUNCTION("CAAudioFile::GetExistingFileInfo", "%p", this);
UInt32 propertySize;
OSStatus err;
-
+
// get mFileDataFormat
propertySize = sizeof(AudioStreamBasicDescription);
XThrowIfError(AudioFileGetProperty(mAudioFile, kAudioFilePropertyDataFormat, &propertySize, &mFileDataFormat), "get audio file's data format");
-
+
// get mFileChannelLayout
err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyChannelLayout, &propertySize, NULL);
if (err == noErr && propertySize > 0) {
}
if (mMode != kReading)
return;
-
+
#if 0
// get mNumberPackets
propertySize = sizeof(mNumberPackets);
printf("CAAudioFile::GetExistingFileInfo: %qd packets\n", mNumberPackets);
#endif
#endif
-
+
// get mMagicCookie
err = AudioFileGetPropertyInfo(mAudioFile, kAudioFilePropertyMagicCookieData, &propertySize, NULL);
if (err == noErr && propertySize > 0) {
InitFileMaxPacketSize();
mPacketMark = 0;
mFrameMark = 0;
-
+
UpdateClientMaxPacketSize();
}
{
LOG_FUNCTION("CAAudioFile::SetClientFormat", "%p", this);
XThrowIf(!dataFormat.IsPCM(), kExtAudioFileError_NonPCMClientFormat, "non-PCM client format on audio file");
-
+
bool dataFormatChanging = (mClientDataFormat.mFormatID == 0 || mClientDataFormat != dataFormat);
-
+
if (dataFormatChanging) {
CloseConverter();
if (mWriteBufferList) {
}
mClientDataFormat = dataFormat;
}
-
+
if (layout && layout->IsValid()) {
XThrowIf(layout->NumberChannels() != mClientDataFormat.NumberChannels(), kExtAudioFileError_InvalidChannelMap, "inappropriate channel map");
mClientChannelLayout = *layout;
}
-
+
bool differentLayouts;
if (mClientChannelLayout.IsValid()) {
if (mFileChannelLayout.IsValid()) {
printf("two invalid layouts\n");
#endif
}
-
+
if (mClientDataFormat != mFileDataFormat || differentLayouts) {
// We need an AudioConverter.
if (mMode == kReading) {
if (mConverter == NULL)
XThrowIfError(AudioConverterNew(&mFileDataFormat, &mClientDataFormat, &mConverter),
"create audio converter");
-
+
#if VERBOSE_CONVERTER
printf("CAAudioFile %p -- created converter\n", this);
CAShow(mConverter);
SetConverterChannelLayout(false, mFileChannelLayout);
SetConverterChannelLayout(true, mClientChannelLayout);
-
+
// propagate leading/trailing frame counts
if (mFileDataFormat.mBitsPerChannel == 0) {
UInt32 propertySize;
// _______________________________________________________________________________________
//
-OSStatus CAAudioFile::SetConverterProperty(
+OSStatus CAAudioFile::SetConverterProperty(
AudioConverterPropertyID inPropertyID,
UInt32 inPropertyDataSize,
const void* inPropertyData,
{
LOG_FUNCTION("CAAudioFile::SetConverterChannelLayout", "%p", this);
OSStatus err;
-
+
if (layout.IsValid()) {
#if VERBOSE_CHANNELMAP
printf("Setting converter's %s channel layout: %s\n", output ? "output" : "input",
AudioConverterPropertyID property = (mMode == kReading) ?
kAudioConverterPropertyMaximumOutputPacketSize :
kAudioConverterPropertyMaximumInputPacketSize;
-
+
UInt32 propertySize = sizeof(UInt32);
XThrowIfError(AudioConverterGetProperty(mConverter, property, &propertySize, &mClientMaxPacketSize),
"get audio converter's maximum packet size");
-
+
if (mFileDataFormat.mBitsPerChannel == 0) {
AudioConverterPrimeInfo primeInfo;
propertySize = sizeof(primeInfo);
}
UInt32 bufferSizeBytes = mIOBufferSizeBytes = std::max(mIOBufferSizeBytes, mFileMaxPacketSize);
// must be big enough for at least one maximum size packet
-
+
if (mIOBufferList.mBuffers[0].mDataByteSize != bufferSizeBytes) {
mIOBufferList.mNumberBuffers = 1;
mIOBufferList.mBuffers[0].mNumberChannels = mFileDataFormat.mChannelsPerFrame;
mIOBufferList.mBuffers[0].mDataByteSize = bufferSizeBytes;
mIOBufferSizePackets = bufferSizeBytes / mFileMaxPacketSize;
}
-
+
UInt32 propertySize = sizeof(UInt32);
UInt32 externallyFramed;
XThrowIfError(AudioFormatGetProperty(kAudioFormatProperty_FormatIsExternallyFramed,
{
AudioFramePacketTranslation trans;
UInt32 propertySize;
-
+
switch (mFileDataFormat.mFramesPerPacket) {
case 1:
return packet;
{
AudioFramePacketTranslation trans;
UInt32 propertySize;
-
+
switch (mFileDataFormat.mFramesPerPacket) {
case 1:
return inFrame;
if (mPacketMark == packetNumber)
return; // already there! don't reset converter
mPacketMark = packetNumber;
-
+
mFrameMark = PacketToFrame(packetNumber) - mFrame0Offset;
mFramesToSkipFollowingSeek = 0;
if (mConverter)
/*
Example: AAC, 1024 frames/packet, 2112 frame offset
-
+
2112
|
Absolute frames: 0 1024 2048 | 3072
* Offset between absolute and client frames is mFrame0Offset.
*** mFrameMark is in client frames ***
-
+
Examples:
clientFrame 0 960 1000 1024
absoluteFrame 2112 3072 3112 3136
#if VERBOSE_IO
SInt64 prevFrameMark = mFrameMark;
#endif
-
+
SInt64 packet;
packet = FrameToPacket(clientFrame);
if (packet < 0)
// this will have backed up mFrameMark to match the beginning of the packet
mFramesToSkipFollowingSeek = std::max(UInt32(clientFrame - mFrameMark), UInt32(0));
mFrameMark = clientFrame;
-
+
#if VERBOSE_IO
printf("CAAudioFile::SeekToFrame: frame %qd (from %qd), packet %qd, skip %ld frames\n", mFrameMark, prevFrameMark, packet, mFramesToSkipFollowingSeek);
#endif
AllocateBuffers();
}
UInt32 bufferSizeBytes = ioData->mBuffers[0].mDataByteSize;
- UInt32 maxNumPackets = bufferSizeBytes / mClientMaxPacketSize;
+ UInt32 maxNumPackets = bufferSizeBytes / mClientMaxPacketSize;
// older versions of AudioConverterFillComplexBuffer don't do this, so do our own sanity check
UInt32 nPackets = std::min(ioNumPackets, maxNumPackets);
-
+
mMaxPacketsToRead = ~0UL;
-
+
if (mClientDataFormat.mFramesPerPacket == 1) { // PCM or equivalent
while (mFramesToSkipFollowingSeek > 0) {
UInt32 skipFrames = std::min(mFramesToSkipFollowingSeek, maxNumPackets);
ioData->mBuffers[i].mDataByteSize = bufferSizeBytes;
}
}
-
+
if (mFileDataFormat.mFramesPerPacket > 0)
// don't read more packets than we are being asked to produce
mMaxPacketsToRead = nPackets / mFileDataFormat.mFramesPerPacket + 1;
}
if (mClientDataFormat.mFramesPerPacket == 1)
mFrameMark += nPackets;
-
+
ioNumPackets = nPackets;
}
return noErr; // not eofErr; EOF is signified by 0 packets/0 bytes
}
#endif
-
+
// determine how much to read
AudioBufferList *readBuffer;
UInt32 readPackets;
#endif
readPackets = This->mMaxPacketsToRead;
}
-
+
// read
UInt32 bytesRead;
OSStatus err;
-
+
StartTiming(This, read);
StartTiming(This, readinconv);
err = AudioFileReadPackets(This->mAudioFile, This->mUseCache, &bytesRead, This->mPacketDescs, This->mPacketMark, &readPackets, readBuffer->mBuffers[0].mData);
DebugMessageN1("Error %ld from AudioFileReadPackets!!!\n", err);
return err;
}
-
+
#if VERBOSE_IO
printf("CAAudioFile::ReadInputProc: read %ld packets (%qd-%qd), %ld bytes, err %ld\n", readPackets, This->mPacketMark, This->mPacketMark + readPackets, bytesRead, err);
#if VERBOSE_IO >= 2
OSStatus err;
AudioConverterPrimeInfo primeInfo;
propertySize = sizeof(primeInfo);
-
+
err = AudioConverterGetProperty(mConverter, kAudioConverterPrimeInfo, &propertySize, &primeInfo);
if (err == noErr) {
AudioFilePacketTableInfo pti;
{
const Byte *p = (Byte *)addr;
UInt32 offset = 0;
-
+
if (len > 0x400) len = 0x400;
-
+
while (len > 0) {
int n = len > 16 ? 16 : len;
printf("%08lX: ", offset);
*/
/*=============================================================================
CAAudioFile.h
-
+
=============================================================================*/
#ifndef __CAAudioFile_h__
// open an existing file
XThrowIfError(ExtAudioFileOpen(&fsref, &mExtAF), "ExtAudioFileOpen failed");
}
-
+
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL) {
XThrowIfError(ExtAudioFileCreateNew(&inParentDir, inFileName, inFileType, &inStreamDesc, inChannelLayout, &mExtAF), "ExtAudioFileCreateNew failed");
}
// use this to wrap an AudioFileID opened externally
XThrowIfError(ExtAudioFileWrapAudioFileID(fileID, forWriting, &mExtAF), "ExtAudioFileWrapAudioFileID failed");
}
-
+
void Close() {
std::cerr << "\tdisposeo of ext audio file @ " << mExtAF << std::endl;
XThrowIfError(ExtAudioFileDispose(mExtAF), "ExtAudioFileClose failed");
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileDataFormat, &size, &mFileDataFormat), "Couldn't get file's data format");
return mFileDataFormat;
}
-
+
const CAAudioChannelLayout & GetFileChannelLayout() {
return FetchChannelLayout(mFileChannelLayout, kExtAudioFileProperty_FileChannelLayout);
}
-
+
void SetFileChannelLayout(const CAAudioChannelLayout &layout) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set file's channel layout");
mFileChannelLayout = layout;
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, &size, &mClientDataFormat), "Couldn't get client data format");
return mClientDataFormat;
}
-
+
const CAAudioChannelLayout & GetClientChannelLayout() {
return FetchChannelLayout(mClientChannelLayout, kExtAudioFileProperty_ClientChannelLayout);
}
-
+
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientDataFormat, sizeof(dataFormat), &dataFormat), "Couldn't set client format");
if (layout)
SetClientChannelLayout(*layout);
}
-
+
void SetClientChannelLayout(const CAAudioChannelLayout &layout) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_ClientChannelLayout, layout.Size(), &layout.Layout()), "Couldn't set client channel layout");
}
-
+
AudioConverterRef GetConverter() const {
UInt32 size = sizeof(AudioConverterRef);
AudioConverterRef converter;
}
return err;
}
-
+
SInt64 GetNumberFrames() {
SInt64 length;
UInt32 size = sizeof(SInt64);
XThrowIfError(ExtAudioFileGetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, &size, &length), "Couldn't get file's length");
return length;
}
-
+
void SetNumberFrames(SInt64 length) {
XThrowIfError(ExtAudioFileSetProperty(mExtAF, kExtAudioFileProperty_FileLengthFrames, sizeof(SInt64), &length), "Couldn't set file's length");
}
-
+
void Seek(SInt64 pos) {
XThrowIfError(ExtAudioFileSeek(mExtAF, pos), "Couldn't seek in audio file");
}
-
+
SInt64 Tell() {
SInt64 pos;
XThrowIfError(ExtAudioFileTell(mExtAF, &pos), "Couldn't get file's mark");
return pos;
}
-
+
void Read(UInt32 &ioFrames, AudioBufferList *ioData) {
XThrowIfError(ExtAudioFileRead(mExtAF, &ioFrames, ioData), "Couldn't read audio file");
}
// - Open
// - PrepareNew followed by Create
// - Wrap
-
+
void Open(const FSRef &fsref);
// open an existing file
void CreateNew(const FSRef &inParentDir, CFStringRef inFileName, AudioFileTypeID inFileType, const AudioStreamBasicDescription &inStreamDesc, const AudioChannelLayout *inChannelLayout=NULL);
-
+
void Wrap(AudioFileID fileID, bool forWriting);
// use this to wrap an AudioFileID opened externally
void Close();
// In case you want to close the file before the destructor executes
-
+
// --- Data formats ---
// Allow specifying the file's channel layout. Must be called before SetClientFormat.
// the channel layout). When reading, the specified layout overrides the one read from the file,
// if any.
void SetFileChannelLayout(const CAAudioChannelLayout &layout);
-
+
// This specifies the data format which the client will use for reading/writing the file,
// which may be different from the file's format. An AudioConverter is created if necessary.
// The client format must be linear PCM.
void SetClientFormat(const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout=NULL);
void SetClientDataFormat(const CAStreamBasicDescription &dataFormat) { SetClientFormat(dataFormat, NULL); }
void SetClientChannelLayout(const CAAudioChannelLayout &layout) { SetClientFormat(mClientDataFormat, &layout); }
-
+
// Wrapping the underlying converter, if there is one
OSStatus SetConverterProperty(AudioConverterPropertyID inPropertyID,
UInt32 inPropertyDataSize,
void SetConverterConfig(CFArrayRef config) {
SetConverterProperty(kAudioConverterPropertySettings, sizeof(config), &config); }
CFArrayRef GetConverterConfig();
-
+
// --- I/O ---
// All I/O is sequential, but you can seek to an arbitrary position when reading.
// SeekToPacket and TellPacket's packet numbers are in the file's data format, not the client's.
// These can fail for files without a constant mFramesPerPacket
void Seek(SInt64 frameNumber);
SInt64 Tell() const; // frameNumber
-
+
// --- Accessors ---
// note: client parameters only valid if SetClientFormat has been called
AudioFileID GetAudioFileID() const { return mAudioFile; }
SInt64 GetNumberFrames() const;
// will be 0 if the file's frames/packet is 0 (variable)
void SetNumberFrames(SInt64 length); // should only be set on a PCM file
-
+
// --- Tunable performance parameters ---
void SetUseCache(bool b) { mUseCache = b; }
void SetIOBufferSizeBytes(UInt32 bufferSizeBytes) { mIOBufferSizeBytes = bufferSizeBytes; }
UInt32 GetIOBufferSizeBytes() { return mIOBufferSizeBytes; }
void * GetIOBuffer() { return mIOBufferList.mBuffers[0].mData; }
void SetIOBuffer(void *buf);
-
+
// -- Profiling ---
#if CAAUDIOFILE_PROFILE
void EnableProfiling(bool b) { mProfiling = b; }
UInt64 TicksInConverter() const { return (mTicksInConverter > 0) ? (mTicksInConverter - mTicksInReadInConverter) : 0; }
UInt64 TicksInIO() const { return mTicksInIO; }
#endif
-
+
// _______________________________________________________________________________________
private:
SInt64 FileDataOffset();
void SeekToPacket(SInt64 packetNumber);
SInt64 TellPacket() const { return mPacketMark; } // will be imprecise if SeekToFrame was called
-
+
void SetConverterChannelLayout(bool output, const CAAudioChannelLayout &layout);
void WritePacketsFromCallback(
AudioConverterComplexInputDataProc inInputDataProc,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
- void* inUserData);
+ void* inUserData);
static OSStatus WriteInputProc( AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription** outDataPacketDescription,
- void* inUserData);
+ void* inUserData);
// _______________________________________________________________________________________
private:
bool mUseCache;
bool mFinishingEncoding;
enum { kClosed, kReading, kPreparingToCreate, kPreparingToWrite, kWriting } mMode;
-
+
// SInt64 mNumberPackets; // in file's format
SInt64 mFileDataOffset;
SInt64 mPacketMark; // in file's format
// lie at frame 2112 of a decoded AAC file
SInt32 mFrame0Offset;
UInt32 mFramesToSkipFollowingSeek;
-
+
// buffers
UInt32 mIOBufferSizeBytes;
UInt32 mIOBufferSizePackets;
bool mClientOwnsIOBuffer;
AudioStreamPacketDescription *mPacketDescs;
UInt32 mNumPacketDescs;
-
+
// formats/conversion
AudioConverterRef mConverter;
CAStreamBasicDescription mFileDataFormat;
CAAudioChannelLayout mClientChannelLayout;
UInt32 mFileMaxPacketSize;
UInt32 mClientMaxPacketSize;
-
+
// cookie
Byte * mMagicCookie;
UInt32 mMagicCookieSize;
-
+
// for ReadPackets
UInt32 mMaxPacketsToRead;
-
+
// for WritePackets
UInt32 mWritePackets;
CABufferList * mWriteBufferList;
-
+
#if CAAUDIOFILE_PROFILE
// performance
bool mProfiling;
struct StackAUChannelInfo {
StackAUChannelInfo (UInt32 inSize) : mChanInfo ((AUChannelInfo*)malloc (inSize)) {}
~StackAUChannelInfo() { free (mChanInfo); }
-
+
AUChannelInfo* mChanInfo;
};
{
Init();
}
-
+
~AUState();
-
+
AudioUnit mUnit;
AUNode mNode;
if (mGetParamProc != NULL) {
return reinterpret_cast<AudioUnitGetParameterProc>(mGetParamProc) (mConnInstanceStorage,
inID, scope, element, &outValue);
- }
+ }
return AudioUnitGetParameter(mUnit, inID, scope, element, &outValue);
}
if (mSetParamProc != NULL) {
return reinterpret_cast<AudioUnitSetParameterProc>(mSetParamProc) (mConnInstanceStorage,
inID, scope, element, value, bufferOffsetFrames);
- }
+ }
return AudioUnitSetParameter(mUnit, inID, scope, element, value, bufferOffsetFrames);
}
-
+
OSStatus Render (AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inOutputBusNumber,
if (mRenderProc != NULL) {
return reinterpret_cast<AudioUnitRenderProc>(mRenderProc) (mConnInstanceStorage,
ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
- }
+ }
return AudioUnitRender(mUnit, ioActionFlags, inTimeStamp, inOutputBusNumber, inNumberFrames, ioData);
}
-
+
OSStatus MIDIEvent (UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
kAudioUnitScope_Global, kMusicDeviceMIDIEventSelect,
&mMIDIEventProc, &size) != noErr)
mMIDIEventProc = NULL;
-
+
if (mRenderProc || mGetParamProc || mSetParamProc || mMIDIEventProc)
mConnInstanceStorage = GetComponentInstanceStorage(mUnit);
else
mConnInstanceStorage = NULL;
}
-
+
ProcPtr mRenderProc, mGetParamProc, mSetParamProc, mMIDIEventProc;
void * mConnInstanceStorage;
AUState () {}
AUState (const AUState& other) : CAReferenceCounted (other) {}
AUState& operator= (const AUState&) { return *this; }
-};
-
-
+};
+
+
CAAudioUnit::AUState::~AUState ()
{
if (mUnit && (mNode == 0)) {
if (mDataPtr != a.mDataPtr) {
if (mDataPtr)
mDataPtr->release();
-
+
if ((mDataPtr = a.mDataPtr) != NULL)
mDataPtr->retain();
-
+
mComp = a.mComp;
}
-
+
return *this;
}
return mDataPtr->mUnit == y;
}
-#pragma mark __State Management
+#pragma mark __State Management
bool CAAudioUnit::IsValid () const
{
return mDataPtr ? mDataPtr->mUnit != 0 : false;
}
-
+
AudioUnit CAAudioUnit::AU() const
{
return mDataPtr ? mDataPtr->mUnit : 0;
}
#pragma mark __Format Handling
-
+
bool CAAudioUnit::CanDo ( int inChannelsIn,
int inChannelsOut) const
-{
+{
// this is the default assumption of an audio effect unit
Boolean* isWritable = 0;
UInt32 dataSize = 0;
kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
&dataSize, isWritable); //don't care if this is writable
-
+
// if this property is NOT implemented an FX unit
// is expected to deal with same channel valance in and out
if (result)
return false;
}
}
-
+
StackAUChannelInfo info (dataSize);
-
+
result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
info.mChanInfo, &dataSize);
if (result) { return false; }
-
+
return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo)));
}
kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
&dataSize, isWritable); //don't care if this is writable
-
+
// if this property is NOT implemented an FX unit
// is expected to deal with same channel valance in and out
-
+
if (result)
{
if (Comp().Desc().IsEffect())
}
}
}
-
+
// special meaning on input, specific num on output
else if (info[i].inChannels < 0) {
if (info[i].outChannels == inChannelsOut)
}
}
}
-
+
// special meaning on output, specific num on input
else if (info[i].outChannels < 0) {
if (info[i].inChannels == inChannelsIn)
else if ((info[i].inChannels == inChannelsIn) && (info[i].outChannels == inChannelsOut)) {
return true;
}
-
+
// now check to see if a wild card on the args (inChannelsIn or inChannelsOut chans is zero) is found
// tells us to match just one side of the scopes
else if (inChannelsIn == 0) {
}
}
}
-
+
return false;
}
// first check our state
// huh!
if (inputs.mNumEls == 0 && outputs.mNumEls == 0) return false;
-
+
UInt32 elCount;
if (GetElementCount (kAudioUnitScope_Input, elCount)) { return false; }
if (elCount != inputs.mNumEls) return false;
if (GetElementCount (kAudioUnitScope_Output, elCount)) { return false; }
if (elCount != outputs.mNumEls) return false;
-
+
// (1) special cases (effects and sources (generators and instruments) only)
UInt32 dataSize = 0;
if (GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
if (numChan != outputs.mChans[out]) return false;
return true;
}
-
+
// in this case, all the channels have to match the current config
if (Comp().Desc().IsGenerator() || Comp().Desc().IsMusicDevice()) {
for (unsigned int in = 0; in < inputs.mNumEls; ++in) {
}
return true;
}
-
+
// if we get here we can't determine anything about channel capabilities
return false;
}
StackAUChannelInfo info (dataSize);
-
+
if (GetProperty (kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
info.mChanInfo, &dataSize) != noErr)
{
return false;
}
-
+
int numInfo = dataSize / sizeof(AUChannelInfo);
-
+
// (2) Test for dynamic capability (or no elements on that scope)
SInt32 dynInChans = 0;
if (ValidateDynamicScope (kAudioUnitScope_Input, dynInChans, info.mChanInfo, numInfo)) {
}
}
}
-
+
return true;
}
kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
&dataSize, isWritable); //don't care if this is writable
-
+
// if this property is NOT implemented an FX unit
// is expected to deal with same channel valance in and out
if (result) {
}
if (result) return false;
-
+
bool canDo = false;
// OK lets get our channel layouts and see if the one we want is present
AudioChannelLayoutTag* info = (AudioChannelLayoutTag*)malloc (dataSize);
inScope, inEl,
info, &dataSize);
if (result) goto home;
-
+
outChannelVector.erase (outChannelVector.begin(), outChannelVector.end());
for (unsigned int i = 0; i < (dataSize / sizeof (AudioChannelLayoutTag)); ++i)
outChannelVector.push_back (info[i]);
OSStatus result = AudioUnitGetPropertyInfo (AU(), kAudioUnitProperty_AudioChannelLayout,
inScope, inEl, &size, NULL);
if (result) return result;
-
+
AudioChannelLayout *layout = (AudioChannelLayout*)malloc (size);
require_noerr (result = AudioUnitGetProperty (AU(), kAudioUnitProperty_AudioChannelLayout,
inScope, inEl, layout, &size), home);
outLayout = CAAudioChannelLayout (layout);
-
+
home:
free (layout);
return result;
OSStatus CAAudioUnit::SetSampleRate (Float64 inSampleRate)
{
OSStatus result;
-
+
UInt32 elCount;
require_noerr (result = GetElementCount(kAudioUnitScope_Input, elCount), home);
if (elCount) {
require_noerr (result = SetSampleRate (kAudioUnitScope_Output, i, inSampleRate), home);
}
}
-
+
home:
return result;
}
if (result)
return result;
outWritable = isWritable ? true : false;
- return noErr;
+ return noErr;
}
OSStatus CAAudioUnit::GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const
OSStatus result = GetPropertyInfo (kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
&dataSize, isWritable); //don't care if this is writable
-
+
// AU has to explicitly tell us about this.
if (result) return false;
StackAUChannelInfo info (dataSize);
-
+
result = GetProperty (kAudioUnitProperty_SupportedNumChannels,
kAudioUnitScope_Global, 0,
info.mChanInfo, &dataSize);
outTotalNumChannels = -1;
return true;
}
-
+
// ok lets now test our special case....
if (inScope == kAudioUnitScope_Input) {
// isn't dynamic on this side at least
if (info[i].inChannels >= 0)
continue;
-
+
if (info[i].inChannels < -2) {
outTotalNumChannels = abs (info[i].inChannels);
return true;
}
}
-
+
else if (inScope == kAudioUnitScope_Output) {
// isn't dynamic on this side at least
if (info[i].outChannels >= 0)
continue;
-
+
if (info[i].outChannels < -2) {
outTotalNumChannels = abs (info[i].outChannels);
return true;
}
}
-
+
else {
break; // wrong scope was specified
}
}
-
- return false;
+
+ return false;
}
OSStatus CAAudioUnit::ConfigureDynamicScope (AudioUnitScope inScope,
bool isDyamic = HasDynamicScope (inScope, numChannels);
if (isDyamic == false)
return kAudioUnitErr_InvalidProperty;
-
+
//lets to a sanity check...
// if numChannels == -1, then it can do "any"...
if (numChannels > 0) {
if (count > numChannels)
return kAudioUnitErr_InvalidPropertyValue;
}
-
+
OSStatus result = SetElementCount (inScope, inNumElements);
if (result)
return result;
-
+
CAStreamBasicDescription desc;
desc.mSampleRate = inSampleRate;
for (unsigned int i = 0; i < inNumElements; ++i) {
}
OSStatus CAAudioUnit::SetBypass (bool inBypass) const
-{
+{
UInt32 bypass = inBypass ? 1 : 0;
return AudioUnitSetProperty (AU(), kAudioUnitProperty_BypassEffect,
kAudioUnitScope_Global, 0,
}
return result;
}
-
+
OSStatus CAAudioUnit::SetPresentPreset (AUPreset &inData)
{
OSStatus result = AudioUnitSetProperty (AU(), kAudioUnitProperty_PresentPreset,
CAStreamBasicDescription desc;
OSStatus result = GetFormat (kAudioUnitScope_Input, 0, desc);
bool hasInput = false;
- //we have input
+ //we have input
if (result == noErr)
{
sRenderCallback.inputProc = PrerollRenderProc;
sRenderCallback.inputProcRefCon = 0;
-
+
result = SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
0, &sRenderCallback, sizeof(sRenderCallback));
if (result) return result;
hasInput = true;
}
-
+
AudioUnitRenderActionFlags flags = 0;
AudioTimeStamp time;
memset (&time, 0, sizeof(time));
{
AUOutputBL list (outputFormat, inFrameSize);
list.Prepare ();
-
+
require_noerr (result = Render (&flags, &time, 0, inFrameSize, list.ABL()), home);
require_noerr (result = GlobalReset(), home);
}
// remove our installed callback
sRenderCallback.inputProc = 0;
sRenderCallback.inputProcRefCon = 0;
-
+
SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
0, &sRenderCallback, sizeof(sRenderCallback));
}
mChans = mStaticChans;
}
memcpy (mChans, c.mChans, c.mNumEls * sizeof(int));
-
+
return *this;
}
~CAAudioUnit ();
-
+
CAAudioUnit& operator= (const CAAudioUnit& y);
bool operator== (const CAAudioUnit& y) const;
bool operator== (const AudioUnit& y) const;
-#pragma mark __State Management
+#pragma mark __State Management
bool IsValid () const;
-
+
AudioUnit AU() const;
operator AudioUnit () const { return AU(); }
const CAComponent& Comp() const { return mComp; }
-
+
bool FromAUGraph () const { return GetAUNode() != 0 || GetAUNode() != -1; }
-
+
AUNode GetAUNode () const;
operator AUNode () const { return GetAUNode(); }
-
+
#pragma mark __API Wrapper
OSStatus Initialize() const { return AudioUnitInitialize(AU()); }
OSStatus Uninitialize() const { return AudioUnitUninitialize(AU()); }
}
OSStatus SetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
Float32 value, UInt32 bufferOffsetFrames=0);
-
+
OSStatus GetParameter(AudioUnitParameterID inID, AudioUnitScope scope, AudioUnitElement element,
Float32 &outValue) const;
UInt32 inOutputBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData);
-
+
OSStatus Reset (AudioUnitScope scope, AudioUnitElement element)
{
return AudioUnitReset (AU(), scope, element);
{
return AudioUnitAddRenderNotify (AU(), inProc, inProcRefCon);
}
-
+
OSStatus RemoveRenderNotify (AURenderCallback inProc, void *inProcRefCon)
{
return AudioUnitRemoveRenderNotify (AU(), inProc, inProcRefCon);
}
-
-// Fast dispatch support for MIDI Effects or Music Devices
+
+// Fast dispatch support for MIDI Effects or Music Devices
OSStatus MIDIEvent (UInt32 inStatus,
UInt32 inData1,
UInt32 inData2,
UInt32 inOffsetSampleFrame);
-
+
// uses the default VoiceForGroup value - this is the normal case
OSStatus StartNote (MusicDeviceGroupID inGroupID,
NoteInstanceID * outNoteInstanceID,
{
return CanDo (inChannelsInOut, inChannelsInOut);
}
-
+
bool CanDo ( int inChannelsIn,
int inChannelsOut) const;
-
+
// This version does a more thorough test for ANY AU with ANY ins/outs
// you pass in the channel helper (for the current element count on that scope)
-
+
bool CanDo ( const CAAUChanHelper &input,
const CAAUChanHelper &output) const;
-
+
bool SupportsNumChannels () const;
-
+
bool HasChannelLayouts (AudioUnitScope inScope,
AudioUnitElement inEl) const;
-
+
int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt);
bool GetChannelLayouts (AudioUnitScope inScope,
AudioUnitElement inEl,
ChannelTagVector &outChannelVector) const;
-
+
OSStatus GetChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl,
- CAAudioChannelLayout &outLayout) const;
+ CAAudioChannelLayout &outLayout) const;
OSStatus SetChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl,
AudioUnitElement inEl,
AudioChannelLayout &inLayout,
UInt32 inSize);
-
+
OSStatus ClearChannelLayout (AudioUnitScope inScope,
AudioUnitElement inEl);
-
+
OSStatus GetFormat (AudioUnitScope inScope,
AudioUnitElement inEl,
AudioStreamBasicDescription &outFormat) const;
// this sets the sample rate on all in/out buses of the AU
OSStatus SetSampleRate (Float64 inSampleRate);
-
+
OSStatus NumberChannels (AudioUnitScope inScope,
AudioUnitElement inEl,
UInt32 &outChans) const;
OSStatus GetElementCount (AudioUnitScope inScope, UInt32 &outCount) const;
OSStatus SetElementCount (AudioUnitScope inScope, UInt32 inCount);
-
+
// value of -1 for outTotalNumChannels indicates no restriction on num channels
// for ex. the Matrix Mixer satisfies this (its in/out element count is writable, and can be set to
// any number of channels.
{
return HasDynamicScope (kAudioUnitScope_Input, outTotalNumChannels);
}
-
+
bool HasDynamicOutputs (SInt32 &outTotalNumChannels) const
{
return HasDynamicScope (kAudioUnitScope_Output, outTotalNumChannels);
}
-
+
// here, if the in (or out) elements are dynamic, then you supply the number of elements
// you want on in (or out) scope, and the number of channels on each consecutive element
OSStatus ConfigureDynamicInput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
{
return ConfigureDynamicScope (kAudioUnitScope_Input, inNumElements, inChannelsPerElement, inSampleRate);
}
-
+
OSStatus ConfigureDynamicOutput (UInt32 inNumElements, UInt32 *inChannelsPerElement, Float64 inSampleRate)
{
return ConfigureDynamicScope (kAudioUnitScope_Output, inNumElements, inChannelsPerElement, inSampleRate);
bool GetBypass () const;
OSStatus SetBypass (bool inBypass) const;
-
+
Float64 Latency () const;
-
+
// these calls just deal with the global preset state
// you could rescope them to deal with presets on the part scope
OSStatus GetAUPreset (CFPropertyListRef &outData) const;
OSStatus SetAUPreset (CFPropertyListRef &inData);
-
+
OSStatus GetPresentPreset (AUPreset &outData) const;
-
+
OSStatus SetPresentPreset (AUPreset &inData);
-
+
bool HasCustomView () const;
-
-#pragma mark __Print
+
+#pragma mark __Print
void Print () const { Print (stdout); }
void Print (FILE* file) const;
-
+
private:
CAComponent mComp;
-
+
class AUState;
AUState* mDataPtr;
-
+
// this can throw - so wrap this up in a static that returns a result code...
CAAudioUnit (const CAComponent& inComp);
int inChannelsOut,
const AUChannelInfo * info,
UInt32 numChanInfo) const;
-
+
bool ValidateDynamicScope (AudioUnitScope inScope,
SInt32 &outTotalNumChannels,
const AUChannelInfo * info,
bool checkOutput,
const AUChannelInfo *info,
UInt32 numInfo) const;
-
+
};
class CAAUChanHelper {
}
CAAUChanHelper(const CAAudioUnit &inAU, AudioUnitScope inScope);
CAAUChanHelper (const CAAUChanHelper &c) :mChans(mStaticChans), mNumEls(0), mDidAllocate(false) { *this = c; }
-
+
~CAAUChanHelper();
CAAUChanHelper& operator= (const CAAUChanHelper &c);
UInt32 * mChans;
UInt32 mNumEls;
-
+
private:
UInt32 mStaticChans[8];
bool mDidAllocate;
*/
/*=============================================================================
CABufferList.cpp
-
+
=============================================================================*/
#include "CABufferList.h"
void CABufferList::AllocateBuffers(UInt32 nBytes)
{
if (nBytes <= GetNumBytes()) return;
-
+
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // get page faults now, not later
-
+
AudioBuffer *buf = mBuffers;
for (UInt32 i = mNumberBuffers; i--; ++buf) {
if (buf->mData != NULL && buf->mDataByteSize > 0)
}
inSetPtrList->VerifyNotTrashingOwnedBuffer();
UInt32 fromByteSize = inSrcList->GetNumBytes();
-
+
if (mNumberBuffers > 1)
// align successive buffers for Altivec and to take alternating
// cache line hits by spacing them by odd multiples of 16
UInt32 memorySize = nBytes * mNumberBuffers;
Byte *newMemory = new Byte[memorySize], *p = newMemory;
memset(newMemory, 0, memorySize); // make buffer "hot"
-
+
AudioBuffer *buf = mBuffers;
AudioBuffer *ptrBuf = inSetPtrList->mBuffers;
AudioBuffer *srcBuf = inSrcList->mBuffers;
*/
/*=============================================================================
CABufferList.h
-
+
=============================================================================*/
#ifndef __CABufferList_h__
This class is designed for use in non-simplistic cases. For AudioUnits, AUBufferList
is preferred.
-
+
CABufferList can be used in one of two ways:
- as mutable pointers into non-owned memory
- as an immutable array of buffers (owns its own memory).
if (mBufferMemory)
delete[] mBufferMemory;
}
-
+
const char * Name() { return mName; }
-
+
const AudioBufferList & GetBufferList() const { return *(AudioBufferList *)&mNumberBuffers; }
-
+
AudioBufferList & GetModifiableBufferList()
{
VerifyNotTrashingOwnedBuffer();
return _GetBufferList();
}
-
+
UInt32 GetNumBytes() const
{
return mBuffers[0].mDataByteSize;
}
-
+
void SetBytes(UInt32 nBytes, void *data)
{
VerifyNotTrashingOwnedBuffer();
mBuffers[0].mDataByteSize = nBytes;
mBuffers[0].mData = data;
}
-
+
void CopyAllFrom(CABufferList *srcbl, CABufferList *ptrbl)
// copies bytes from srcbl
// make ptrbl reflect the length copied
if (srcbl != ptrbl)
srcbl->BytesConsumed(nBytes);
}
-
+
void AppendFrom(CABufferList *blp, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
}
blp->BytesConsumed(nBytes);
}
-
+
void PadWithZeroes(UInt32 desiredBufferSize)
// for cases where an algorithm (e.g. SRC) requires some
// padding to create silence following end-of-file
buf->mDataByteSize = desiredBufferSize;
}
}
-
+
void SetToZeroes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
buf->mDataByteSize = nBytes;
}
}
-
+
void Reset()
{
DeallocateBuffers();
}
-
+
Boolean SameDataAs(const CABufferList* anotherBufferList)
{
// check to see if two buffer lists point to the same memory.
if (mNumberBuffers != anotherBufferList->mNumberBuffers) return false;
-
+
for (UInt32 i = 0; i < mNumberBuffers; ++i) {
if (mBuffers[i].mData != anotherBufferList->mBuffers[i].mData) return false;
}
return true;
}
-
+
void BytesConsumed(UInt32 nBytes)
// advance buffer pointers, decrease buffer sizes
{
buf->mDataByteSize -= nBytes;
}
}
-
+
void SetFrom(const AudioBufferList *abl)
{
VerifyNotTrashingOwnedBuffer();
memcpy(&_GetBufferList(), abl, (char *)&abl->mBuffers[abl->mNumberBuffers] - (char *)abl);
}
-
+
void SetFrom(const CABufferList *blp)
{
SetFrom(&blp->GetBufferList());
}
-
+
void SetFrom(const AudioBufferList *abl, UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
mybuf->mData = srcbuf->mData;
}
}
-
+
void SetFrom(const CABufferList *blp, UInt32 nBytes)
{
SetFrom(&blp->GetBufferList(), nBytes);
}
-
+
AudioBufferList * ToAudioBufferList(AudioBufferList *abl) const
{
memcpy(abl, &GetBufferList(), (char *)&abl->mBuffers[mNumberBuffers] - (char *)abl);
return abl;
}
-
+
void AllocateBuffers(UInt32 nBytes);
void AllocateBuffersAndCopyFrom(UInt32 nBytes, CABufferList *inCopyFromList, CABufferList *inSetPtrList);
-
+
void DeallocateBuffers();
-
+
void UseExternalBuffer(Byte *ptr, UInt32 nBytes);
void AdvanceBufferPointers(UInt32 nBytes)
buf->mDataByteSize -= nBytes;
}
}
-
+
void SetNumBytes(UInt32 nBytes)
{
VerifyNotTrashingOwnedBuffer();
bool CACFDictionary::GetBool(const CFStringRef inKey, bool& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetSInt32(const CFStringRef inKey, SInt32& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetUInt32(const CFStringRef inKey, UInt32& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetSInt64(const CFStringRef inKey, SInt64& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetUInt64(const CFStringRef inKey, UInt64& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetFloat32(const CFStringRef inKey, Float32& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetFloat64(const CFStringRef inKey, Float64& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetString(const CFStringRef inKey, CFStringRef& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
-
+
bool CACFDictionary::GetArray(const CFStringRef inKey, CFArrayRef& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
-
+
bool CACFDictionary::GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetData(const CFStringRef inKey, CFDataRef& outValue) const
{
bool theAnswer = false;
-
+
CFTypeRef theValue = NULL;
if(GetCFType(inKey, theValue))
{
theAnswer = true;
}
}
-
+
return theAnswer;
}
bool CACFDictionary::GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const
{
bool theAnswer = false;
-
+
if(mCFDictionary != NULL)
{
outValue = CFDictionaryGetValue(mCFDictionary, inKey);
theAnswer = (outValue != NULL);
}
-
+
return theAnswer;
}
bool CACFDictionary::GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const
{
bool theAnswer = false;
-
+
if(mCFDictionary != NULL)
{
CACFString theKey(inKey);
theAnswer = GetCFType(theKey.GetCFString(), outValue);
}
}
-
+
return theAnswer;
}
bool CACFDictionary::AddSInt32(const CFStringRef inKey, SInt32 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddUInt32(const CFStringRef inKey, UInt32 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddSInt64(const CFStringRef inKey, SInt64 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddUInt64(const CFStringRef inKey, UInt64 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddFloat32(const CFStringRef inKey, Float32 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddFloat64(const CFStringRef inKey, Float64 inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFNumber theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFNumber());
}
-
+
return theAnswer;
}
bool CACFDictionary::AddNumber(const CFStringRef inKey, const CFNumberRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
-
+
return theAnswer;
}
bool CACFDictionary::AddString(const CFStringRef inKey, const CFStringRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
-
+
return theAnswer;
}
bool CACFDictionary::AddArray(const CFStringRef inKey, const CFArrayRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
-
+
return theAnswer;
}
bool CACFDictionary::AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
-
+
return theAnswer;
}
bool CACFDictionary::AddData(const CFStringRef inKey, const CFDataRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
theAnswer = AddCFType(inKey, inValue);
}
-
+
return theAnswer;
}
bool CACFDictionary::AddCFType(const CFStringRef inKey, const CFTypeRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CFDictionarySetValue(mCFDictionary, inKey, inValue);
theAnswer = true;
}
-
+
return theAnswer;
}
bool CACFDictionary::AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFString theKey(inKey);
theAnswer = AddCFType(theKey.GetCFString(), inValue);
}
}
-
+
return theAnswer;
}
bool CACFDictionary::AddCString(const CFStringRef inKey, const char* inValue)
{
bool theAnswer = false;
-
+
if(mMutable && (mCFDictionary != NULL))
{
CACFString theValue(inValue);
theAnswer = AddCFType(inKey, theValue.GetCFString());
}
}
-
+
return theAnswer;
}
CACFDictionary(const CACFDictionary& inDictionary) : mCFDictionary(inDictionary.mCFDictionary), mRelease(inDictionary.mRelease), mMutable(inDictionary.mMutable) { if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } }
CACFDictionary& operator=(const CACFDictionary& inDictionary) { mCFDictionary = inDictionary.mCFDictionary; mRelease = inDictionary.mRelease; mMutable = inDictionary.mMutable; if(mRelease && (mCFDictionary != NULL)) { CFRetain(mCFDictionary); } return *this; }
~CACFDictionary() { if(mRelease && (mCFDictionary != NULL)) { CFRelease(mCFDictionary); } }
-
+
// Attributes
public:
bool IsValid() const { return mCFDictionary != NULL; }
bool IsMutable() const { return mMutable;}
bool CanModify() const { return mMutable && (mCFDictionary != NULL); }
-
+
bool WillRelease() const { return mRelease; }
void ShouldRelease(bool inRelease) { mRelease = inRelease; }
-
+
CFDictionaryRef GetDict() const { return mCFDictionary; }
CFDictionaryRef GetCFDictionary() const { return mCFDictionary; }
CFDictionaryRef CopyCFDictionary() const { if(mCFDictionary != NULL) { CFRetain(mCFDictionary); } return mCFDictionary; }
bool HasKey(const CFStringRef inKey) const;
UInt32 Size() const;
void GetKeys(const void** keys) const;
-
+
bool GetBool(const CFStringRef inKey, bool& outValue) const;
bool GetSInt32(const CFStringRef inKey, SInt32& outValue) const;
bool GetUInt32(const CFStringRef inKey, UInt32& outValue) const;
bool GetUInt64(const CFStringRef inKey, UInt64& outValue) const;
bool GetFloat32(const CFStringRef inKey, Float32& outValue) const;
bool GetFloat64(const CFStringRef inKey, Float64& outValue) const;
- bool GetString(const CFStringRef inKey, CFStringRef& outValue) const;
- bool GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;
- bool GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;
+ bool GetString(const CFStringRef inKey, CFStringRef& outValue) const;
+ bool GetArray(const CFStringRef inKey, CFArrayRef& outValue) const;
+ bool GetDictionary(const CFStringRef inKey, CFDictionaryRef& outValue) const;
bool GetData(const CFStringRef inKey, CFDataRef& outValue) const;
bool GetCFType(const CFStringRef inKey, CFTypeRef& outValue) const;
-
+
bool GetCFTypeWithCStringKey(const char* inKey, CFTypeRef& outValue) const;
bool AddSInt32(const CFStringRef inKey, SInt32 inValue);
bool AddDictionary(const CFStringRef inKey, const CFDictionaryRef inValue);
bool AddData(const CFStringRef inKey, const CFDataRef inValue);
bool AddCFType(const CFStringRef inKey, const CFTypeRef inValue);
-
+
bool AddCFTypeWithCStringKey(const char* inKey, const CFTypeRef inValue);
bool AddCString(const CFStringRef inKey, const char* inValue);
void Clear() { if(CanModify()) { CFDictionaryRemoveAllValues(mCFDictionary); } }
-
+
void Show() { CFShow(mCFDictionary); }
-
+
// Implementation
private:
CFMutableDictionaryRef mCFDictionary;
Float32 CACFNumber::GetFixed32() const
{
SInt32 theFixedValue = GetSInt32();
-
+
// this is a 16.16 value so convert it to a float
Float32 theSign = theFixedValue < 0 ? -1.0 : 1.0;
theFixedValue *= (SInt32)theSign;
Float32 theWholePart = (theFixedValue & 0x7FFF0000) >> 16;
Float32 theFractPart = theFixedValue & 0x0000FFFF;
theFractPart /= 65536.0;
-
+
return theSign * (theWholePart + theFractPart);
}
private:
void Retain() { if(mWillRelease && (mCFNumber != NULL)) { CFRetain(mCFNumber); } }
void Release() { if(mWillRelease && (mCFNumber != NULL)) { CFRelease(mCFNumber); } }
-
+
CFNumberRef mCFNumber;
bool mWillRelease;
UInt32 CACFString::GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding)
{
UInt32 theAnswer = 0;
-
+
if(inCFString != NULL)
{
CFRange theRange = { 0, CFStringGetLength(inCFString) };
CFStringGetBytes(inCFString, theRange, inEncoding, 0, false, NULL, 0x7FFFFFFF, (CFIndex*)&theAnswer);
}
-
+
return theAnswer;
}
private:
void Retain() { if(mWillRelease && (mCFString != NULL)) { CFRetain(mCFString); } }
void Release() { if(mWillRelease && (mCFString != NULL)) { CFRelease(mCFString); } }
-
+
CFStringRef mCFString;
bool mWillRelease;
static UInt32 GetStringByteLength(CFStringRef inCFString, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
static void GetCString(CFStringRef inCFString, char* outString, UInt32& ioStringSize, CFStringEncoding inEncoding = kCFStringEncodingUTF8);
static void GetUnicodeString(CFStringRef inCFString, UInt16* outString, UInt32& ioStringSize);
-
+
};
inline bool operator<(const CACFString& x, const CACFString& y) { return CFStringCompare(x.GetCFString(), y.GetCFString(), 0) == kCFCompareLessThan; }
private:
void Retain() { if(mWillRelease && (mCFMutableString != NULL)) { CFRetain(mCFMutableString); } }
void Release() { if(mWillRelease && (mCFMutableString != NULL)) { CFRelease(mCFMutableString); } }
-
+
CFMutableStringRef mCFMutableString;
bool mWillRelease;
ResFileRefNum componentResFileID = kResFileNotOpened;
OSStatus result;
short thngResourceCount;
-
+
short curRes = CurResFile();
require_noerr (result = OpenAComponentResFile( mComp, &componentResFileID), home);
require_noerr (result = componentResFileID <= 0, home);
-
+
UseResFile(componentResFileID);
thngResourceCount = Count1Resources(kComponentResourceType);
-
+
require_noerr (result = ResError(), home);
// only go on if we successfully found at least 1 thng resource
require_noerr (thngResourceCount <= 0 ? -1 : 0, home);
if (!versionFound)
result = resNotFound;
-
+
UseResFile(curRes); // revert
-
+
if ( componentResFileID != kResFileNotOpened )
CloseComponentResFile(componentResFileID);
-
+
home:
return result;
}
Handle h1 = NewHandle(4);
CAComponentDescription desc;
OSStatus err = GetComponentInfo (Comp(), &desc, h1, 0, 0);
-
+
if (err) { DisposeHandle(h1); return; }
-
+
HLock(h1);
char* ptr1 = *h1;
// Get the manufacturer's name... look for the ':' character convention
char* displayStr = 0;
const_cast<CAComponent*>(this)->mCompName = CFStringCreateWithPascalString(NULL, (const unsigned char*)*h1, kCFStringEncodingMacRoman);
-
+
for (int i = 0; i < len; ++i) {
if (ptr1[i] == ':') { // found the name
ptr1[i] = 0;
break;
}
}
-
+
if (displayStr)
{
const_cast<CAComponent*>(this)->mManuName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman);
-
+
//move displayStr ptr past the manu, to the name
// we move the characters down a index, because the handle doesn't have any room
// at the end for the \0
const_cast<CAComponent*>(this)->mAUName = CFStringCreateWithCString(NULL, displayStr, kCFStringEncodingMacRoman);
}
-
+
DisposeHandle (h1);
}
}
public:
CAComponent ()
: mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) {}
-
+
// if next is specifed that is used to find the next component after that one
CAComponent (const ComponentDescription& inDesc, CAComponent* next = 0);
-
+
CAComponent (const CAComponent& y)
: mComp (0), mDesc(), mManuName(0), mAUName(0), mCompName(0), mCompInfo (0) { *this = y; }
CAComponent (const Component& comp);
-
+
CAComponent (const ComponentInstance& compInst);
CAComponent (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
-
+
~CAComponent ();
-
+
CAComponent& operator= (const CAComponent& y);
-
+
// returns true if this object references a valid component
bool IsValid () const { return Comp() != 0; }
-
+
bool HasAUStrings() const { SetCompNames (); return mManuName != 0; }
// CFStringRef should be retained by caller if needed beyond lifetime of this object
-
+
// Can return NULL if component doesn't follow AU naming conventions
CFStringRef GetAUManu () const { SetCompNames (); return mManuName; }
CFStringRef GetAUName () const { SetCompNames (); return mAUName ? mAUName : mCompName; }
-
+
// Return value of NULL indicates a problem getting that information from the component
CFStringRef GetCompName () const { SetCompNames(); return mCompName; }
CFStringRef GetCompInfo () const { SetCompInfo(); return mCompInfo; }
-
+
const CAComponentDescription& Desc () const { return mDesc; }
-
+
OSStatus Open (ComponentInstance& outInst) const
{
return OpenAComponent (Comp(), &outInst);
}
OSStatus GetResourceVersion (UInt32 &outVersion) const;
-
+
const Component& Comp() const { return mComp; }
-
+
void Print(FILE* file = stdout) const;
OSStatus Save (CFPropertyListRef *outData) const;
-
+
OSStatus Restore (CFPropertyListRef &inData);
-
+
private:
Component mComp;
CAComponentDescription mDesc;
-
+
CFStringRef mManuName, mAUName, mCompName, mCompInfo;
void SetCompNames () const;
char str[24];
fprintf (file, "ComponentDescription: %s - ", StringForOSType(desc->componentType, str));
fprintf (file, "%s - ", StringForOSType(desc->componentSubType, str));
- fprintf (file, "%s", StringForOSType(desc->componentManufacturer, str));
+ fprintf (file, "%s", StringForOSType(desc->componentManufacturer, str));
fprintf (file, ", 0x%lX, 0x%lX\n", desc->componentFlags, desc->componentFlagsMask);
}
}
{
bool flag = IsEffect() || IsMusicDevice() || IsOffline();
if (flag) return true;
-
+
switch (componentType) {
case kAudioUnitType_Output:
case kAudioUnitType_FormatConverter:
bool CAComponentDescription::Matches (const ComponentDescription &desc) const
{
bool matches = false;
-
+
// see if the type matches
matches = _MatchTest (componentType, desc.componentType);
-
+
if (matches)
matches = _MatchTest (componentSubType, desc.componentSubType);
-
+
if (matches)
matches = _MatchTest (componentManufacturer, desc.componentManufacturer);
-
+
return matches;
}
*/
/*=============================================================================
CAComponentDescription.h
-
+
=============================================================================*/
#ifndef __CAComponentDescription_h__
class CAComponentDescription : public ComponentDescription {
public:
CAComponentDescription() { memset (this, 0, sizeof (ComponentDescription)); }
-
+
CAComponentDescription (OSType inType, OSType inSubtype = 0, OSType inManu = 0);
CAComponentDescription(const ComponentDescription& desc) { memcpy (this, &desc, sizeof (ComponentDescription)); }
-
+
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// interrogation
-
+
bool IsAU () const;
-
+
bool IsAUFX() const { return componentType == kAudioUnitType_Effect; }
bool IsAUFM() const { return componentType == kAudioUnitType_MusicEffect; }
-
+
bool IsEffect () const { return IsAUFX() || IsAUFM() || IsPanner(); }
-
+
bool IsOffline () const { return componentType == 'auol'; }
-
+
bool IsFConv () const { return componentType == kAudioUnitType_FormatConverter; }
-
+
bool IsPanner () const { return componentType == kAudioUnitType_Panner; }
-
+
bool IsMusicDevice () const { return componentType == kAudioUnitType_MusicDevice; }
-
+
#ifndef MAC_OS_X_VERSION_10_4
bool IsGenerator () const { return componentType =='augn'; }
#else
bool IsGenerator () const { return componentType ==kAudioUnitType_Generator; }
#endif
-
+
bool IsOutput () const { return componentType == kAudioUnitType_Output; }
-
+
bool IsSource () const { return IsMusicDevice() || IsGenerator(); }
-
+
OSType Type () const { return componentType; }
OSType SubType () const { return componentSubType; }
OSType Manu () const { return componentManufacturer; }
int Count() const { return CountComponents(const_cast<CAComponentDescription*>(this)); }
-
+
// does a semantic match where "wild card" values for type, subtype, manu will match
bool Matches (const ComponentDescription &desc) const;
-
+
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// other
-
+
void Print(FILE* file = stdout) const { _CAShowComponentDescription (this, file); }
OSStatus Save (CFPropertyListRef *outData) const;
#pragma mark Basic Definitions
#if DEBUG || CoreAudio_Debug
-
+
// can be used to break into debugger immediately, also see CADebugger
#define BusError() (*(long *)0 = 0)
-
+
// basic debugging print routines
#if TARGET_OS_MAC && !TARGET_API_MAC_CARBON
extern pascal void DebugStr(const unsigned char* debuggerMsg);
#define DebugMessageN3(msg, N1, N2, N3)
#else
#include "CADebugPrintf.h"
-
+
#if (CoreAudio_FlushDebugMessages && !CoreAudio_UseSysLog) || defined(CoreAudio_UseSideFile)
#define FlushRtn ;fflush(DebugPrintfFile)
#else
#define FlushRtn
#endif
-
+
#if CoreAudio_ThreadStampMessages
#include <pthread.h>
#include "CAHostTimeBase.h"
#else
#define vprint(msg)
#endif
-
+
#if CoreAudio_StopOnFailure
#include "CADebugger.h"
#define STOP CADebuggerStop()
*/
/*=============================================================================
CAMath.h
-
+
=============================================================================*/
#ifndef __CAMath_h__
*/
/*=============================================================================
CAReferenceCounted.h
-
+
=============================================================================*/
#ifndef __CAReferenceCounted_h__
class CAReferenceCounted {
public:
CAReferenceCounted() : mRefCount(1) {}
-
+
void retain() { IncrementAtomic(&mRefCount); }
-
+
void release()
{
// this returns the ORIGINAL value, not the new one.
char formatID[5];
*(UInt32 *)formatID = CFSwapInt32HostToBig(mFormatID);
formatID[4] = '\0';
- fprintf(f, "%2ld ch, %6.0f Hz, '%-4.4s' (0x%08lX) ",
+ fprintf(f, "%2ld ch, %6.0f Hz, '%-4.4s' (0x%08lX) ",
NumberChannels(), mSampleRate, formatID,
mFormatFlags);
if (mFormatID == kAudioFormatLinearPCM) {
((mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh) ? " high-aligned" : " low-aligned") : "";
const char *deinter = (mFormatFlags & kAudioFormatFlagIsNonInterleaved) ? ", deinterleaved" : "";
const char *commaSpace = (packed[0]!='\0') || (align[0]!='\0') ? ", " : "";
-
+
fprintf(f, "%ld-bit%s%s %s%s%s%s%s\n",
mBitsPerChannel, endian, sign, floatInt,
commaSpace, packed, align, deinter);
fprintf(f, "from %d-bit source, ", sourceBits);
else
fprintf(f, "from UNKNOWN source bit depth, ");
-
+
fprintf(f, "%ld frames/packet\n", mFramesPerPacket);
}
else
theEndianString = "Little Endian";
#endif
}
-
+
const char* theKindString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
{
{
theKindString = (inAbbreviate ? "UInt" : "Unsigned Integer");
}
-
+
const char* thePackingString = NULL;
if((inDescription.mFormatFlags & kAudioFormatFlagIsPacked) == 0)
{
thePackingString = "Low";
}
}
-
+
const char* theMixabilityString = NULL;
if((inDescription.mFormatFlags & kIsNonMixableFlag) == 0)
{
{
theMixabilityString = "Unmixable";
}
-
+
if(inAbbreviate)
{
if(theEndianString != NULL)
}
}
break;
-
+
case kAudioFormatAC3:
strcpy(outName, "AC-3");
break;
-
+
case kAudioFormat60958AC3:
strcpy(outName, "AC-3 for SPDIF");
break;
-
+
default:
{
char* the4CCString = (char*)&inDescription.mFormatID;
{
bool theAnswer = false;
bool isDone = false;
-
+
// note that if either side is 0, that field is skipped
-
+
// format ID is the first order sort
if((!isDone) && ((x.mFormatID != 0) && (y.mFormatID != 0)))
{
isDone = true;
}
}
-
-
+
+
// mixable is always better than non-mixable for linear PCM and should be the second order sort item
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
isDone = true;
}
}
-
+
// floating point vs integer for linear PCM only
if((!isDone) && ((x.mFormatID == kAudioFormatLinearPCM) && (y.mFormatID == kAudioFormatLinearPCM)))
{
isDone = true;
}
}
-
+
// bit depth
if((!isDone) && ((x.mBitsPerChannel != 0) && (y.mBitsPerChannel != 0)))
{
isDone = true;
}
}
-
+
// sample rate
if((!isDone) && fnonzero(x.mSampleRate) && fnonzero(y.mSampleRate))
{
isDone = true;
}
}
-
+
// number of channels
if((!isDone) && ((x.mChannelsPerFrame != 0) && (y.mChannelsPerFrame != 0)))
{
isDone = true;
}
}
-
+
return theAnswer;
}
{
UInt32 xFlags = x.mFormatFlags;
UInt32 yFlags = y.mFormatFlags;
-
+
// match wildcards
if (x.mFormatID == 0 || y.mFormatID == 0 || xFlags == 0 || yFlags == 0)
return true;
-
+
if (x.mFormatID == kAudioFormatLinearPCM)
- {
+ {
// knock off the all clear flag
xFlags = xFlags & ~kAudioFormatFlagsAreAllClear;
yFlags = yFlags & ~kAudioFormatFlagsAreAllClear;
-
+
// if both kAudioFormatFlagIsPacked bits are set, then we don't care about the kAudioFormatFlagIsAlignedHigh bit.
if (xFlags & yFlags & kAudioFormatFlagIsPacked) {
xFlags = xFlags & ~kAudioFormatFlagIsAlignedHigh;
yFlags = yFlags & ~kAudioFormatFlagIsAlignedHigh;
}
-
+
// if both kAudioFormatFlagIsFloat bits are set, then we don't care about the kAudioFormatFlagIsSignedInteger bit.
if (xFlags & yFlags & kAudioFormatFlagIsFloat) {
xFlags = xFlags & ~kAudioFormatFlagIsSignedInteger;
yFlags = yFlags & ~kAudioFormatFlagIsSignedInteger;
}
-
+
// if the bit depth is 8 bits or less and the format is packed, we don't care about endianness
if((x.mBitsPerChannel <= 8) && ((xFlags & kAudioFormatFlagIsPacked) == kAudioFormatFlagIsPacked))
{
{
yFlags = yFlags & ~kAudioFormatFlagIsBigEndian;
}
-
+
// if the number of channels is 0 or 1, we don't care about non-interleavedness
if (x.mChannelsPerFrame <= 1 && y.mChannelsPerFrame <= 1) {
xFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
// the semantics for equality are:
// 1) Values must match exactly
// 2) wildcard's are ignored in the comparison
-
+
#define MATCH(name) ((x.name) == 0 || (y.name) == 0 || (x.name) == (y.name))
-
+
return
// check the sample rate
(fiszero(x.mSampleRate) || fiszero(y.mSampleRate) || fequal(x.mSampleRate, y.mSampleRate))
-
+
// check the format ids
&& MATCH(mFormatID)
-
+
// check the format flags
&& MatchFormatFlags(x, y)
-
+
// check the bytes per packet
&& MATCH(mBytesPerPacket)
-
+
// check the frames per packet
&& MATCH(mFramesPerPacket)
-
+
// check the bytes per frame
&& MATCH(mBytesPerFrame)
-
+
// check the channels per frame
&& MATCH(mChannelsPerFrame)
-
+
// check the channels per frame
&& MATCH(mBitsPerChannel) ;
}
*/
/*=============================================================================
CAStreamBasicDescription.h
-
+
=============================================================================*/
#ifndef __CAStreamBasicDescription_h__
// Construction/Destruction
public:
CAStreamBasicDescription() { memset (this, 0, sizeof(AudioStreamBasicDescription)); }
-
+
CAStreamBasicDescription(const AudioStreamBasicDescription &desc)
{
SetFrom(desc);
}
-
+
CAStreamBasicDescription( double inSampleRate, UInt32 inFormatID,
UInt32 inBytesPerPacket, UInt32 inFramesPerPacket,
UInt32 inBytesPerFrame, UInt32 inChannelsPerFrame,
{
memcpy(this, &desc, sizeof(AudioStreamBasicDescription));
}
-
+
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// interrogation
-
+
bool IsPCM() const { return mFormatID == kAudioFormatLinearPCM; }
-
+
bool PackednessIsSignificant() const
{
Assert(IsPCM(), "PackednessIsSignificant only applies for PCM");
return (SampleWordSize() << 3) != mBitsPerChannel;
}
-
+
bool AlignmentIsSignificant() const
{
return PackednessIsSignificant() || (mBitsPerChannel & 7) != 0;
}
-
+
bool IsInterleaved() const
{
return !IsPCM() || !(mFormatFlags & kAudioFormatFlagIsNonInterleaved);
}
-
+
// for sanity with interleaved/deinterleaved possibilities, never access mChannelsPerFrame, use these:
- UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
+ UInt32 NumberInterleavedChannels() const { return IsInterleaved() ? mChannelsPerFrame : 1; }
UInt32 NumberChannelStreams() const { return IsInterleaved() ? 1 : mChannelsPerFrame; }
UInt32 NumberChannels() const { return mChannelsPerFrame; }
UInt32 SampleWordSize() const { return (mBytesPerFrame > 0) ? mBytesPerFrame / NumberInterleavedChannels() : 0;}
Assert(mBytesPerFrame > 0, "bytesPerFrame must be > 0 in BytesToFrames");
return nbytes / mBytesPerFrame;
}
-
+
bool SameChannelsAndInterleaving(const CAStreamBasicDescription &a) const
{
return this->NumberChannels() == a.NumberChannels() && this->IsInterleaved() == a.IsInterleaved();
}
-
+
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// manipulation
-
+
void SetCanonical(UInt32 nChannels, bool interleaved)
// note: leaves sample rate untouched
{
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
-
+
void ChangeNumberChannels(UInt32 nChannels, bool interleaved)
// alter an existing format
{
mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
}
}
-
+
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//
// other
-
+
void Print() const
{
Print (stdout);
void Print(FILE* file) const
{
- PrintFormat (file, "", "AudioStreamBasicDescription:");
+ PrintFormat (file, "", "AudioStreamBasicDescription:");
}
void PrintFormat(FILE *f, const char *indent, const char *name) const;
OSStatus Save(CFPropertyListRef *outData) const;
-
+
OSStatus Restore(CFPropertyListRef &inData);
// Operations
*/
/*=============================================================================
CAXException.cpp
-
+
=============================================================================*/
#include "CAXException.h"
*/
/*=============================================================================
CAXException.h
-
+
=============================================================================*/
#ifndef __CAXException_h__
} else
strcpy(mOperation, operation);
}
-
+
char *FormatError(char *str) const
{
return FormatError(str, mError);
}
-
+
char mOperation[256];
const OSStatus mError;
-
+
// -------------------------------------------------
-
+
typedef void (*WarningHandler)(const char *msg, OSStatus err);
-
+
/*static void Throw(const char *operation, OSStatus err)
{
throw CAXException(operation, err);
}*/
-
+
static char *FormatError(char *str, OSStatus error)
{
// see if it appears to be a 4-char-code
sprintf(str, "%ld", error);
return str;
}
-
+
static void Warning(const char *s, OSStatus error)
{
if (sWarningHandler)
(*sWarningHandler)(s, error);
}
-
+
static void SetWarningHandler(WarningHandler f) { sWarningHandler = f; }
private:
static WarningHandler sWarningHandler;
LIBARDOUR_API void make_property_quarks ();
extern LIBARDOUR_API PBD::PropertyChange bounds_change;
-
+
extern LIBARDOUR_API const char* const ardour_config_info;
LIBARDOUR_API void find_bindings_files (std::map<std::string,std::string>&);
static pthread_t get_process_thread () { return _process_thread; }
static bool is_process_thread();
- private:
+ private:
bool _currently_in_cycle;
MIDI::timestamp_t _last_write_timestamp;
bool have_timer;
int create_port ();
/** Channel used to signal to the MidiControlUI that input has arrived */
-
+
std::string _connections;
PBD::ScopedConnection connect_connection;
PBD::ScopedConnection halt_connection;
const Sample* const src_raw = src + src_offset;
mix_buffers_no_gain(dst_raw, src_raw, len);
-
+
_silent = false;
_written = true;
}
private:
boost::shared_ptr<Diskstream> diskstream_factory (XMLNode const &);
-
+
int deprecated_use_diskstream_connections ();
void set_state_part_two ();
void set_state_part_three ();
bool parameter_is_control (uint32_t) const;
bool parameter_is_input (uint32_t) const;
bool parameter_is_output (uint32_t) const;
-
+
void set_info (PluginInfoPtr);
int set_state(const XMLNode& node, int);
* countdown, whose duration will be reduced to half of its previous
* value.
*/
-
+
PBD::Signal0<void> BecameSilent;
void reset_silence_countdown ();
-
+
private:
AudioEngine ();
#ifdef SILENCE_AFTER
framecnt_t _silence_countdown;
uint32_t _silence_hit_cnt;
-#endif
+#endif
};
-
+
} // namespace ARDOUR
#endif /* __ardour_audioengine_h__ */
void set_default_fade_out ();
framecnt_t verify_xfade_bounds (framecnt_t, bool start);
-
+
void set_envelope_active (bool yn);
void set_default_envelope ();
private:
friend class ::AudioRegionReadTest;
friend class ::PlaylistReadTest;
-
+
PBD::Property<bool> _envelope_active;
PBD::Property<bool> _default_fade_in;
PBD::Property<bool> _default_fade_out;
AutomationListProperty (PBD::PropertyDescriptor<boost::shared_ptr<AutomationList> > d, Ptr o, Ptr c)
: PBD::SharedStatefulProperty<AutomationList> (d.property_id, o, c)
{}
-
+
PBD::PropertyBase* clone () const;
-
+
private:
/* No copy-construction nor assignment */
AutomationListProperty (AutomationListProperty const &);
void load_mandatory_protocols ();
void midi_connectivity_established ();
void drop_protocols ();
-
+
int activate (ControlProtocolInfo&);
int deactivate (ControlProtocolInfo&);
-
+
std::list<ControlProtocolInfo*> control_protocol_info;
static const std::string state_node_name;
private:
bool _no_outs_cuz_we_no_monitor;
boost::shared_ptr<MuteMaster> _mute_master;
-
+
static bool panners_legal;
static PBD::Signal0<void> PannersLegal;
std::string device_name; ///< state device name
ARDOUR::framecnt_t sample_rate; ///< sample rate used by the device in this state
ARDOUR::pframes_t buffer_size; ///< buffer size used by the device in this state
-
+
PortStateList input_channel_states; ///< states of device Audio inputs
PortStateList multi_out_channel_states; ///< states of device Audio inputs in Multi Out mode
PortStateList stereo_out_channel_states; ///< states of device Audio inputs in Stereo Out mode
std::string format_name () const { return _format_name; }
Type type () const { return _type; }
-
+
FormatId format_id () const {
if (!format_ids.empty() )
return *format_ids.begin();
else
return FormatId(0);
}
-
+
Endianness endianness () const {
if (!endiannesses.empty() )
return *endiannesses.begin();
else
return Endianness(0);
}
-
+
SampleFormat sample_format () const {
if (!sample_formats.empty() )
return *sample_formats.begin();
else
return SampleFormat(0);
}
-
+
SampleRate sample_rate () const {
if (!sample_rates.empty() )
return *sample_rates.begin();
else
return SampleRate(0);
-
+
}
-
+
Quality quality () const {
if (!qualities.empty() )
return *qualities.begin();
virtual ~FileSource ();
const std::string& path() const { return _path; }
-
+
virtual bool safe_file_extension (const std::string& path) const = 0;
int move_to_trash (const std::string& trash_dir_name);
const std::string& origin() const { return _origin; }
virtual void set_path (const std::string&);
-
+
static PBD::Signal2<int,std::string,std::vector<std::string> > AmbiguousFileName;
void existence_check ();
class Route;
class Session;
-class GraphEdges;
+class GraphEdges;
typedef boost::shared_ptr<GraphNode> node_ptr_t;
typedef std::set< node_ptr_t > node_set_t;
typedef std::list< node_ptr_t > node_list_t;
-/** A node on our processing graph, ie a Route */
+/** A node on our processing graph, ie a Route */
class LIBARDOUR_API GraphNode
{
public:
void set_record_enabled (bool yn);
void set_record_safe (bool yn);
-
+
void reset_tracker ();
void resolve_tracker (Evoral::EventSink<framepos_t>& buffer, framepos_t time);
void set_always_parse (bool yn);
void set_trace_on (bool yn);
-
+
MIDI::Parser& self_parser() { return _self_parser; }
protected:
bool _input_active;
bool _always_parse;
bool _trace_on;
-
+
/* Naming this is tricky. AsyncMIDIPort inherits (for now, aug 2013) from
* both MIDI::Port, which has _parser, and this (ARDOUR::MidiPort). We
* need parsing support in this object, independently of what the
};
} /* namespace */
-
+
#endif /* __libardour_scene_change_h__ */
MidiChannelFilter _capture_filter;
virtual boost::shared_ptr<Diskstream> diskstream_factory (XMLNode const &);
-
+
boost::shared_ptr<MidiDiskstream> midi_diskstream () const;
void write_out_of_band_data (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, framecnt_t nframes);
public:
MidiPortManager();
virtual ~MidiPortManager ();
-
+
/* Ports used for control. These are read/written to outside of the
* process callback (asynchronously with respect to when data
* actually arrives).
int set_state (const XMLNode&, int version);
XMLNode& get_state ();
-
+
boost::shared_ptr<Pannable> pannable() const { return _pannable; }
static bool equivalent (pan_t a, pan_t b) {
void set_layer (boost::shared_ptr<Region>, double);
void set_capture_insertion_in_progress (bool yn);
-
+
protected:
friend class Session;
struct PresetRecord {
PresetRecord () : number (-1), user (true) {}
PresetRecord (const std::string& u, const std::string& l, int n = -1, bool s = true) : uri (u), label (l), number (n), user (s) {}
-
+
bool operator!= (PresetRecord const & a) const {
return number != a.number || uri != a.uri || label != a.label;
}
-
+
std::string uri;
std::string label;
int number; // if <0, invalid
struct Match {
Match () : method (Impossible), plugins (0) {}
Match (MatchingMethod m, int32_t p, ChanCount h = ChanCount ()) : method (m), plugins (p), hide (h) {}
-
+
MatchingMethod method; ///< method to employ
int32_t plugins; ///< number of copies of the plugin that we need
ChanCount hide; ///< number of channels to hide
int windows_vst_discover_from_path (std::string path, bool cache_only = false);
int windows_vst_discover (std::string path, bool cache_only = false);
-
+
int lxvst_discover_from_path (std::string path, bool cache_only = false);
int lxvst_discover (std::string path, bool cache_only = false);
public:
PortRegistrationFailure (std::string const & why = "")
: reason (why) {}
-
+
~PortRegistrationFailure () throw () {}
-
+
const char *what() const throw () { return reason.c_str(); }
-
+
private:
std::string reason;
};
* Realtime safe.
*/
void cycle_start (pframes_t nframes);
-
+
/** Signal the end of an audio cycle.
* This signifies that the cycle began with @ref cycle_start has ended.
* This MUST be called at the end of each cycle.
};
-
+
} // namespace
#endif /* __libardour_port_manager_h__ */
Evoral::Range<framepos_t> last_range () const {
return Evoral::Range<framepos_t> (_last_position, _last_position + _last_length - 1);
}
-
+
Evoral::Range<framepos_t> range () const {
return Evoral::Range<framepos_t> (first_frame(), last_frame());
}
virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute);
virtual void set_length_internal (framecnt_t);
virtual void set_start_internal (framecnt_t);
-
+
DataType _type;
PBD::Property<bool> _sync_marked;
PBD::Property<framepos_t> _position;
/** Sync position relative to the start of our file */
PBD::Property<framepos_t> _sync_position;
-
+
SourceList _sources;
/** Used when timefx are applied, so we can always use the original source */
SourceList _master_sources;
AnalysisFeatureList _transients;
-
+
boost::weak_ptr<ARDOUR::Playlist> _playlist;
-
+
private:
void mid_thaw (const PBD::PropertyChange&);
* announce=false but they still need to be in the map soon after
* creation.
*/
-
+
static void map_add (boost::shared_ptr<Region>);
private:
namespace ARDOUR {
extern LIBARDOUR_API const char* revision;
-
+
extern "C" {
LIBARDOUR_API const char* get_ardour_revision();
}
virtual MonitorState monitoring_state () const;
virtual MeterState metering_state () const;
-
+
/* these are the core of the API of a Route. see the protected sections as well */
virtual int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool muted () const;
void set_mute (bool yn, void* src);
-
+
bool muted_by_others() const;
/* controls use set_solo() to modify this route's solo state
uint32_t _solo_isolated_by_upstream;
void mod_solo_isolated_by_upstream (bool, void*);
-
+
bool _denormal_protection;
bool _recordable : 1;
Route (Route const &);
void maybe_note_meter_position ();
-
+
/** true if we've made a note of a custom meter position in these variables */
bool _custom_meter_position_noted;
/** the processor that came after the meter when it was last set to a custom position,
{
public:
typedef std::map<GraphVertex, std::set<GraphVertex> > EdgeMap;
-
+
void add (GraphVertex from, GraphVertex to, bool via_sends_only);
bool has (GraphVertex from, GraphVertex to, bool* via_sends_only);
std::set<GraphVertex> from (GraphVertex r) const;
bool has_none_to (GraphVertex to) const;
bool empty () const;
void dump () const;
-
+
private:
void insert (EdgeMap& e, GraphVertex a, GraphVertex b);
-
+
typedef std::multimap<GraphVertex, std::pair<GraphVertex, bool> > EdgeMapWithSends;
-
+
EdgeMapWithSends::iterator find_in_from_to_with_sends (GraphVertex, GraphVertex);
/** map of edges with from as `first' and to as `second' */
};
} /* namespace */
-
+
#endif /* __libardour_scene_change_h__ */
public:
SceneChanger (Session& s) : SessionHandleRef (s) {}
virtual ~SceneChanger () {};
-
+
virtual void run (framepos_t start, framepos_t end) = 0;
virtual void locate (framepos_t where) = 0;
};
} /* namespace */
-
+
#endif /* __libardour_scene_change_h__ */
bool set_name (const std::string& str);
std::string value_as_string (boost::shared_ptr<AutomationControl>) const;
-
+
static uint32_t how_many_sends();
static std::string name_and_id_new_send (Session&, Delivery::Role r, uint32_t&, bool);
/* Timecode status signals */
PBD::Signal1<void, bool> MTCSyncStateChanged;
- PBD::Signal1<void, bool> LTCSyncStateChanged;
+ PBD::Signal1<void, bool> LTCSyncStateChanged;
/* Record status signals */
/* Timecode state signals */
PBD::Signal0<void> MtcOrLtcInputPortChanged;
-
+
void queue_event (SessionEvent*);
void request_roll_at_and_return (framepos_t start, framepos_t return_to);
framecnt_t worst_input_latency () const { return _worst_input_latency; }
framecnt_t worst_track_latency () const { return _worst_track_latency; }
framecnt_t worst_playback_latency () const { return _worst_output_latency + _worst_track_latency; }
-
+
struct SaveAs {
std::string new_parent_folder; /* parent folder where new session folder will be created */
std::string new_name; /* name of newly saved session */
bool copy_external; /* true if external media should be consolidated into the newly saved session; false otherwise */
std::string final_session_folder_name; /* filled in by * Session::save_as(), provides full path to newly saved session */
-
+
/* emitted as we make progress. 3 arguments passed to signal
* handler:
*
AudioEngine const & engine () const { return _engine; }
static std::string default_track_name_pattern (DataType);
-
+
/* Time */
framepos_t transport_frame () const {return _transport_frame; }
bool synced_to_engine() const { return _slave && config.get_external_sync() && Config->get_sync_source() == Engine; }
bool synced_to_mtc () const { return config.get_external_sync() && Config->get_sync_source() == MTC && g_atomic_int_get (const_cast<gint*>(&_mtc_active)); }
bool synced_to_ltc () const { return config.get_external_sync() && Config->get_sync_source() == LTC && g_atomic_int_get (const_cast<gint*>(&_ltc_active)); }
-
+
double transport_speed() const { return _transport_speed; }
bool transport_stopped() const { return _transport_speed == 0.0f; }
bool transport_rolling() const { return _transport_speed != 0.0f; }
void set_object_selection (framepos_t start, framepos_t end);
void clear_range_selection ();
void clear_object_selection ();
-
+
/* buffers for gain and pan */
gain_t* gain_automation_buffer () const;
void* ptr,
float opt
);
-
+
static PBD::Signal0<void> SendFeedback;
/* Speakers */
boost::shared_ptr<MidiPort> scene_in () const;
boost::shared_ptr<MidiPort> scene_out () const;
-
+
boost::shared_ptr<MidiPort> midi_clock_output_port () const;
boost::shared_ptr<MidiPort> midi_clock_input_port () const;
boost::shared_ptr<MidiPort> mtc_output_port () const;
void reconnect_ltc_input ();
void reconnect_ltc_output ();
-
+
protected:
friend class AudioEngine;
void set_block_size (pframes_t nframes);
PBD::ScopedConnection mtc_status_connection;
void ltc_status_changed (bool);
PBD::ScopedConnection ltc_status_connection;
-
+
void initialize_latencies ();
void set_worst_io_latencies ();
void set_worst_playback_latency ();
int post_engine_init ();
int immediately_post_engine ();
void remove_empty_sounds ();
-
+
void session_loaded ();
void setup_midi_control ();
void set_track_loop (bool);
bool select_playhead_priority_target (framepos_t&);
void follow_playhead_priority ();
-
+
/* These are synchronous and so can only be called from within the process
* cycle
*/
*/
Evoral::Range<framepos_t> _range_selection;
Evoral::Range<framepos_t> _object_selection;
-
+
/* main outs */
uint32_t main_outs;
ev->rt_slot = boost::bind (method, this, rl, targ, group_override);
ev->rt_return = after;
ev->event_loop = PBD::EventLoop::get_event_loop_for_thread ();
-
+
return ev;
}
/* Scene Changing */
SceneChanger* _scene_changer;
-
+
/* persistent, non-track related MIDI ports */
MidiPortManager* _midi_ports;
MIDI::MachineControl* _mmc;
-
+
void setup_ltc ();
void setup_click ();
void setup_click_state (const XMLNode*);
void setup_bundles ();
-
+
void save_as_bring_callback (uint32_t, uint32_t, std::string);
static int get_session_info_from_path (XMLTree& state_tree, const std::string& xmlpath);
static void init_event_pool ();
CrossThreadPool* event_pool() const { return own_pool; }
-
+
private:
static PerThreadPool* pool;
CrossThreadPool* own_pool;
{
boost::shared_ptr<RouteList> r = routes.reader();
RouteList public_order (*r);
-
+
if (sort) {
public_order.sort (RoutePublicOrderSorter());
}
-
+
for (RouteList::iterator i = public_order.begin(); i != public_order.end(); i++) {
(obj->*func) (**i);
}
{
boost::shared_ptr<RouteList> r = routes.reader();
RouteList public_order (*r);
-
+
if (sort) {
public_order.sort (RoutePublicOrderSorter());
}
class LIBARDOUR_API TimecodeSlave : public Slave {
public:
TimecodeSlave () {}
-
+
virtual Timecode::TimecodeFormat apparent_timecode_format() const = 0;
-
+
/* this is intended to be used by a UI and polled from a timeout. it should
return a string describing the current position of the TC source. it
should NOT do any computation, but should use a cached value
of the TC source position.
*/
virtual std::string approximate_current_position() const = 0;
-
+
framepos_t timecode_offset;
bool timecode_negative_offset;
-
+
PBD::Signal1<void, bool> ActiveChanged;
};
mutable framepos_t _smf_last_read_time;
int open_for_write ();
-
+
void ensure_disk_file (const Lock& lock);
framecnt_t read_unlocked (const Lock& lock,
the tempo section is located in. A value of 0.0 indicates that
it occurs on the first beat of the bar, a value of 0.5 indicates
that it occurs halfway through the bar and so on.
-
+
this enables us to keep the tempo change at the same relative
position within the bar if/when the meter changes.
*/
BBTPoint (const MeterSection& m, const TempoSection& t, framepos_t f,
uint32_t b, uint32_t e)
: frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
-
+
Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
operator Timecode::BBT_Time() const { return bbt(); }
operator framepos_t() const { return frame; }
void get_grid (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
framepos_t start, framepos_t end);
-
+
/* TEMPO- AND METER-SENSITIVE FUNCTIONS
bbt_time(), bbt_time_rt(), frame_time() and bbt_duration_at()
are all sensitive to tempo and meter, and will give answers
that align with the grid formed by tempo and meter sections.
-
+
They SHOULD NOT be used to determine the position of events
whose location is canonically defined in beats.
*/
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
/* TEMPO-SENSITIVE FUNCTIONS
-
+
These next 4 functions will all take tempo in account and should be
used to determine position (and in the last case, distance in beats)
when tempo matters but meter does not.
void insert_time (framepos_t, framecnt_t);
bool remove_time (framepos_t where, framecnt_t amount); //returns true if anything was moved
-
+
int n_tempos () const;
int n_meters () const;
friend class ::BBTTest;
friend class ::FrameposPlusBeatsTest;
friend class ::TempoTest;
-
+
static Tempo _default_tempo;
static Meter _default_meter;
BBTPointList::const_iterator bbt_before_or_at (framepos_t);
BBTPointList::const_iterator bbt_before_or_at (const Timecode::BBT_Time&);
BBTPointList::const_iterator bbt_after_or_at (framepos_t);
-
+
framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
void bbt_time (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
-
+
const MeterSection& first_meter() const;
MeterSection& first_meter();
const TempoSection& first_tempo() const;
TempoSection& first_tempo();
-
+
void do_insert (MetricSection* section);
void add_tempo_locked (const Tempo&, Timecode::BBT_Time where, bool recompute);
PBD::Signal0<void> MonitoringChanged;
MeterState metering_state () const;
-
+
virtual int no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool state_changing);
void maybe_declick (BufferSet&, framecnt_t, int);
boost::shared_ptr<RecEnableControl> _rec_enable_control;
-
+
framecnt_t check_initial_delay (framecnt_t nframes, framepos_t&);
private:
virtual boost::shared_ptr<Diskstream> diskstream_factory (XMLNode const &) = 0;
-
+
void diskstream_playlist_changed ();
void diskstream_record_enable_changed ();
void diskstream_record_safe_changed ();
K = 7.8990885960495589E+00
*/
-
+
return 8.2857630370864188E-01 * pow(g,5.1526743785019269E-01) * exp (-g/7.8990885960495589E+00);
#else
return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
#ifndef OLD_GAIN_MATH
/* 5th order polynomial function fit to data from a TC Spectra console
fader (image of fader gradations).
-
+
y = a + bx1 + cx2 + dx3 + fx4 + gx5
-
+
a = -1.1945480381045521E-02
b = 1.5809476525537265E+00
c = -1.5850710838966151E+01
bool parameter_is_control (uint32_t) const { return true; }
bool parameter_is_input (uint32_t) const { return true; }
bool parameter_is_output (uint32_t) const { return false; }
-
+
int connect_and_run (
BufferSet&, ChanMapping in, ChanMapping out,
pframes_t nframes, framecnt_t offset
void print_parameter (uint32_t, char*, uint32_t len) const;
bool has_editor () const;
-
+
AEffect * plugin () const { return _plugin; }
VSTState * state () const { return _state; }
MidiBuffer * midi_buffer () const { return _midi_out_buf; }
int set_state (XMLNode const &, int);
int first_user_preset_index () const;
-
+
protected:
void set_plugin (AEffect *);
gchar* get_chunk (bool) const;
XMLTree * presets_tree () const;
std::string presets_file () const;
void find_presets ();
-
+
VSTHandle* _handle;
VSTState* _state;
AEffect* _plugin;
int numInputs;
int numOutputs;
int numParams;
-
+
int wantMidi;
int wantEvents;
int hasEditor;
int canProcessReplacing;
-
+
char** ParamNames;
char** ParamLabels;
};
void* dll;
char* name;
char* path;
-
+
main_entry_t main_entry;
int plugincnt;
void* windows_window;
int xid; ///< X11 XWindow
-
+
int want_resize; ///< Set to signal the plugin resized its UI
void* extra_data; ///< Pointer to any extra data
-
+
void * event_callback_thisptr;
void (* eventProc) (void * event);
-
+
VSTHandle* handle;
int width;
int destroy;
int vst_version;
int has_editor;
-
+
int program_set_without_editor;
-
+
int want_program;
int want_chunk;
int n_pending_keys;
int wanted_chunk_size;
float * want_params;
float * set_params;
-
+
VSTKey pending_keys[16];
int dispatcher_wantcall;
typedef struct _VSTHandle VSTHandle;
namespace ARDOUR {
-
+
class AudioEngine;
class Session;
output_fifo.get_read_vector (&vec);
MidiBuffer& mb (get_midi_buffer (nframes));
-
+
if (vec.len[0]) {
Evoral::Event<double>* evp = vec.buf[0];
-
+
for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
mb.push_back (evp->time(), evp->size(), evp->buffer());
}
}
-
+
if (vec.len[1]) {
Evoral::Event<double>* evp = vec.buf[1];
mb.push_back (evp->time(), evp->size(), evp->buffer());
}
}
-
+
if ((written = vec.len[0] + vec.len[1]) != 0) {
output_fifo.increment_read_idx (written);
}
if (ARDOUR::Port::sends_output()) {
flush_output_fifo (nframes);
}
-
+
/* copy incoming data from the port buffer into the input FIFO
and if necessary wakeup the reader
*/
if (ARDOUR::Port::receives_input()) {
MidiBuffer& mb (get_midi_buffer (nframes));
framecnt_t when;
-
+
if (have_timer) {
when = timer ();
} else {
/* this is the best estimate of "when" this MIDI data is being
* delivered
*/
-
+
_parser->set_timestamp (AudioEngine::instance()->sample_time() + timestamp);
for (size_t n = 0; n < msglen; ++n) {
_parser->scanner (msg[n]);
Glib::Threads::Mutex::Lock lm (output_fifo_lock);
RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0} };
-
+
output_fifo.get_write_vector (&vec);
if (vec.len[0] + vec.len[1] < 1) {
}
output_fifo.increment_write_idx (1);
-
+
ret = msglen;
} else {
if (_currently_in_cycle) {
MidiBuffer& mb (get_midi_buffer (_cycle_nframes));
-
+
if (timestamp == 0) {
timestamp = _last_write_timestamp;
}
-
+
if (mb.push_back (timestamp, msglen, msg)) {
ret = msglen;
_last_write_timestamp = timestamp;
if (!ARDOUR::Port::receives_input()) {
return 0;
}
-
+
timestamp_t time;
Evoral::EventType type;
uint32_t size;
Sample *buf = bufs.get_audio (n).data(rec_offset);
memcpy (chaninfo->current_capture_buffer, buf, sizeof (Sample) * rec_nframes);
-
+
} else {
framecnt_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1];
}
if ((_track->monitoring_state () & MonitoringDisk) || collect_playback) {
-
+
/* we're doing playback */
framecnt_t necessary_samples;
memcpy ((char *) chaninfo->playback_wrap_buffer,
chaninfo->playback_vector.buf[0],
chaninfo->playback_vector.len[0] * sizeof (Sample));
-
+
/* Copy buf[1] from playback_buf */
memcpy (chaninfo->playback_wrap_buffer + chaninfo->playback_vector.len[0],
chaninfo->playback_vector.buf[1],
int channel = 0;
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) {
ChannelInfo* chaninfo (*chan);
-
+
playback_distance = interpolation.interpolate (
channel, nframes, chaninfo->current_playback_buffer, chaninfo->speed_buffer);
-
+
chaninfo->current_playback_buffer = chaninfo->speed_buffer;
}
-
+
} else {
playback_distance = nframes;
}
if (need_disk_signal) {
/* copy data over to buffer set */
-
+
size_t n_buffers = bufs.count().n_audio();
size_t n_chans = c->size();
gain_t scaling = 1.0f;
-
+
if (n_chans > n_buffers) {
scaling = ((float) n_buffers)/n_chans;
}
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
-
+
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
ChannelInfo* chaninfo (*chan);
-
+
if (n < n_chans) {
if (scaling != 1.0f) {
buf.read_from_with_gain (chaninfo->current_playback_buffer, nframes, scaling);
ChanCount cnt (DataType::AUDIO, n_chans);
cnt.set (DataType::MIDI, bufs.count().n_midi());
bufs.set_count (cnt);
-
+
/* extra buffers will already be silent, so leave them alone */
}
/* do not read from disk while session is marked as Loading, to avoid
useless redundant I/O.
*/
-
+
if (_session.state_of_the_state() & Session::Loading) {
return 0;
}
-
+
if (c->empty()) {
return 0;
}
/* now back to samples */
framecnt_t samples_to_read = byte_size_for_read / (bits_per_sample / 8);
-
+
//cerr << name() << " will read " << byte_size_for_read << " out of total bytes " << total_bytes << " in buffer of "
// << c->front()->playback_buf->bufsize() * bits_per_sample / 8 << " bps = " << bits_per_sample << endl;
// cerr << name () << " read samples = " << samples_to_read << " out of total space " << total_space << " in buffer of " << c->front()->playback_buf->bufsize() << " samples\n";
// uint64_t before = g_get_monotonic_time ();
// uint64_t elapsed;
-
+
for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
ChannelInfo* chan (*i);
// elapsed = g_get_monotonic_time () - before;
// cerr << "\tbandwidth = " << (byte_size_for_read / 1048576.0) / (elapsed/1000000.0) << "MB/sec\n";
-
+
file_frame = file_frame_tmp;
assert (file_frame >= 0);
ret = ((total_space - samples_to_read) > disk_read_chunk_frames);
-
+
c->front()->playback_buf->get_write_vector (&vector);
-
+
out:
return ret;
}
}
_last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
-
+
_playlist->clear_changes ();
_playlist->set_capture_insertion_in_progress (true);
_playlist->freeze ();
*/
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("Finish capture, add new CI, %1 + %2\n", ci->start, ci->frames));
-
+
capture_info.push_back (ci);
capture_captured = 0;
if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) {
return;
}
-
+
/* can't rec-safe in destructive mode if transport is before start ????
REQUIRES REVIEW */
-
+
if (destructive() && yn && _session.transport_frame() < _session.current_start_frame()) {
return;
}
-
+
/* yes, i know that this not proof against race conditions, but its
good enough. i think.
*/
-
+
if (record_safe () != yn) {
if (yn) {
engage_record_safe ();
} else {
disengage_record_safe ();
}
-
+
RecordSafeChanged (); /* EMIT SIGNAL */
}
}
boost::shared_ptr<AudioRegion> wf_region;
boost::shared_ptr<AudioRegion> region;
-
+
/* First create the whole file region */
PropertyList plist;
-
+
plist.add (Properties::start, 0);
plist.add (Properties::length, first_fs->length (first_fs->timeline_position()));
plist.add (Properties::name, region_name_from_path (first_fs->name(), true));
* the playlist */
region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
-
+
_playlist->add_region (region, position);
}
if (Profile->get_trx()) {
return false;
}
-
+
if (!_playlist) {
requires_bounce = false;
return false;
/** A segment of region that needs to be read */
struct Segment {
Segment (boost::shared_ptr<AudioRegion> r, Evoral::Range<framepos_t> a) : region (r), range (a) {}
-
+
boost::shared_ptr<AudioRegion> region; ///< the region
Evoral::Range<framepos_t> range; ///< range of the region to read, in session frames
};
if (!string_is_affirmative (p->value())) {
continue;
}
-
+
if ((p = (*i)->property (X_("in"))) == 0) {
continue;
}
*/
const XMLNodeList c = (*i)->children ();
-
+
for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
if ((*j)->name() == X_("FadeOut")) {
out_a->fade_out()->set_state (**j, version);
out_a->inverse_fade_out()->set_state (**j, version);
}
}
-
+
out_a->set_fade_out_active (true);
} else {
*/
const XMLNodeList c = (*i)->children ();
-
+
for (XMLNodeConstIterator j = c.begin(); j != c.end(); ++j) {
if ((*j)->name() == X_("FadeIn")) {
in_a->fade_in()->set_state (**j, version);
in_a->inverse_fade_in()->set_state (**j, version);
}
}
-
+
in_a->set_fade_in_active (true);
}
}
}
name = rename_pair.second;
}
-
+
XMLProperty* p = xml_playlist.property ("name");
if (!p) {
error << _("badly-formed XML in imported playlist") << endmsg;
int dret;
framecnt_t playback_distance;
-
+
if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
/* need to do this so that the diskstream sets its
BufferSet& bufs = _session.get_route_buffers (n_process_buffers ());
fill_buffers_with_input (bufs, _input, nframes);
-
+
if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) {
_meter->run (bufs, start_frame, end_frame, nframes, true);
}
/* does the output from the last considered processor match the
* input to this one?
*/
-
+
if (naudio != (*r)->input_streams().n_audio()) {
return false;
}
(*r)->deactivate ();
}
}
-
+
_session.set_dirty ();
}
}
}
name = rename_pair.second;
}
-
+
XMLNode* c = xml_track.child ("IO");
if (!c) {
error << _("badly-formed XML in imported track") << endmsg;
error << _("badly-formed XML in imported track") << endmsg;
return false;
}
-
+
p->set_value (name);
-
+
track_handler.add_name (name);
return true;
AUListenerDispose (_parameter_listener);
_parameter_listener = 0;
}
-
+
if (unit) {
DEBUG_TRACE (DEBUG::AudioUnits, "about to call uninitialize in plugin destructor\n");
unit->Uninitialize ();
if (input_elements > 0) {
/* setup render callback: the plugin calls this to get input data
*/
-
+
AURenderCallbackStruct renderCallbackInfo;
-
+
renderCallbackInfo.inputProc = _render_callback;
renderCallbackInfo.inputProcRefCon = this;
-
+
DEBUG_TRACE (DEBUG::AudioUnits, "set render callback in input scope\n");
if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
}
/* reset plugin info to show currently configured state */
-
+
_info->n_inputs = in;
_info->n_outputs = out;
uint32_t nmidi = bufs.count().n_midi();
for (uint32_t i = 0; i < nmidi; ++i) {
-
+
/* one MIDI port/buffer only */
-
+
MidiBuffer& m = bufs.get_midi (i);
-
+
for (MidiBuffer::iterator i = m.begin(); i != m.end(); ++i) {
Evoral::MIDIEvent<framepos_t> ev (*i);
-
+
if (ev.is_channel_event()) {
const uint8_t* b = ev.buffer();
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("%1: MIDI event %2\n", name(), ev));
int32_t possible_in = info->cache.io_configs.front().first;
int32_t possible_out = info->cache.io_configs.front().second;
-
+
if (possible_in > 0) {
info->n_inputs.set (DataType::AUDIO, possible_in);
} else {
AUPlugin::set_info (PluginInfoPtr info)
{
Plugin::set_info (info);
-
+
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
_has_midi_input = pinfo->needs_midi_input ();
_has_midi_output = false;
}
_instance = new AudioEngine ();
-
+
return _instance;
}
#ifdef SILENCE_AFTER_SECONDS
_silence_countdown = nframes * SILENCE_AFTER_SECONDS;
#endif
-
+
return 0;
}
if (_measuring_latency == MeasureAudio && _mtdm) {
/* run a normal cycle from the perspective of the PortManager
so that we get silence on all registered ports.
-
+
we overwrite the silence on the two ports used for latency
measurement.
*/
-
+
PortManager::cycle_start (nframes);
PortManager::silence (nframes);
return_after_remove_check = true;
} else if (_latency_flush_frames) {
-
+
/* wait for the appropriate duration for the MTDM signal to
* drain from the ports before we revert to normal behaviour.
*/
PortManager::cycle_start (nframes);
PortManager::silence (nframes);
PortManager::cycle_end (nframes);
-
+
if (_latency_flush_frames > nframes) {
_latency_flush_frames -= nframes;
} else {
} else if (session_removal_countdown > 0) {
/* we'll be fading audio out.
-
+
if this is the last time we do this as part
of session removal, do a MIDI panic now
to get MIDI stopped. This relies on the fact
}
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
-
+
PortManager::check_monitoring ();
last_monitor_check = next_processed_frames;
}
#ifdef SILENCE_AFTER_SECONDS
bool was_silent = (_silence_countdown == 0);
-
+
if (_silence_countdown >= nframes) {
_silence_countdown -= nframes;
} else {
if (_silence_countdown == 0 || _session->silent()) {
PortManager::silence (nframes);
}
-
-#else
+
+#else
if (_session->silent()) {
PortManager::silence (nframes);
}
#endif
-
+
if (session_remove_pending && session_removal_countdown) {
PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
-
+
if (session_removal_countdown > nframes) {
session_removal_countdown -= nframes;
} else {
_processed_frames = next_processed_frames;
PT_TIMING_CHECK (2);
-
+
return 0;
}
while (!_stop_hw_reset_processing) {
if (g_atomic_int_get (&_hw_reset_request_count) != 0 && _backend) {
-
+
_reset_request_lock.unlock();
-
+
Glib::Threads::RecMutex::Lock pl (_state_lock);
g_atomic_int_dec_and_test (&_hw_reset_request_count);
-
+
std::cout << "AudioEngine::RESET::Reset request processing. Requests left: " << _hw_reset_request_count << std::endl;
DeviceResetStarted(); // notify about device reset to be started
if ( ( 0 == stop () ) &&
( 0 == _backend->reset_device () ) &&
( 0 == start () ) ) {
-
+
std::cout << "AudioEngine::RESET::Engine started..." << std::endl;
-
+
// inform about possible changes
BufferSizeChanged (_backend->buffer_size() );
DeviceResetFinished(); // notify about device reset finish
// we've got an error
DeviceError();
}
-
+
std::cout << "AudioEngine::RESET::Done." << std::endl;
_reset_request_lock.lock();
_hw_devicelist_update_thread->join ();
_hw_devicelist_update_thread = 0;
}
-
+
}
if (_session) {
_session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs);
}
-#endif
+#endif
}
Glib::Module::get_last_error()) << endmsg;
return 0;
}
-
+
if (!module.get_symbol ("descriptor", func)) {
error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg;
error << Glib::Module::get_last_error() << endmsg;
return 0;
}
-
+
dfunc = (AudioBackendInfo* (*)(void))func;
info = dfunc();
if (!info->available()) {
}
module.make_resident ();
-
+
return info;
}
AudioEngine::available_backends() const
{
vector<const AudioBackendInfo*> r;
-
+
for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
r.push_back (i->second);
}
}
drop_backend ();
-
+
try {
if (b->second->instantiate (arg1, arg2)) {
throw failed_constructor ();
}
-
+
_backend = b->second->factory (*this);
} catch (exception& e) {
}
_running = true;
-
+
if (_session) {
_session->set_frame_rate (_backend->sample_rate());
-
+
if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
}
}
-
+
if (!for_latency) {
Running(); /* EMIT SIGNAL */
}
-
+
return 0;
}
_latency_output_port = 0;
_latency_input_port = 0;
_started_for_latency = false;
-
+
Port::PortDrop ();
if (!for_latency) {
Stopped (); /* EMIT SIGNAL */
}
-
+
return 0;
}
return false;
}
}
-
+
return true;
}
if (size != curve2->size()) {
return;
}
-
+
Evoral::ControlList::const_iterator c1 = curve1->begin();
int count = 0;
for (Evoral::ControlList::const_iterator c2 = curve2->begin(); c2!=curve2->end(); c2++ ) {
float v1 = accurate_coefficient_to_dB((*c1)->value);
float v2 = accurate_coefficient_to_dB((*c2)->value);
-
+
double interp = v1 * ( 1.0-( (double)count / (double)size) );
interp += v2 * ( (double)count / (double)size );
*/
assert (cnt >= 0);
-
+
if (n_channels() == 0) {
return 0;
}
of any fade out that we are dealing with
*/
frameoffset_t fade_out_offset = 0;
-
+
/* Amount (length) of fade out that we are dealing with in this read */
framecnt_t fade_out_limit = 0;
framecnt_t fade_interval_start = 0;
/* Fade in */
-
+
if (_fade_in_active && _session.config.get_use_region_fades()) {
-
+
framecnt_t fade_in_length = (framecnt_t) _fade_in->back()->when;
/* see if this read is within the fade in */
-
+
if (internal_offset < fade_in_length) {
fade_in_limit = min (to_read, fade_in_length - internal_offset);
}
}
-
+
/* Fade out */
-
+
if (_fade_out_active && _session.config.get_use_region_fades()) {
-
+
/* see if some part of this read is within the fade out */
/* ................. >| REGION
fade_interval_start = max (internal_offset, _length - framecnt_t (_fade_out->back()->when));
framecnt_t fade_interval_end = min(internal_offset + to_read, _length.val());
-
+
if (fade_interval_end > fade_interval_start) {
/* (part of the) the fade out is in this buffer */
fade_out_limit = fade_interval_end - fade_interval_start;
/* explicit inverse fade in curve (e.g. for constant
* power), so we have to fetch it.
*/
-
+
_inverse_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
-
+
/* Fade the data from lower layers out */
for (framecnt_t n = 0; n < fade_in_limit; ++n) {
buf[n] *= gain_buffer[n];
}
-
+
/* refill gain buffer with the fade in */
-
+
_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
-
+
} else {
-
+
/* no explicit inverse fade in, so just use (1 - fade
* in) for the fade out of lower layers
*/
-
+
_fade_in->curve().get_vector (internal_offset, internal_offset + fade_in_limit, gain_buffer, fade_in_limit);
-
+
for (framecnt_t n = 0; n < fade_in_limit; ++n) {
buf[n] *= 1 - gain_buffer[n];
}
if (opaque()) {
if (_inverse_fade_out) {
-
+
_inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
-
+
/* Fade the data from lower levels in */
for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
buf[m] *= gain_buffer[n];
}
-
+
/* fetch the actual fade out */
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
-
+
} else {
/* no explicit inverse fade out (which is
* actually a fade in), so just use (1 - fade
* out) for the fade in of lower layers
*/
-
+
_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
-
+
for (framecnt_t n = 0, m = fade_out_offset; n < fade_out_limit; ++n, ++m) {
buf[m] *= 1 - gain_buffer[n];
}
buf[m] += mixdown_buffer[m] * gain_buffer[n];
}
}
-
+
/* MIX OR COPY THE REGION BODY FROM mixdown_buffer INTO buf */
framecnt_t const N = to_read - fade_in_limit - fade_out_limit;
if (to_read == 0) {
return 0;
}
-
+
if (chan_n < n_channels()) {
boost::shared_ptr<AudioSource> src = boost::dynamic_pointer_cast<AudioSource> (srcs[chan_n]);
}
} else {
-
+
/* use silence */
memset (buf, 0, sizeof (Sample) * to_read);
}
_fade_out->set_state (*grandchild, version);
}
}
-
+
if ((prop = child->property ("active")) != 0) {
if (string_is_affirmative (prop->value())) {
set_fade_out_active (true);
set_fade_out_active (false);
}
}
-
+
} else if ( (child->name() == "InverseFadeIn") || (child->name() == "InvFadeIn") ) {
XMLNode* grandchild = child->child ("AutomationList");
if (grandchild) {
_fade_in->fast_simple_add (len, GAIN_COEFF_UNITY);
reverse_curve (_inverse_fade_in.val(), _fade_in.val());
break;
-
+
case FadeSymmetric:
//start with a nearly linear cuve
_fade_in->fast_simple_add (0, 1);
_fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
reverse_curve (_inverse_fade_out.val(), _fade_out.val());
break;
-
+
case FadeFast:
generate_db_fade (_fade_out.val(), len, num_steps, -60);
generate_inverse_power_curve (_inverse_fade_out.val(), _fade_out.val());
break;
-
+
case FadeSlow:
generate_db_fade (c1, len, num_steps, -1); //start off with a slow fade
generate_db_fade (c2, len, num_steps, -80); //end with a fast fade
_fade_out->fast_simple_add (len, GAIN_COEFF_SMALL);
reverse_curve (_inverse_fade_out.val(), _fade_out.val());
break;
-
+
case FadeSymmetric:
//start with a nearly linear cuve
_fade_out->fast_simple_add (0, 1);
if (len > _length) {
len = _length - 1;
}
-
+
if (len < 64) {
len = 64;
}
bool changed = _fade_out->extend_to (len);
if (changed) {
-
+
if (_inverse_fade_out) {
_inverse_fade_out->extend_to (len);
}
} else {
rl = pl->regions_at (last_frame());
}
-
+
RegionList::iterator i;
boost::shared_ptr<Region> other;
uint32_t n = 0;
}
return min (length(), min (maxlen, len));
-
+
}
AudioSource::read (Sample *dst, framepos_t start, framecnt_t cnt, int /*channel*/) const
{
assert (cnt >= 0);
-
+
Glib::Threads::Mutex::Lock lm (_lock);
return read_unlocked (dst, start, cnt);
}
}
if (!_captured_for.empty()) {
-
+
/* _captured_for is only set after a capture pass is
* complete. so we know that capturing is finished for this
* file, and now we can check actual size of the peakfile is at
* might decided to get rid of that anyway.
*
*/
-
+
const off_t expected_file_size = (_length / (double) samples_per_file_peak) * sizeof (PeakData);
-
+
if (statbuf.st_size < expected_file_size) {
warning << string_compose (_("peak file %1 is truncated from %2 to %3"), _peakpath, expected_file_size, statbuf.st_size) << endmsg;
const_cast<AudioSource*>(this)->build_peaks_from_scratch ();
error << string_compose (_("Cannot open peakfile @ %1 for reading (%2)"), _peakpath, strerror (errno)) << endmsg;
return -1;
}
-
+
scale = npeaks/expected_peaks;
/* hold lock while building peaks */
Glib::Threads::Mutex::Lock lp (_lock);
-
+
if (prepare_for_peakfile_writes ()) {
goto out;
}
framecnt_t frames_to_read = min (bufsize, cnt);
framecnt_t frames_read;
-
+
if ((frames_read = read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
done_with_peakfile_writes (false);
/* create (and connect) new ports */
_main_outs->defer_pan_reset ();
-
+
if (left.length()) {
_output->add_port (left, this, DataType::AUDIO);
}
-
+
if (right.length()) {
_output->add_port (right, this, DataType::AUDIO);
}
-
+
_main_outs->allow_pan_reset ();
_main_outs->reset_panner ();
} else {
-
+
/* reconnect existing ports */
boost::shared_ptr<Port> oleft (_output->nth (0));
oright->connect (right);
}
}
-
+
}
return 0;
{
{
Glib::Threads::Mutex::Lock lm (_control_lock);
-
+
for (Controls::const_iterator li = _controls.begin(); li != _controls.end(); ++li) {
boost::dynamic_pointer_cast<AutomationControl>(li->second)->drop_references ();
}
AutoState result = Off;
boost::shared_ptr<AutomationControl> c = automation_control(param);
-
+
if (c) {
result = c->automation_state();
}
if (_state == Touch) {
if (mark) {
-
+
/* XXX need to mark the last added point with the
* current time
*/
boost::shared_ptr<AutomationList> (new AutomationList (*this->_current.get()))
);
}
-
+
, _last_time (0)
, _run_thread (false)
{
-
+
}
AutomationWatch::~AutomationWatch ()
* creates reference cycles. we don't need to make the weak_ptr<>
* explicit here, but it helps to remind us what is going on.
*/
-
+
boost::weak_ptr<AutomationControl> wac (ac);
ac->DropReferences.connect_same_thread (*this, boost::bind (&AutomationWatch::remove_weak_automation_watch, this, wac));
}
}
}
}
-
+
_last_time = time;
}
if (_session) {
_run_thread = true;
_thread = Glib::Threads::Thread::create (boost::bind (&AutomationWatch::thread, this));
-
+
_session->TransportStateChange.connect_same_thread (transport_connection, boost::bind (&AutomationWatch::transport_state_change, this));
}
}
}
bool rolling = _session->transport_rolling();
-
+
_last_time = _session->audible_frame ();
{
for (size_t i = 0; i < num_buffers; ++i) {
bufs.push_back(Buffer::create(type, buffer_capacity));
}
-
+
_available.set(type, num_buffers);
_count.set (type, num_buffers);
}
if (t == DataType::NIL) {
return c;
}
-
+
Glib::Threads::Mutex::Lock lm (_channel_mutex);
vector<Channel>::const_iterator i = _channel.begin ();
if (t == DataType::NIL) {
return c;
}
-
+
Glib::Threads::Mutex::Lock lm (_channel_mutex);
uint32_t s = 0;
-
+
vector<Channel>::const_iterator i = _channel.begin ();
for (uint32_t j = 0; j < c; ++j) {
if (i->type == t) {
{
// set up capture and playback buffering
Diskstream::set_buffering_parameters (Config->get_buffering_preset());
-
+
/* size is in Samples, not bytes */
const float rate = (float)_session.frame_rate();
audio_dstream_capture_buffer_size = (uint32_t) floor (Config->get_audio_capture_buffer_seconds() * rate);
// we are ready to request buffer adjustments
_session.adjust_capture_buffering ();
_session.adjust_playback_buffering ();
-
+
return 0;
}
}
}
-
+
restart:
DEBUG_TRACE (DEBUG::Butler, "at restart for disk work\n");
disk_work_outstanding = false;
case 0:
DEBUG_TRACE (DEBUG::Butler, string_compose ("\ttrack refill done %1\n", tr->name()));
break;
-
+
case 1:
DEBUG_TRACE (DEBUG::Butler, string_compose ("\ttrack refill unfinished %1\n", tr->name()));
disk_work_outstanding = true;
for (RouteList::iterator i = rl->begin(); !transport_work_requested() && should_run && i != rl->end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
-
+
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (!tr) {
}
return disk_work_outstanding;
-}
+}
bool
Butler::flush_tracks_to_disk_after_locate (boost::shared_ptr<RouteList> rl, uint32_t& errors)
/* almost the same as the "normal" version except that we do not test
* for transport_work_requested() and we force flushes.
*/
-
+
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
}
return disk_work_outstanding;
-}
+}
void
Butler::schedule_transport_work ()
cp->set_active (true);
return 0;
-}
+}
int
ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
/* called explicitly by Session::destroy() so that we can clean up
* before the process cycle stops and ports vanish.
*/
-
+
Glib::Threads::Mutex::Lock lm (protocols_lock);
-
+
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
delete *p;
}
-
+
control_protocols.clear ();
-
+
for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
// mark existing protocols as requested
// otherwise the ControlProtocol instances are not recreated in set_session
(*p)->protocol = 0;
}
}
-}
+}
ControlProtocol*
ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
if (cpi.mandatory) {
return 0;
}
-
+
/* save current state */
delete cpi.state;
DEBUG_TRACE (DEBUG::ControlProtocols,
string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
-
+
for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
control_protocol_discover (*i);
}
}
bool active = string_is_affirmative (prop->value());
-
+
if ((prop = (*citer)->property (X_("name"))) == 0) {
continue;
}
ControlProtocolInfo* cpi = cpi_by_name (prop->value());
-
+
if (cpi) {
cpi->state = new XMLNode (**citer);
-
+
if (active) {
if (_session) {
instantiate (*cpi);
_max_points = N;
_points = 0;
}
-
+
void
StoringTimer::dump (string const & file)
} else if (_points > _max_points) {
return;
}
-
+
_point[_points] = p;
_value[_points] = get_cycles ();
_ref[_points] = _current_ref;
-
+
++_points;
}
Delivery::~Delivery()
{
- DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
+ DEBUG_TRACE (DEBUG::Destruction, string_compose ("delivery %1 destructor\n", _name));
/* this object should vanish from any signal callback lists
that it is on before we get any further. The full qualification
if (!_output) {
return;
}
-
+
PortSet& ports (_output->ports());
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
error << string_compose (_("%1: this session uses destructive tracks, which are not supported"), PROGRAM_NAME) << endmsg;
return -1;
}
-
+
if ((prop = node.property (X_("capture-alignment"))) != 0) {
set_align_choice (AlignChoice (string_2_enum (prop->value(), _alignment_choice)), true);
} else {
non_realtime_set_speed ();
}
}
-
+
if ((prop = node.property ("record-safe")) != 0) {
_record_safe = PBD::string_is_affirmative (prop->value()) ? 1 : 0;
}
Diskstream::default_disk_read_chunk_frames()
{
return 65536;
-}
+}
framecnt_t
Diskstream::default_disk_write_chunk_frames ()
if (!get_buffering_presets (bp, read_chunk_size, read_buffer_size, write_chunk_size, write_buffer_size)) {
return;
}
-
+
disk_read_chunk_frames = read_chunk_size;
disk_write_chunk_frames = write_chunk_size;
Config->set_audio_capture_buffer_seconds (write_buffer_size);
} else {
_starting = false;
}
-
+
return true;
}
// if current is not found switch to default if is supported
if (bs_iter == buffer_sizes.end ()) {
bs_iter = std::find (buffer_sizes.begin (), buffer_sizes.end (), backend->default_buffer_size (_current_state->device_name));
-
+
if (bs_iter != buffer_sizes.end ()) {
_current_state->buffer_size = backend->default_buffer_size (_current_state->device_name);
} else {
// This is done during session construction
// _session->reconnect_ltc_input ();
// _session->reconnect_ltc_output ();
-
+
framecnt_t desired_sample_rate = _session->nominal_frame_rate ();
if ( desired_sample_rate > 0 && set_new_sample_rate_in_controller (desired_sample_rate))
{
EngineStateController::push_current_state_to_backend (bool start)
{
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance ()->current_backend ();
-
+
if (!backend) {
return false;
}
if (!result ) {
std::cout << "EngineStateController::Setting device sample rate " << _current_state->sample_rate << std::endl;
result = backend->set_sample_rate (_current_state->sample_rate);
-
+
if (result) {
error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate ()) << endmsg;
}
REGISTER_CLASS_ENUM (SessionEvent, Replace);
REGISTER_CLASS_ENUM (SessionEvent, Clear);
REGISTER (_SessionEvent_Action);
-
+
REGISTER_CLASS_ENUM (Session, Stopped);
REGISTER_CLASS_ENUM (Session, Waiting);
REGISTER_CLASS_ENUM (Session, Running);
} else {
PBD::warning << "Unknown Parameter '" << str << "'" << endmsg;
}
-
+
return Evoral::Parameter(p_type, p_channel, p_id);
}
folder = tmp;
}
}
-
+
if (folder.empty()) {
folder = session.session_directory().export_path();
}
config = new_config;
uint32_t const channels = config.channel_config->get_n_chans();
max_frames_out = 4086 - (4086 % channels); // TODO good chunk size
-
+
buffer.reset (new AllocatingProcessContext<Sample> (max_frames_out, channels));
peak_reader.reset (new PeakReader ());
normalizer.reset (new AudioGrapher::Normalizer (config.format->normalize_target()));
this is the timespan to do this time
*/
current_timespan = config_map.begin()->first;
-
+
export_status->total_frames_current_timespan = current_timespan->get_length();
export_status->timespan_name = current_timespan->name();
export_status->processed_frames_current_timespan = 0;
BINARY = "header-less" audio (44.1 kHz, 16 Bit, little endian),
MOTOROLA = "header-less" audio (44.1 kHz, 16 Bit, big endian),
and MP3
-
+
We try to use these file types whenever appropriate and
default to our own names otherwise.
*/
status.out << "CD_TEXT {" << endl << " LANGUAGE 0 {" << endl;
status.out << " TITLE " << toc_escape_cdtext (status.marker->name()) << endl;
-
+
status.out << " PERFORMER ";
if (status.marker->cd_info.find("performer") != status.marker->cd_info.end()) {
status.out << toc_escape_cdtext (status.marker->cd_info["performer"]) << endl;
} else {
status.out << "\"\"" << endl;
}
-
+
if (status.marker->cd_info.find("composer") != status.marker->cd_info.end()) {
status.out << " SONGWRITER " << toc_escape_cdtext (status.marker->cd_info["composer"]) << endl;
}
out += buf;
}
}
-
+
out += '"';
return out;
out += *c;
}
}
-
+
out += '"';
return out;
{
std::string latin1_txt;
std::string out;
-
+
try {
latin1_txt = Glib::convert (txt, "ISO-8859-1", "UTF-8");
} catch (Glib::ConvertError& err) {
throw Glib::ConvertError (err.code(), string_compose (_("Cannot convert %1 to Latin-1 text"), txt));
}
-
+
// does not do much mor than UTF-8 to Latin1 translation yet, but
// that may have to change if cue parsers in burning programs change
out = '"' + latin1_txt + '"';
} else {
session_range = session.locations()->session_range_location();
}
-
+
if (!session_range) { return false; }
ExportTimespanPtr timespan = handler->add_timespan();
ExportProfileManager::get_sample_filename_for_format (ExportFilenamePtr filename, ExportFormatSpecPtr format)
{
assert (format);
-
+
if (channel_configs.empty()) { return ""; }
std::list<string> filenames;
if (!channel_configs.empty ()) {
channel_config_state = channel_configs.front();
}
-
+
TimespanStatePtr timespan_state = timespans.front();
/*** Check "global" config ***/
check_config (warnings, timespan_state, channel_config_state, *format_it, *filename_it);
}
}
-
+
return warnings;
}
vector<string>::iterator j = i;
++j;
-
+
while (j != hits.end()) {
if (PBD::equivalent_paths (*i, *j)) {
/* *i and *j are the same file; break out of the loop early */
} else {
/* only one match: happy days */
-
+
keeppath = de_duped_hits[0];
}
-
+
} else {
keeppath = path;
}
if (!empty()) {
return false;
}
-
+
if (!removable()) {
return false;
}
return true;
}
-
+
int
FileSource::rename (const string& newpath)
{
return 0;
}
-
+
called, so rely on build-time detection of the
product name etc.
*/
-
+
#ifdef USE_TRACKS_CODE_FEATURES
/* Tracks does not use versioned configuration folders, which may or
may not be problematic in the future.
*/
return X_(PROGRAM_NAME);
-#else
+#else
const string config_dir_name = string_compose ("%1%2", X_(PROGRAM_NAME), version);
#if defined (__APPLE__) || defined (PLATFORM_WINDOWS)
/* use lower case folder name on Linux */
return downcase (config_dir_name);
#endif
-#endif
-}
+#endif
+}
std::string
user_config_directory (int version)
if (s.empty()) {
std::cerr << _("ARDOUR_DLL_PATH not set in environment - exiting\n");
::exit (1);
- }
+ }
return s;
#endif
}
sample_rate = session.frame_rate();
} else {
boost::shared_ptr<AudioRegion> aregion = boost::dynamic_pointer_cast<AudioRegion>(region);
-
+
if (aregion) {
sample_rate = aregion->audio_source()->sample_rate();
} else {
return -1;
}
}
-
+
nsrcs.push_back (boost::dynamic_pointer_cast<Source> (
SourceFactory::createWritable (region->data_type(), session,
path, false, sample_rate)));
}
-
+
catch (failed_constructor& err) {
error << string_compose (_("filter: error creating new file %1 (%2)"), path, strerror (errno)) << endmsg;
return -1;
#ifdef PLATFORM_WINDOWS
/* We have AVX-optimized code for Windows */
-
+
if (fpu->has_avx()) {
-#else
+#else
/* AVX code doesn't compile on Linux yet */
-
+
if (false) {
-#endif
+#endif
info << "Using AVX optimized routines" << endmsg;
-
+
// AVX SET
compute_peak = x86_sse_avx_compute_peak;
find_peaks = x86_sse_avx_find_peaks;
if (g_mkdir_with_parents (new_dir.c_str(), 0755)) {
return -1;
}
-
+
if (old_version == 3) {
-
+
old_name = Glib::build_filename (old_dir, X_("recent"));
new_name = Glib::build_filename (new_dir, X_("recent"));
* $CONFIG/ardour.rc. Pick up the newer "old" config file,
* to avoid confusion.
*/
-
+
string old_name = Glib::build_filename (old_dir, X_("config"));
if (!Glib::file_test (old_name, Glib::FILE_TEST_EXISTS)) {
old_name = Glib::build_filename (old_dir, X_("presets"));
new_name = Glib::build_filename (new_dir, X_("presets"));
-
+
copy_recurse (old_name, new_name);
/* presets */
new_name = Glib::build_filename (new_dir, X_("plugin_statuses"));
copy_file (old_name, new_name);
-
+
/* export formats */
old_name = Glib::build_filename (old_dir, export_formats_dir_name);
new_name = Glib::build_filename (new_dir, export_formats_dir_name);
-
+
vector<string> export_formats;
g_mkdir_with_parents (Glib::build_filename (new_dir, export_formats_dir_name).c_str(), 0755);
find_files_matching_pattern (export_formats, old_name, X_("*.format"));
ARDOUR::check_for_old_configuration_files ()
{
int current_version = atoi (X_(PROGRAM_VERSION));
-
+
if (current_version <= 1) {
return;
}
surface support that would list their port names, we do have to
list them here.
*/
-
+
char const * const reserved[] = {
_("Monitor"),
_("Master"),
for (int n = 0; reserved[n]; ++n) {
reserved_io_names.push_back (reserved[n]);
}
-
+
libardour_initialized = true;
return true;
ARDOUR::setup_fpu ()
{
FPU* fpu = FPU::instance ();
-
+
if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
// valgrind doesn't understand this assembler stuff
// September 10th, 2007
#ifdef DEBUG_DENORMAL_EXCEPTION
/* This will raise a FP exception if a denormal is detected */
MXCSR &= ~_MM_MASK_DENORM;
-#endif
+#endif
switch (Config->get_denormal_model()) {
case DenormalNone:
if (fd < 0) {
return false;
}
-
+
char c;
-
+
if (yn) {
c = '1';
} else {
c = '0';
}
-
+
(void) ::write (fd, &c, 1);
(void) ::close (fd);
again:
_callback_start_sem.wait ();
-
+
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread is awake\n");
if (!_threads_active) {
return;
}
}
-
+
if (channels == 0) {
error << _("Import: file contains no channels.") << endmsg;
continue;
Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
}
}
-
+
/* imported, copied files cannot be written or removed
*/
} catch (...) {
error << _("Failed to remove some files after failed/cancelled import operation") << endmsg;
}
-
+
}
status.done = true;
}
MIDI::Name::PatchPrimaryKey patch_key (program, bank);
-
+
boost::shared_ptr<MIDI::Name::Patch> patch =
MIDI::Name::MidiPatchManager::instance().find_patch (external_instrument_model,
external_instrument_mode, channel, patch_key);
return string_compose ("prg %1 bnk %2",program + MIDI_BP_ZERO , bank + MIDI_BP_ZERO);
}
-}
+}
string
InstrumentInfo::get_controller_name (Evoral::Parameter param) const
if (!dev_names) {
return "";
}
-
+
boost::shared_ptr<ChannelNameSet> chan_names(
dev_names->channel_name_set_by_channel(
external_instrument_mode, param.channel()));
}
return control_names->control(param.id())->name();
-}
+}
boost::shared_ptr<MIDI::Name::ChannelNameSet>
InstrumentInfo::get_patches (uint8_t channel)
}
boost::shared_ptr<Plugin> pp = insert->plugin();
-
+
if (pp->current_preset_uses_general_midi()) {
patch_list = InstrumentInfo::general_midi_patches ();
std::vector<Plugin::PresetRecord> presets = pp->get_presets ();
std::vector<Plugin::PresetRecord>::iterator i;
int n;
-
+
/* XXX note the assumption that plugin presets start their numbering at
* zero
*/
-
+
for (n = 0, i = presets.begin(); i != presets.end(); ++i, ++n) {
if ((*i).number >= 0) {
patch_list.push_back (boost::shared_ptr<Patch> (new Patch ((*i).label, n)));
cns->set_patch_banks (patch_banks);
return cns;
-}
+}
const MIDI::Name::PatchNameList&
InstrumentInfo::general_midi_patches()
boost::shared_ptr<PluginInsert> insert = boost::dynamic_pointer_cast<PluginInsert> (p);
if (insert) {
boost::shared_ptr<Plugin> pp = insert->plugin();
-
+
if (pp->current_preset_uses_general_midi()) {
return MIDI::Name::general_midi_program_names[std::min((uint8_t) 127,program)];
}
}
Glib::Threads::Mutex::Lock lm (_sends_mutex, Glib::Threads::TRY_LOCK);
-
+
if (lm.locked ()) {
for (list<InternalSend*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
if ((*i)->active () && (!(*i)->source_route() || (*i)->source_route()->active())) {
} else {
if (role() == Listen) {
/* We're going to the monitor bus, so discard MIDI data */
-
+
uint32_t const bufs_audio = bufs.count().get (DataType::AUDIO);
uint32_t const mixbufs_audio = mixbufs.count().get (DataType::AUDIO);
-
+
/* monitor-section has same number of channels as master-bus (on creation).
*
* There is no clear answer what should happen when trying to PFL or AFL
for (BufferSet::audio_iterator b = mixbufs.audio_begin(); b != mixbufs.audio_end(); ++b) {
b->prepare ();
}
-}
+}
* ::disconnect()
*/
if (_ports.contains (a) || _ports.contains (b)) {
- changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */
+ changed (IOChange (IOChange::ConnectionsChanged), this); /* EMIT SIGNAL */
}
} else {
/* we didn't get the lock, so assume that we're inside
}
_session.set_dirty ();
-
+
return 0;
}
ChanCount before = _ports.count ();
ChanCount after = before;
after.set (type, after.get (type) + 1);
-
+
bool const r = PortCountChanging (after); /* EMIT SIGNAL */
if (r) {
return -1;
}
-
+
IOChange change;
{
/* Create a new port */
string portname = build_legal_port_name (type);
-
+
if (_direction == Input) {
if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
change.before = _ports.count ();
_ports.add (our_port);
}
-
+
PortCountChanged (n_ports()); /* EMIT SIGNAL */
change.type = IOChange::ConfigurationChanged;
change.after = _ports.count ();
snprintf (buf, sizeof (buf), "%" PRId64, _user_latency);
node->add_property (X_("user-latency"), buf);
-
+
return *node;
}
for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
if ((*i)->name() == "Port") {
-
+
prop = (*i)->property (X_("name"));
-
+
if (prop) {
string new_name;
string old = prop->value();
if (slash != string::npos) {
/* port name is of form: <IO-name>/<port-name> */
-
+
new_name = name;
new_name += old.substr (old.find ('/'));
-
+
prop->set_value (new_name);
}
}
XMLNodeIterator niter;
const string instr = enum_2_string (IO::Input);
const string outstr = enum_2_string (IO::Output);
-
+
if (_own_input) {
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
const XMLProperty* prop;
}
}
}
-
+
if (io_node) {
_input->set_state(*io_node, version);
-
+
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
set_name (_input->name());
}
-
+
} else {
/* no input, which is OK */
}
-
+
}
-
+
if (_own_output) {
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == "IO") {
}
}
}
-
+
if (io_node) {
_output->set_state(*io_node, version);
-
+
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
set_name (_output->name());
LADSPA_PortDescriptor
LadspaPlugin::port_descriptor (uint32_t i) const
{
- if (i < _descriptor->PortCount) {
+ if (i < _descriptor->PortCount) {
return _descriptor->PortDescriptors[i];
}
-
+
warning << "LADSPA plugin port index " << i << " out of range." << endmsg;
return 0;
}
-
-
+
+
vstfx_new ()
{
VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
-
+
/*Mutexes*/
-
+
pthread_mutex_init (&vstfx->lock, 0);
pthread_cond_init (&vstfx->window_status_change, 0);
pthread_cond_init (&vstfx->plugin_dispatcher_called, 0);
pthread_cond_init (&vstfx->window_created, 0);
/*Safe values*/
-
+
vstfx->want_program = -1;
vstfx->want_chunk = 0;
vstfx->n_pending_keys = 0;
vstfx->eventProc = 0;
vstfx->extra_data = 0;
vstfx->want_resize = 0;
-
+
return vstfx;
}
PBD::error << string_compose (_("Could not open existing LXVST plugin: %1"), dlerror()) << endmsg;
return 0;
}
-
+
/*We didn't find the library so try and get the path specified in the
env variable LXVST_PATH*/
envdup = getenv ("LXVST_PATH");
-
+
/*Path not specified - not much more we can do*/
-
+
if (envdup == 0)
return 0;
-
+
/*Copy the path into envdup*/
-
+
envdup = strdup (envdup);
-
+
if (envdup == 0)
return 0;
-
+
len2 = strlen(path);
/*Try all the possibilities in the path - deliminated by : */
char *saveptr;
lxvst_path = strtok_r (envdup, ":", &saveptr);
-
+
while (lxvst_path != 0)
{
vstfx_error ("\"%s\"", lxvst_path);
len1 = strlen(lxvst_path);
-
+
if (full_path) free(full_path);
full_path = (char*)malloc(len1 + 1 + len2 + 1);
memcpy(full_path, lxvst_path, len1);
/*Succeeded */
break;
}
-
+
/*Try again*/
lxvst_path = strtok_r (0, ":", &saveptr);
{
char* buf = 0;
VSTHandle* fhandle;
-
+
/*Create a new handle we can use to reference the plugin*/
fhandle = vstfx_handle_new();
-
+
/*See if we have .so appended to the path - if not we need to make sure it is added*/
if (strstr (path, ".so") == 0)
{
/*Append the .so to the path - Make sure the path has enough space*/
-
+
buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
sprintf (buf, "%s.so", path);
else
{
/*We already have .so appened to the filename*/
-
+
buf = strdup(path);
}
we don't know anything about its name until we load and instantiate the plugin
which we don't want to do at this point
*/
-
+
fhandle->name = strdup (PBD::basename_nosuffix (path).c_str());
/*call load_vstfx_library to actually load the .so into memory*/
if ((fhandle->dll = vstfx_load_vst_library (buf)) == 0)
{
vstfx_unload (fhandle);
-
+
free(buf);
-
+
return 0;
}
if (fhandle->main_entry == 0)
{
/*If it can't be found, unload the plugin and return a 0 handle*/
-
+
vstfx_unload (fhandle);
-
+
free(buf);
-
+
return 0;
}
{
/*Still have plugin instances - can't unload the library
- actually dlclose keeps an instance count anyway*/
-
+
return -1;
}
{
free (fhandle->name);
}
-
+
/*Don't need the plugin handle any more*/
-
+
free (fhandle);
return 0;
}
free (vstfx);
return 0;
}
-
+
vstfx->handle = fhandle;
vstfx->plugin->user = userptr;
-
+
if (vstfx->plugin->magic != kEffectMagic)
{
vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
free (vstfx);
return 0;
}
-
+
vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
-
+
/*May or May not need to 'switch the plugin on' here - unlikely
since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
-
+
//vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, 0, 0);
-
+
vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
-
+
vstfx->handle->plugincnt++;
vstfx->wantIdle = 0;
-
+
return vstfx;
}
void vstfx_close (VSTState* vstfx)
{
vstfx_destroy_editor(vstfx);
-
+
if(vstfx->plugin)
{
vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, 0, 0);
-
+
/*Calling dispatcher with effClose will cause the plugin's destructor to
be called, which will also remove the editor if it exists*/
-
+
vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
}
if (vstfx->handle->plugincnt)
vstfx->handle->plugincnt--;
-
+
/*vstfx_unload will unload the dll if the instance count allows -
we need to do this because some plugins keep their own instance count
and (JUCE) manages the plugin UI in its own thread. When the plugins
internal instance count reaches zero, JUCE stops the UI thread and won't
restart it until the next time the library is loaded. If we don't unload
the lib JUCE will never restart*/
-
-
+
+
if (vstfx->handle->plugincnt)
{
return;
}
-
+
/*Valid plugin loaded - so we can unload it and 0 the pointer
to it. We can't free the handle here because we don't know what else
might need it. It should be / is freed when the plugin is deleted*/
int success;
/* write header */
-
+
fprintf(f, "<plugin_state>\n");
success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
-
+
if(success == 1)
{
fprintf (f, " <check field=\"productString\" value=\"%s\"/>\n", productString);
}
success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
-
+
if(success == 1)
{
fprintf (f, " <check field=\"effectName\" value=\"%s\"/>\n", effectName);
}
success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
-
+
if( success == 1 )
{
fprintf (f, " <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
for(i=0; i < numParams; i++)
{
float val;
-
+
pthread_mutex_lock( &vstfx->lock );
val = vstfx->plugin->getParameter(vstfx->plugin, i );
pthread_mutex_unlock( &vstfx->lock );
int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt)
{
pthread_mutex_lock (&vstfx->lock);
-
+
/*Set up the opcode and parameters*/
-
+
vstfx->dispatcher_opcode = opcode;
vstfx->dispatcher_index = index;
vstfx->dispatcher_val = val;
vstfx->dispatcher_ptr = ptr;
vstfx->dispatcher_opt = opt;
-
+
/*Signal that we want the call to happen*/
-
+
vstfx->dispatcher_wantcall = 1;
/*Wait for the call to happen*/
pthread_mutex_unlock (&vstfx->lock);
/*Return the result*/
-
+
return vstfx->dispatcher_retval;
}
_bbt_end = other._bbt_end;
_flags = other._flags;
_position_lock_style = other._position_lock_style;
-
+
/* XXX need to copy scene change */
/* copy is not locked even if original was */
}
start_changed (this); /* EMIT SIGNAL */
StartChanged (); /* EMIT SIGNAL */
-
+
if (is_session_range ()) {
Session::StartTimeChanged (old); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset (s);
}
XMLNode* scene_child = find_named_node (node, SceneChange::xml_node_name);
-
+
if (scene_child) {
_scene_change = SceneChange::factory (*scene_child, version);
}
{
Glib::Threads::Mutex::Lock lm (lock);
vector<LocationPair> locs;
-
+
for (LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
locs.push_back (make_pair ((*i)->start(), (*i)));
if (!(*i)->is_mark()) {
} else {
delta = (*i)->start() - pos;
}
-
+
if (slop == 0 && delta == 0) {
/* special case: no slop, and direct hit for position */
return *i;
LocationStartEarlierComparison cmp;
sort (locs.begin(), locs.end(), cmp);
-
+
/* locs is sorted in reverse order */
for (vector<LocationPair>::iterator i = locs.begin(); i != locs.end(); ++i) {
static bool lv2_filter (const string& str, void* /*arg*/)
{
/* Not a dotfile, has a prefix before a period, suffix is "lv2" */
-
+
return str[0] != '.' && (str.length() > 3 && str.find (".lv2") == (str.length() - 4));
}
/* two events at identical times. we need to determine
the order in which they should occur.
-
+
the rule is:
-
+
Controller messages
Program Change
Note Off
Channel Pressure
Pitch Bend
*/
-
+
if ((a) >= 0xf0 || (b) >= 0xf0 || ((a & 0xf) != (b & 0xf))) {
-
+
/* if either message is not a channel message, or if the channels are
* different, we don't care about the type.
*/
-
+
b_first = true;
-
+
} else {
-
+
switch (b & 0xf0) {
case MIDI_CMD_CONTROL:
b_first = true;
break;
-
+
case MIDI_CMD_PGM_CHANGE:
switch (a & 0xf0) {
case MIDI_CMD_CONTROL:
b_first = true;
}
break;
-
+
case MIDI_CMD_NOTE_OFF:
switch (a & 0xf0) {
case MIDI_CMD_CONTROL:
b_first = true;
}
break;
-
+
case MIDI_CMD_NOTE_ON:
switch (a & 0xf0) {
case MIDI_CMD_CONTROL:
b_first = true;
}
break;
-
+
case MIDI_CMD_CHANNEL_PRESSURE:
switch (a & 0xf0) {
case MIDI_CMD_CONTROL:
break;
}
}
-
+
return b_first;
}
-
+
/** Merge \a other into this buffer. Realtime safe. */
bool
MidiBuffer::merge_in_place (const MidiBuffer &other)
(*us).time(), (*them).time(),
(int) *(_data + us.offset + sizeof (TimeType)),
(int) *(other._data + them.offset + sizeof (TimeType))));
-
+
uint8_t our_midi_status_byte = *(_data + us.offset + sizeof (TimeType));
uint8_t their_midi_status_byte = *(other._data + them.offset + sizeof (TimeType));
bool them_first = second_simultaneous_midi_byte_is_first (our_midi_status_byte, their_midi_status_byte);
-
+
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("other message came first ? %1\n", them_first));
-
+
if (!them_first) {
/* skip past our own event */
++us;
}
-
+
bytes_to_merge = sizeof (TimeType) + (*them).size();
-
+
/* move our remaining events later in the buffer by
* enough to fit the one message we're going to merge
*/
++them;
} else {
-
+
/* advance past our own events to get to the correct insertion
point for the next event(s) from "other"
*/
-
+
while (us != end() && (*us).time() <= (*them).time()) {
++us;
}
if (us == end()) {
/* just append the rest of other and we're done*/
-
+
memcpy (_data + us.offset, other._data + them.offset, other._size - them.offset);
_size += other._size - them.offset;
assert(_size <= _capacity);
that it can read it if it likes.
*/
_gui_feed_buffer.clear ();
-
+
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
/* This may fail if buf is larger than _gui_feed_buffer, but it's not really
the end of the world if it does.
if (need_disk_signal) {
/* copy the diskstream data to all output buffers */
-
+
MidiBuffer& mbuf (bufs.get_midi (0));
get_playback (mbuf, playback_distance);
* but we do need to check so that the decision on whether or not we
* need the butler is done correctly.
*/
-
+
/* furthermore..
*
* Doing heavy GUI operations[1] can stall also the butler.
id(), this_read, start) << endmsg;
return -1;
}
-
+
g_atomic_int_add (&_frames_written_to_ringbuffer, this_read);
if (reversed) {
} else {
disengage_record_enable ();
}
-
+
RecordEnableChanged (); /* EMIT SIGNAL */
}
}
if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) { // REQUIRES REVIEW
return;
}
-
+
/* yes, i know that this not proof against race conditions, but its
good enough. i think.
*/
-
+
if (record_safe () != yn) {
if (yn) {
engage_record_safe ();
} else {
disengage_record_safe ();
}
-
+
RecordSafeChanged (); /* EMIT SIGNAL */
}
}
bool const rolling = _session.transport_speed() != 0.0f;
boost::shared_ptr<MidiPort> sp = _source_port.lock ();
-
+
if (sp && Config->get_monitoring_model() == HardwareMonitoring) {
sp->request_input_monitoring (!(_session.config.get_auto_input() && rolling));
}
try {
string new_path = _session.new_midi_source_path (name());
-
+
if (_write_source->rename (new_path)) {
return string();
}
} catch (...) {
return string ();
}
-
+
return our_old_name;
}
MidiDiskstream::ensure_input_monitoring (bool yn)
{
boost::shared_ptr<MidiPort> sp = _source_port.lock ();
-
+
if (sp) {
sp->ensure_input_monitoring (yn);
}
MidiDiskstream::playback_buffer_load () const
{
/* For MIDI it's not trivial to differentiate the following two cases:
-
+
1. The playback buffer is empty because the system has run out of time to fill it.
2. The playback buffer is empty because there is no more data on the playlist.
cannot keep up when #2 happens, when in fact it can. Since MIDI data rates
are so low compared to audio, just give a pretend answer here.
*/
-
+
return 1;
}
MidiDiskstream::capture_buffer_load () const
{
/* We don't report playback buffer load, so don't report capture load either */
-
+
return 1;
}
// _playback_buf->dump (cerr);
// cerr << "----------------\n";
- size_t events_read = 0;
+ size_t events_read = 0;
if (loc) {
framepos_t effective_start;
} else {
effective_start = playback_sample;
}
-
+
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("looped, effective start adjusted to %1\n", effective_start));
if (effective_start == loc->start()) {
loc->start(), second));
events_read += _playback_buf->read (dst, loc->start(), second);
}
-
+
} else {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #3, adjusted start as %1 for %2\n",
effective_start, nframes));
MidiDiskstream::get_gui_feed_buffer () const
{
boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
-
+
Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex);
b->copy (_gui_feed_buffer);
return b;
_removed_notes.push_back (*i);
}
}
-
+
if (!side_effect_removals.empty()) {
cerr << "SER: \n";
for (set<NotePtr>::iterator i = side_effect_removals.begin(); i != side_effect_removals.end(); ++i) {
assert (i->note);
}
}
-
+
for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
Property prop = i->property;
_model->add_note_unlocked (*i);
}
}
-
+
_model->ContentsChanged(); /* EMIT SIGNAL */
}
int channel = 0;
int program = 0;
int bank = 0;
-
+
if ((prop_id = n->property ("id")) != 0) {
istringstream s (prop_id->value());
s >> id;
MidiModel::control_list_marked_dirty ()
{
AutomatableSequence<Evoral::Beats>::control_list_marked_dirty ();
-
+
ContentsChanged (); /* EMIT SIGNAL */
}
if (!_session) {
return;
}
-
+
std::string path_to_patches = _session->session_directory().midi_patch_path();
if (!Glib::file_test (path_to_patches, Glib::FILE_TEST_EXISTS)) {
<< endmsg;
continue;
}
-
+
_documents[device->first] = document;
_master_devices_by_model[device->first] = device->second;
MidiBuffer& mb (get_midi_buffer (nframes));
/* dump incoming MIDI to parser */
-
+
for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) {
uint8_t* buf = (*b).buffer();
-
+
_self_parser.set_timestamp (now + (*b).time());
-
+
uint32_t limit = (*b).size();
-
+
for (size_t n = 0; n < limit; ++n) {
_self_parser.scanner (buf[n]);
}
*/
for (pframes_t i = 0; i < event_count; ++i) {
-
+
pframes_t timestamp;
size_t size;
uint8_t* buf;
-
+
port_engine.midi_event_get (timestamp, size, &buf, buffer, i);
-
+
if (buf[0] == 0xfe) {
/* throw away active sensing */
continue;
buf[0] = 0x80 | (buf[0] & 0x0F); /* note off */
buf[2] = 0x40; /* default velocity */
}
-
+
/* check that the event is in the acceptable time range */
-
+
if ((timestamp >= (_global_port_buffer_offset + _port_buffer_offset)) &&
(timestamp < (_global_port_buffer_offset + _port_buffer_offset + nframes))) {
_buffer->push_back (timestamp, size, buf);
if (sends_output ()) {
void* port_buffer = 0;
-
+
if (_resolve_required) {
port_buffer = port_engine.get_buffer (_port_handle, nframes);
/* resolve all notes at the start of the buffer */
resolve_notes (port_buffer, 0);
_resolve_required = false;
}
-
+
if (_buffer->empty()) {
return;
}
if (sends_output() && _trace_on) {
uint8_t const * const buf = ev.buffer();
- const framepos_t now = AudioEngine::instance()->sample_time_at_cycle_start();
+ const framepos_t now = AudioEngine::instance()->sample_time_at_cycle_start();
_self_parser.set_timestamp (now + ev.time());
-
+
uint32_t limit = ev.size();
-
+
for (size_t n = 0; n < limit; ++n) {
_self_parser.scanner (buf[n]);
}
assert (success);
ev_time = *(reinterpret_cast<T*>((uintptr_t)peekbuf));
-
+
if (ev_time >= end) {
break;
}
buf[0] = 0xB0 | (_channel & 0xf);
buf[1] = 0x20;
- buf[2] = _bank & 0x7f;
+ buf[2] = _bank & 0x7f;
return 3;
}
, last_program_message_time (-1)
, last_delivered_program (-1)
, last_delivered_bank (-1)
-
+
{
/* catch any add/remove/clear etc. for all Locations */
_session.locations()->changed.connect_same_thread (*this, boost::bind (&MIDISceneChanger::locations_changed, this));
if (msc->bank() >= 0) {
have_seen_bank_changes = true;
}
-
+
scenes.insert (std::make_pair ((*l)->start(), msc));
}
}
}
Glib::Threads::RWLock::ReaderLock lm (scene_lock, Glib::Threads::TRY_LOCK);
-
+
if (!lm.locked()) {
return;
}
if (i->first >= end) {
break;
}
-
+
rt_deliver (mbuf, i->first - start, i->second);
-
+
++i;
}
}
if (scenes.empty()) {
return;
}
-
+
Scenes::const_iterator i = scenes.lower_bound (pos);
-
+
if (i != scenes.end()) {
if (i->first != pos) {
if (msc->program() != last_delivered_program || msc->bank() != last_delivered_bank) {
non_rt_deliver (msc);
}
-}
+}
void
MIDISceneChanger::set_input_port (MIDI::Port* mp)
input_port = mp;
incoming_connections.drop_connections();
-
+
if (input_port) {
-
+
/* midi port is asynchronous. MIDI parsing will be carried out
* by the MIDI UI thread which will emit the relevant signals
* and thus invoke our callbacks as necessary.
if (!loc) {
/* create a new marker at the desired position */
-
+
std::string new_name;
if (!locations->next_available_name (new_name, _("Scene "))) {
std::cerr << "No new marker name available\n";
return;
}
-
+
loc = new Location (_session, time, time, new_name, Location::IsMark);
new_mark = true;
}
}
loc->set_scene_change (boost::shared_ptr<MIDISceneChange> (msc));
-
+
/* this will generate a "changed" signal to be emitted by locations,
and we will call ::gather() to update our list of MIDI events.
*/
void
MidiStateTracker::remove (uint8_t note, uint8_t chn)
-{
+{
switch (_active_notes[note + 128 * chn]) {
case 0:
break;
if (_step_editing) { /* REQUIRES REVIEW */
return;
}
-
+
Track::set_record_safe (yn, src);
}
*/
boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream> (ds);
mds->set_note_mode (_note_mode);
-
+
Track::set_diskstream (ds);
- mds->reset_tracker ();
+ mds->reset_tracker ();
_diskstream->set_track (this);
if (Profile->get_trx()) {
}
-
+
/* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
-
+
write_out_of_band_data (bufs, start_frame, end_frame, nframes);
-
+
/* final argument: don't waste time with automation if we're not recording or rolling */
-
+
process_output_buffers (bufs, start_frame, end_frame, nframes,
declick, (!diskstream->record_enabled() && !_session.transport_stopped()));
}
need_butler = diskstream->commit (playback_distance);
-
+
return 0;
}
midi_diskstream()->resolve_tracker(_immediate_events, 0);
}
}
-
+
void
MidiTrack::set_monitoring (MonitorChoice mc)
{
if (mc != _monitoring) {
Track::set_monitoring (mc);
-
+
/* monitoring state changed, so flush out any on notes at the
* port level.
*/
PortSet& ports (_output->ports());
-
+
for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
if (mp) {
}
boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
-
+
if (md) {
md->reset_tracker ();
}
{
vector<AsyncMIDIPort*> ports;
AsyncMIDIPort* p;
-
+
if ((p = dynamic_cast<AsyncMIDIPort*> (_session.midi_input_port()))) {
ports.push_back (p);
}
-
-
+
+
if ((p = dynamic_cast<AsyncMIDIPort*> (_session.mmc_input_port()))) {
ports.push_back (p);
}
if ((p = dynamic_cast<AsyncMIDIPort*> (_session.scene_input_port()))) {
ports.push_back (p);
}
-
+
if (ports.empty()) {
return;
}
-
+
for (vector<AsyncMIDIPort*>::const_iterator pi = ports.begin(); pi != ports.end(); ++pi) {
(*pi)->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &MidiControlUI::midi_input_handler), *pi));
(*pi)->xthread().attach (_main_loop->get_context());
if (_midi_in) {
return;
}
-
+
_midi_in = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("MIDI control in"), true);
_midi_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("MIDI control out"), true);
ports.insert (make_pair (_mmc_output_port->name(), _mmc_out));
ports.insert (make_pair (_scene_output_port->name(), _scene_out));
ports.insert (make_pair (_scene_input_port->name(), _scene_in));
-
+
for (XMLNodeList::const_iterator n = nodes.begin(); n != nodes.end(); ++n) {
if ((prop = (*n)->property (X_("name"))) == 0) {
continue;
if (p == ports.end()) {
continue;
}
-
+
p->second->set_state (**n, version);
}
}
/* don't double-scale by both track dim and global dim coefficients */
gain_t dim_level = (global_dim == GAIN_COEFF_UNITY ? (_channels[chn]->dim ? dim_level_this_time : GAIN_COEFF_UNITY) : GAIN_COEFF_UNITY);
-
+
if (_channels[chn]->soloed) {
target_gain = _channels[chn]->polarity * _channels[chn]->cut * dim_level * global_cut * global_dim * solo_boost;
} else {
, _responding_to_control_auto_state_change (0)
{
//boost_debug_shared_ptr_mark_interesting (this, "pannable");
-
+
add_control (pan_azimuth_control);
add_control (pan_elevation_control);
add_control (pan_width_control);
}
_panner.reset ();
-
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == X_("Panner")) {
if (yn == _bypassed) {
return;
}
-
+
_bypassed = yn;
_session.set_dirty ();
Changed (); /* EMIT SIGNAL */
pending_contents_change = false;
RegionAdded (boost::weak_ptr<Region> (r)); /* EMIT SIGNAL */
ContentsChanged (); /* EMIT SIGNAL */
-
+
}
}
remove_dependents (*s);
RegionRemoved (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
}
-
+
for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
crossfade_ranges.push_back ((*s)->range ());
/* don't emit RegionAdded signal until relayering is done,
pending_layering = true;
ContentsChanged (); /* EMIT SIGNAL */
}
-
+
for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
(*s)->clear_changes ();
RegionAdded (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
}
-
+
if ((regions_changed && !in_set_state) || pending_layering) {
relayer ();
}
-
+
coalesce_and_check_crossfades (crossfade_ranges);
-
+
if (!pending_range_moves.empty ()) {
/* We don't need to check crossfades for these as pending_bounds has
already covered it.
*/
RangesMoved (pending_range_moves, from_undo);
}
-
+
if (!pending_region_extensions.empty ()) {
RegionsExtended (pending_region_extensions);
}
while (itimes--) {
for (RegionList::iterator i = other->regions.begin(); i != other->regions.end(); ++i) {
boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i, true);
-
+
/* put these new regions on top of all existing ones, but preserve
the ordering they had in the original playlist.
*/
-
+
add_region_internal (copy_of_region, (*i)->position() + pos);
set_layer (copy_of_region, copy_of_region->layer() + top);
}
} else if (new_pos >= limit ) {
new_pos = limit;
}
-
+
(*i)->set_position (new_pos);
}
}
Playlist::find_regions_at (framepos_t frame)
{
/* Caller must hold lock */
-
+
boost::shared_ptr<RegionList> rlist (new RegionList);
-
+
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if ((*i)->covers (frame)) {
rlist->push_back (*i);
}
}
-
+
return rlist;
}
Playlist::regions_touched_locked (framepos_t start, framepos_t end)
{
boost::shared_ptr<RegionList> rlist (new RegionList);
-
+
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if ((*i)->coverage (start, end) != Evoral::OverlapNone) {
rlist->push_back (*i);
}
}
-
+
return rlist;
}
RegionReadLock rlock (this);
AnalysisFeatureList points;
AnalysisFeatureList these_points;
-
+
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
if (dir > 0) {
if ((*i)->last_frame() < from) {
continue;
}
}
-
+
(*i)->get_transients (these_points);
-
+
/* add first frame, just, err, because */
-
+
these_points.push_back ((*i)->first_frame());
-
+
points.insert (points.end(), these_points.begin(), these_points.end());
these_points.clear ();
}
-
+
if (points.empty()) {
return -1;
}
-
+
TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
bool reached = false;
-
+
if (dir > 0) {
for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
if ((*x) >= from) {
reached = true;
}
-
+
if (reached && (*x) > from) {
return *x;
}
if ((*x) <= from) {
reached = true;
}
-
+
if (reached && (*x) < from) {
return *x;
}
}
}
-
+
return -1;
}
RegionReadLock rlock (this);
boost::shared_ptr<Region> ret;
framepos_t closest = max_framepos;
-
+
bool end_iter = false;
-
+
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-
+
if(end_iter) break;
-
+
frameoffset_t distance;
boost::shared_ptr<Region> r = (*i);
framepos_t pos = 0;
-
+
switch (point) {
case Start:
pos = r->first_frame ();
pos = r->sync_position ();
break;
}
-
+
switch (dir) {
case 1: /* forwards */
-
+
if (pos > frame) {
if ((distance = pos - frame) < closest) {
closest = distance;
end_iter = true;
}
}
-
+
break;
-
+
default: /* backwards */
-
+
if (pos < frame) {
if ((distance = frame - pos) < closest) {
closest = distance;
} else {
end_iter = true;
}
-
+
break;
}
}
-
+
return ret;
}
RegionWriteLock rlock (this);
add_region_internal (region, region->position());
}
-
+
region->resume_property_changes ();
}
if (seen_region_nodes && regions.empty()) {
ret = -1;
}
-
+
thaw ();
notify_contents_changed ();
}
++i;
}
-
+
copy.insert (i, region);
setup_layering_indices (copy);
} else if (type->value() == "midi") {
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, node, hidden));
}
-
+
pl->set_region_ownership ();
-
+
if (pl && !hidden) {
PlaylistCreated (pl, unused);
}
pl = boost::shared_ptr<Playlist> (new AudioPlaylist (s, name, hidden));
else if (type == DataType::MIDI)
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (s, name, hidden));
-
+
if (pl && !hidden) {
PlaylistCreated (pl, false);
}
-
+
return pl;
} catch (...) {
return boost::shared_ptr<Playlist> ();
boost::shared_ptr<Playlist> pl;
boost::shared_ptr<const AudioPlaylist> apl;
boost::shared_ptr<const MidiPlaylist> mpl;
-
+
try {
if ((apl = boost::dynamic_pointer_cast<const AudioPlaylist> (old)) != 0) {
if (pl && !hidden) {
PlaylistCreated (pl, false);
}
-
+
return pl;
} catch (...) {
return boost::shared_ptr<Playlist> ();
}
-
+
}
boost::shared_ptr<Playlist>
pl = boost::shared_ptr<Playlist> (new MidiPlaylist (mpl, start, cnt, name, hidden));
pl->set_region_ownership ();
}
-
+
/* this factory method does NOT notify others */
-
+
return pl;
} catch (...) {
return boost::shared_ptr<Playlist> ();
root->add_property (X_("last-preset-label"), _last_preset.label);
root->add_property (X_("parameter-changed-since-last-preset"), _parameter_changed_since_last_preset ? X_("yes") : X_("no"));
-#ifndef NO_PLUGIN_STATE
+#ifndef NO_PLUGIN_STATE
add_state (root);
#else
if (!seen_get_state_message) {
}
DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, input streams = %1, match using %2\n", in, _match.method));
-
+
if (_match.method == Split) {
/* we are splitting 1 processor input to multiple plugin inputs,
return in;
} else {
-
+
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
in.set (*t, in.get (*t) * _plugins.size ());
}
We allow replication only for plugins with either zero or 1 inputs and outputs
for every valid data type.
*/
-
+
uint32_t f = 0;
bool can_replicate = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
bool could_hide = false;
bool cannot_hide = false;
ChanCount hide_channels;
-
+
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
if (inputs.get(*t) > in.get(*t)) {
/* there is potential to hide, since the plugin has more inputs of type t than the insert */
PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
{
plugin->set_insert_id (this->id());
-
+
if (_plugins.empty()) {
/* first (and probably only) plugin instance - connect to relevant signals
*/
cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n";
throw failed_constructor ();
}
-
+
PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this));
}
Port::disconnect_all ()
{
if (_port_handle) {
-
+
port_engine.disconnect_all (_port_handle);
_connections.clear ();
-
+
/* a cheaper, less hacky way to do boost::shared_from_this() ...
*/
boost::shared_ptr<Port> pself = port_manager->get_port_by_name (name());
if (_port_handle) {
r = port_engine.get_latency_range (_port_handle, sends_output() ? true : false);
-
+
DEBUG_TRACE (DEBUG::Latency, string_compose (
"GET PORT %1: %4 PUBLIC latency range %2 .. %3\n",
name(), r.min, r.max,
}
vector<string> c;
-
+
get_connections (c);
for (vector<string>::const_iterator i = c.begin(); i != c.end(); ++i) {
if ((*c)->name() != X_("Connection")) {
continue;
}
-
+
if ((prop = (*c)->property (X_("other"))) == 0) {
continue;
}
Sample* out = outbuf.data();
_mtdm->process (nframes, in, out);
-
+
outbuf.set_written (true);
}
boost::shared_ptr<const Ports> pr = ports.reader();
const string::size_type len = first_part_of_port_name.length();
-
+
for (Ports::const_iterator x = pr->begin(); x != pr->end(); ++x) {
string prefix = x->first.substr (0, len);
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> p = writer.get_copy();
Ports::iterator x = p->find (old_relative_name);
-
+
if (x != p->end()) {
boost::shared_ptr<Port> port = x->second;
p->erase (x);
if (!Profile->get_trx()) {
/* re-establish connections */
-
+
DEBUG_TRACE (DEBUG::Ports, string_compose ("reconnect %1 ports\n", p->size()));
-
+
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->reconnect ();
}
port_b, b,
conn
); /* EMIT SIGNAL */
-}
+}
void
PortManager::registration_callback ()
if (!_backend) {
return 0;
}
-
+
return _backend->port_name_size ();
}
if (!_backend) {
return string();
}
-
+
return _backend->my_name();
}
PortManager::check_monitoring ()
{
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
-
+
bool x;
-
+
if (i->second->last_monitor() != (x = i->second->monitoring_input ())) {
i->second->set_last_monitor (x);
/* XXX I think this is dangerous, due to
PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes)
{
for (Ports::iterator i = _cycle_ports->begin(); i != _cycle_ports->end(); ++i) {
-
+
if (i->second->sends_output()) {
-
+
boost::shared_ptr<AudioPort> ap = boost::dynamic_pointer_cast<AudioPort> (i->second);
if (ap) {
Sample* s = ap->engine_get_whole_audio_buffer ();
gain_t g = base_gain;
-
+
for (pframes_t n = 0; n < nframes; ++n) {
*s++ *= g;
g -= gain_step;
sort(v.begin(), v.end(), sort_ports_by_name);
sort(_all_ports.begin(), _all_ports.end(), sort_ports_by_type_and_name);
-
+
_count.set(port->type(), _count.get(port->type()) + 1);
assert(_count.get(port->type()) == _ports[port->type()].size());
}
if (i != _all_ports.end()) {
_all_ports.erase(i);
}
-
+
for (std::vector<PortVec>::iterator l = _ports.begin(); l != _ports.end(); ++l) {
PortVec::iterator i = find(l->begin(), l->end(), port);
if (i != l->end()) {
XMLProperty const * prop;
XMLNodeList children = node.children ();
-
+
for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
if ((*i)->name() == X_("IO")) {
-
+
if ((prop = (*i)->property ("name")) != 0) {
set_name (prop->value ());
}
-
+
set_id (**i);
//note: in A2, active state was stored in the Redirect node, not the child IO node
}
}
}*/
-
+
}
}
*/
Processor::set_name (prop->value());
}
-
+
set_id (node);
}
/* now correct for start-of-model offset */
pos += offset;
-
+
if (fabs (pos - swung_pos) > fabs (pos - swung_previous_grid_position)) {
pos = swung_previous_grid_position;
} else {
* these versions of new_start and new_end are
* guaranteed to precisely align with the quantize grid(s).
*/
-
+
double new_start = round (((*i)->time().to_double() - offset) / _start_grid) * _start_grid;
double new_end = round (((*i)->end_time().to_double() - offset) / _end_grid) * _end_grid;
new_start = swing_position (new_start, _start_grid, _swing, offset);
new_end = swing_position (new_end, _end_grid, _swing, offset);
-
+
} else {
/* now correct for start-of-model offset */
new_start += offset;
new_end += offset;
}
-
+
double delta = new_start - (*i)->time().to_double();
-
+
if (fabs (delta) >= _threshold) {
if (_snap_start) {
delta *= _strength;
e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
*/
_last_position = _position;
-
+
if (_position != pos) {
_position = pos;
return _position + (minlen - _start) - 1;
}
-
+
if (ret) {
ret->set_name (new_region_name(ret->name()));
ret->set_position (region->position());
-
+
if (ret->session().config.get_glue_new_regions_to_bars_and_beats ()) {
ret->set_position_lock_style (MusicTime);
}
if (ret->session().config.get_glue_new_regions_to_bars_and_beats ()) {
ret->set_position_lock_style (MusicTime);
}
-
+
if (announce) {
map_add (ret);
CheckNewRegion (ret);
if (ret->session().config.get_glue_new_regions_to_bars_and_beats ()) {
ret->set_position_lock_style (MusicTime);
}
-
+
if (announce) {
map_add (ret);
CheckNewRegion (ret);
/* Don't fiddle with position_lock_style here as the region
description is coming from XML.
*/
-
+
CheckNewRegion (ret);
}
}
if (!r) {
return;
}
-
+
Glib::Threads::Mutex::Lock lm (region_map_lock);
RegionMap::iterator i = region_map.find (r->id());
update_region_name_number_map (region);
Glib::Threads::Mutex::Lock lm (region_name_maps_mutex);
-
+
map<string, PBD::ID>::iterator i = region_name_map.begin();
while (i != region_name_map.end() && i->second != region->id ()) {
++i;
RegionMap::iterator j = i;
++j;
-
+
if (i->second->uses_source (src)) {
remove_from_region_name_map (i->second->name ());
region_map.erase (i);
on a transition between monitoring states we get a de-clicking gain
change in the _main_outs delivery, if config.get_use_monitor_fades()
is true.
-
+
We override this in the case where we have an internal generator.
*/
bool silence = _have_internal_generator ? false : (monitoring_state () == MonitoringSilence);
-
+
_main_outs->no_outs_cuz_we_no_monitor (silence);
/* -------------------------------------------------------------------------------------------
}
}
-
+
if (!changed) {
return;
}
-
+
/* forward propagate solo-isolate status to everything fed by this route, but not those via sends only */
boost::shared_ptr<RouteList> routes = _session.get_routes ();
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
-
+
if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
continue;
}
-
+
bool sends_only;
bool does_feed = feeds (*i, &sends_only);
-
+
if (does_feed && !sends_only) {
(*i)->mod_solo_isolated_by_upstream (yn, src);
}
}
-
+
/* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
solo_isolated_changed (src);
//master is never muted by others
if (is_master())
return false;
-
+
//now check to see if something is soloed (and I am not)
return (_session.soloing() && !self_soloed() && !solo_isolated());
}
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
ProcessorList::iterator loc;
-
+
if (p == PreFader) {
/* generic pre-fader: insert immediately before the amp */
loc = find (_processors.begin(), _processors.end(), _amp);
}
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
-
+
ProcessorList::iterator i = _processors.begin ();
int j = 0;
while (i != _processors.end() && j < index) {
if ((*i)->display_to_user()) {
++j;
}
-
+
++i;
}
if (processor->set_state (node, version)) {
return false;
}
-
+
//A2 uses the "active" flag in the toplevel redirect node, not in the child plugin/IO
if (i != children.end()) {
if ((prop = (*i)->property (X_("active"))) != 0) {
if (_processors.empty()) {
return;
}
-
+
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (!(*i)->display_to_user() || boost::dynamic_pointer_cast<Amp> (*i)) {
continue;
}
-
+
if (state) {
(*i)->activate ();
} else {
again:
for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ++x) {
-
+
boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
-
+
if (d && d->target_route() == route) {
rl.release ();
if (remove_processor (*x, &err, false) > 0) {
/* Set up the meter for its new position */
ProcessorList::iterator loc = find (_processors.begin(), _processors.end(), _meter);
-
+
ChanCount m_in;
-
+
if (loc == _processors.begin()) {
m_in = _input->n_ports();
} else {
XMLNodeList children = node.children();
for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
-
+
if ((*i)->name() == X_("IO")) {
IO::set_name_in_state (**i, name);
if (role && role->value() == X_("Main")) {
(*i)->add_property (X_("name"), name);
}
-
+
} else if ((*i)->name() == X_("Diskstream")) {
(*i)->add_property (X_("playlist"), string_compose ("%1.1", name).c_str());
(*i)->add_property (X_("name"), name);
-
+
}
}
}
} else {
all_connections.min = ~((pframes_t) 0);
all_connections.max = 0;
-
+
/* iterate over all "from" ports and determine the latency range for all of their
connections to the "outside" (outside of this Route).
*/
-
+
for (PortSet::iterator p = from.begin(); p != from.end(); ++p) {
-
+
LatencyRange range;
-
+
p->get_connected_latency_range (range, playback);
-
+
all_connections.min = min (all_connections.min, range.min);
all_connections.max = max (all_connections.max, range.max);
}
if (_meter_point != MeterCustom) {
return;
}
-
+
_custom_meter_position_noted = true;
/* custom meter points range from after trim to before panner/main_outs
* this is a limitation by the current processor UI
/* ignore inactive processors and obviously ignore the main
* outs since everything has them and we don't care.
*/
-
+
if ((*i)->active() && (*i) != _main_outs && (*i)->does_routing()) {
return true;;
}
{
//Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
-
+
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
(*i)->transport_located (pos);
}
{
size_t n_buffers;
size_t i;
-
+
/* MIDI
*
* We don't currently mix MIDI input together, so we don't need the
boost::shared_ptr<MidiPort> source_port = io->midi (i);
MidiBuffer& buf (bufs.get_midi (i));
-
+
if (source_port) {
buf.copy (source_port->get_midi_buffer(nframes));
} else {
if (n_ports > n_buffers) {
scaling = ((float) n_buffers) / n_ports;
}
-
+
for (i = 0; i < n_ports; ++i) {
-
+
/* if there are more ports than buffers, map them onto buffers
* in a round-robin fashion
*/
boost::shared_ptr<AudioPort> source_port = io->audio (i);
AudioBuffer& buf (bufs.get_audio (i%n_buffers));
-
+
if (i < n_buffers) {
-
+
/* first time through just copy a channel into
the output buffer.
*/
if (scaling != 1.0f) {
buf.apply_gain (scaling, nframes);
}
-
+
} else {
-
+
/* on subsequent times around, merge data from
* the port with what is already there
*/
if (i == _from_to_with_sends.end ()) {
return false;
}
-
+
if (via_sends_only) {
*via_sends_only = i->second.second;
}
if (i == _from_to.end ()) {
return set<GraphVertex> ();
}
-
+
return i->second;
}
if (i->second.empty ()) {
_from_to.erase (i);
}
-
+
EdgeMap::iterator j = _to_from.find (to);
assert (j != _to_from.end ());
j->second.erase (from);
}
cout << "\n";
}
-
+
for (EdgeMap::const_iterator i = _to_from.begin(); i != _to_from.end(); ++i) {
cout << "TO: " << i->first->name() << " ";
for (set<GraphVertex>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
)
{
boost::shared_ptr<RouteList> sorted_routes (new RouteList);
-
+
/* queue of routes to process */
RouteList queue;
/* Do the sort: algorithm is Kahn's from Wikipedia.
`Topological sorting of large networks', Communications of the ACM 5(11):558-562.
*/
-
+
while (!queue.empty ()) {
GraphVertex r = queue.front ();
queue.pop_front ();
if (r->route_group()) {
r->route_group()->remove (r);
}
-
+
routes->push_back (r);
r->set_route_group (this);
factor = 0.0000003f / g - 1.0f;
}
-
+
return factor;
}
Searchpath spath(user_config_directory ());
spath += ardour_dll_directory ();
spath.add_subdirectory_to_paths (surfaces_dir_name);
-
+
spath += Searchpath(Glib::getenv(surfaces_env_variable_name));
return spath;
}
abort(); /*NOTREACHED*/
return string();
}
-
+
}
Send::Send (Session& s, boost::shared_ptr<Pannable> p, boost::shared_ptr<MuteMaster> mm, Role r, bool ignore_bitslot)
/* don't try to reset bitslot if there is a node for it already: this can cause
issues with the session's accounting of send ID's
*/
-
+
if ((prop = node.property ("bitslot")) == 0) {
if (_role == Delivery::Aux) {
_bitslot = _session.next_aux_send_id ();
}
}
}
-
+
XMLNodeList nlist = node.children();
for (XMLNodeIterator i = nlist.begin(); i != nlist.end(); ++i) {
if ((*i)->name() == X_("Processor")) {
return _amp->value_as_string (ac);
}
-
+
, loop_changing (false)
, last_loopend (0)
, _session_dir (new SessionDirectory (fullpath))
- , _current_snapshot_name (snapshot_name)
+ , _current_snapshot_name (snapshot_name)
, state_tree (0)
, state_was_pending (false)
, _state_of_the_state (StateOfTheState(CannotSave|InitialConnecting|Loading))
pthread_cond_init (&_rt_emit_cond, 0);
pre_engine_init (fullpath);
-
+
if (_is_new) {
Stateful::loading_state_version = CURRENT_SESSION_FILE_VERSION;
-#ifdef USE_TRACKS_CODE_FEATURES
+#ifdef USE_TRACKS_CODE_FEATURES
sr = EngineStateController::instance()->get_current_sample_rate();
#endif
if (ensure_engine (sr)) {
if (load_state (_current_snapshot_name)) {
throw SessionException (_("Failed to load state"));
}
-
+
/* try to get sample rate from XML state so that we
* can influence the SR if we set up the audio
* engine.
if (state_tree) {
const XMLProperty* prop;
- if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {
+ if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {
sr = atoi (prop->value());
}
}
_engine.reset_timebase ();
#ifdef USE_TRACKS_CODE_FEATURES
-
+
EngineStateController::instance()->set_session(this);
-
+
if (_is_new ) {
if ( ARDOUR::Profile->get_trx () ) {
/* Waves Tracks: fill session with tracks basing on the amount of inputs.
* each available input must have corresponding track when session starts.
*/
-
+
uint32_t how_many (0);
-
+
std::vector<std::string> inputs;
EngineStateController::instance()->get_physical_audio_inputs(inputs);
-
+
how_many = inputs.size();
-
+
list<boost::shared_ptr<AudioTrack> > tracks;
-
+
// Track names after driver
if (Config->get_tracks_auto_naming() == NameAfterDriver) {
string track_name = "";
string track_name;
track_name = inputs[i];
replace_all (track_name, "system:capture", "");
-
+
list<boost::shared_ptr<AudioTrack> > single_track = new_audio_track (1, 1, Normal, 0, 1, track_name);
tracks.insert(tracks.begin(), single_track.front());
}
} else { // Default track names
tracks = new_audio_track (1, 1, Normal, 0, how_many, string());
}
-
+
if (tracks.size() != how_many) {
destroy ();
throw failed_constructor ();
}
}
#endif
-
+
_is_new = false;
session_loaded ();
Session::~Session ()
{
-#ifdef PT_TIMING
+#ifdef PT_TIMING
ST.dump ("ST.dump");
-#endif
+#endif
destroy ();
}
* know that the engine is running, but before we either create a
* session or set state for an existing one.
*/
-
+
if (how_many_dsp_threads () > 1) {
/* For now, only create the graph if we are using >1 DSP threads, as
it is a bit slower than the old code with 1 thread.
/* shutdown control surface protocols while we still have ports
and the engine to move data to any devices.
*/
-
+
ControlProtocolManager::instance().drop_protocols ();
-
+
_engine.remove_session ();
#ifdef USE_TRACKS_CODE_FEATURES
_butler->drop_references ();
delete _butler;
_butler = 0;
-
+
delete _all_route_group;
DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n");
delete _locations; _locations = 0;
delete _tempo_map;
-
+
DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
Session::setup_ltc ()
{
XMLNode* child = 0;
-
+
_ltc_input.reset (new IO (*this, X_("LTC In"), IO::Input));
_ltc_output.reset (new IO (*this, X_("LTC Out"), IO::Output));
-
+
if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC In"))) != 0) {
_ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
} else {
}
reconnect_ltc_input ();
}
-
+
if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC Out"))) != 0) {
_ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
} else {
}
reconnect_ltc_output ();
}
-
+
/* fix up names of LTC ports because we don't want the normal
* IO style of NAME/TYPE-{in,out}N
*/
-
+
_ltc_input->nth (0)->set_name (X_("LTC-in"));
_ltc_output->nth (0)->set_name (X_("LTC-out"));
}
void
Session::setup_click_state (const XMLNode* node)
-{
+{
const XMLNode* child = 0;
-
+
if (node && (child = find_named_node (*node, "Click")) != 0) {
-
+
/* existing state for Click */
int c = 0;
}
}
}
-
+
if (c == 0) {
_clicking = Config->get_clicking ();
if (!_master_out || !Config->get_auto_connect_standard_busses() || _monitor_out) {
return;
}
-
+
// Waves Tracks: Do not connect master bas for Tracks if AutoConnectMaster option is not set
// In this case it means "Multi Out" output mode
if (ARDOUR::Profile->get_trx() && !(Config->get_output_auto_connect() & AutoConnectMaster) ) {
/* if requested auto-connect the outputs to the first N physical ports.
*/
-
+
uint32_t limit = _master_out->n_outputs().n_total();
vector<string> outputs[DataType::num_types];
-
+
for (uint32_t i = 0; i < DataType::num_types; ++i) {
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
}
-
+
for (uint32_t n = 0; n < limit; ++n) {
boost::shared_ptr<Port> p = _master_out->output()->nth (n);
string connect_to;
if (outputs[p->type()].size() > n) {
connect_to = outputs[p->type()][n];
}
-
+
if (!connect_to.empty() && p->connected_to (connect_to) == false) {
if (_master_out->output()->connect (p, connect_to, this)) {
error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
/* Hold process lock while doing this so that we don't hear bits and
* pieces of audio as we work on each route.
*/
-
+
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-
+
/* Connect tracks to monitor section. Note that in an
existing session, the internal sends will already exist, but we want the
routes to notice that they connect to the control out specifically.
*/
-
-
+
+
boost::shared_ptr<RouteList> r = routes.reader ();
PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
-
+
for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
-
+
if ((*x)->is_monitor()) {
/* relax */
} else if ((*x)->is_master()) {
rl.push_back (r);
add_routes (rl, false, false, false);
-
+
assert (_monitor_out);
/* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
are undefined, at best.
*/
-
+
uint32_t limit = _monitor_out->n_inputs().n_audio();
-
+
if (_master_out) {
-
+
/* connect the inputs to the master bus outputs. this
* represents a separate data feed from the internal sends from
* each route. as of jan 2011, it allows the monitor section to
for (uint32_t n = 0; n < limit; ++n) {
boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
-
+
if (o) {
string connect_to = o->name();
if (_monitor_out->input()->connect (p, connect_to, this)) {
}
}
}
-
+
/* if monitor section is not connected, connect it to physical outs
*/
-
+
if (Config->get_auto_connect_standard_busses() && !_monitor_out->output()->connected ()) {
-
+
if (!Config->get_monitor_bus_preferred_bundle().empty()) {
-
+
boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
-
+
if (b) {
_monitor_out->output()->connect_ports_to_bundle (b, true, this);
} else {
Config->get_monitor_bus_preferred_bundle())
<< endmsg;
}
-
+
} else {
-
+
/* Monitor bus is audio only */
vector<string> outputs[DataType::num_types];
uint32_t mod = outputs[DataType::AUDIO].size();
uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
-
+
if (mod != 0) {
-
+
for (uint32_t n = 0; n < limit; ++n) {
-
+
boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
string connect_to;
if (outputs[DataType::AUDIO].size() > (n % mod)) {
connect_to = outputs[DataType::AUDIO][n % mod];
}
-
+
if (!connect_to.empty()) {
if (_monitor_out->output()->connect (p, connect_to, this)) {
error << string_compose (
/* Hold process lock while doing this so that we don't hear bits and
* pieces of audio as we work on each route.
*/
-
+
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
/* Connect tracks to monitor section. Note that in an
PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
for (RouteList::iterator x = rls->begin(); x != rls->end(); ++x) {
-
+
if ((*x)->is_monitor()) {
/* relax */
} else if ((*x)->is_master()) {
}
}
-
+
last_loopend = location->end();
set_dirty ();
}
//if there is no existing session, we need to make a new session location (should never happen)
existing = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
}
-
+
if (end <= start) {
error << _("Session: you can't use that location for session start/end)") << endmsg;
return;
}
existing->set( start, end );
-
+
set_dirty();
}
if (_ignore_skips_updates) {
return;
}
-
+
Locations::LocationList skips;
if (consolidate) {
Locations::LocationList const & locs (_locations->list());
for (Locations::LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
-
+
Location* location = *i;
-
+
if (location->is_skip() && location->is_skipping()) {
SessionEvent* ev = new SessionEvent (SessionEvent::Skip, SessionEvent::Add, location->start(), location->end(), 1.0);
queue_event (ev);
We might be re-adding a location here but it doesn't actually matter
for all the locations that the Session takes an interest in.
*/
-
+
{
PBD::Unwinder<bool> protect_ignore_skip_updates (_ignore_skips_updates, true);
for (Locations::LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
location_added (*i);
}
}
-
+
update_skips (NULL, false);
}
if (rs == Recording) {
break;
}
-
+
if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
_last_record_location = _transport_frame;
clear_clicks ();
reset_write_sources (false);
-
+
// XXX we need some equivalent to this, somehow
// SndFileSource::setup_standard_crossfades (frames_per_second);
::process(). It is therefore fine to do things that block
here.
*/
-
+
{
current_block_size = nframes;
/* We are going to build a directed graph of our routes;
this is where the edges of that graph are put.
*/
-
+
GraphEdges edges;
/* Go through all routes doing two things:
* routes directly or indirectly feed them. This information
* is used by the solo code.
*/
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
/* Clear out the route's list of direct or indirect feeds */
/* Attempt a topological sort of the route graph */
boost::shared_ptr<RouteList> sorted_routes = topological_sort (r, edges);
-
+
if (sorted_routes) {
/* We got a satisfactory topological sort, so there is no feedback;
use this new graph.
if (_process_graph) {
_process_graph->rechain (sorted_routes, edges);
}
-
+
_current_route_graph = edges;
/* Complete the building of the routes' lists of what directly
so the solo code will think that everything is still connected
as it was before.
*/
-
+
FeedbackDetected (); /* EMIT SIGNAL */
}
routes, but hidden objects like the click track. So check port names
before anything else.
*/
-
+
for (vector<string>::const_iterator reserved = reserved_io_names.begin(); reserved != reserved_io_names.end(); ++reserved) {
if (base == *reserved) {
definitely_add_number = true;
break;
}
}
-
+
if (!definitely_add_number && route_by_name (base) == 0) {
/* juse use the base */
name = base;
}
++id;
-
+
} while (id < (UINT_MAX-1));
return false;
{
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
if (track->input()->ensure_io (input, false, this)) {
- error << "cannot configure " << input << " out configuration for new midi track" << endmsg;
+ error << "cannot configure " << input << " out configuration for new midi track" << endmsg;
goto failed;
}
PluginPtr plugin = instrument->load (*this);
boost::shared_ptr<Processor> p (new PluginInsert (*this, plugin));
(*r)->add_processor (p, PreFader);
-
+
}
}
}
}
mtc_in_ptr->disconnect_all ();
-
+
std::vector<EngineStateController::MidiPortState> midi_port_states;
EngineStateController::instance()->get_physical_midi_input_states (midi_port_states);
-
+
std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
-
+
for (; state_iter != midi_port_states.end(); ++state_iter) {
if (state_iter->available && state_iter->mtc_in) {
mtc_in_ptr->connect (state_iter->name);
}
}
-
+
if (!_midi_ports->mtc_input_port ()->connected () &&
config.get_external_sync () &&
(Config->get_sync_source () == MTC) ) {
config.set_external_sync (false);
}
-
+
if ( ARDOUR::Profile->get_trx () ) {
// Tracks need this signal to update timecode_source_dropdown
MtcOrLtcInputPortChanged (); //emit signal
const string name_pattern = default_track_name_pattern (DataType::AUDIO);
bool const use_number = (how_many != 1) || name_template.empty () || (name_template == name_pattern);
-
+
while (how_many) {
if (!find_route_name (name_template.empty() ? _(name_pattern.c_str()) : name_template, ++track_id, track_name, use_number)) {
RouteList ret;
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
-
+
while (how_many) {
if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, use_number)) {
error << "cannot find name for new audio bus" << endmsg;
bus->add_internal_return ();
ret.push_back (bus);
-
+
RouteAddedOrRemoved (true); /* EMIT SIGNAL */
ARDOUR::GUIIdle ();
} else {
string const route_name = node_copy.property(X_("name"))->value ();
-
+
/* generate a new name by adding a number to the end of the template name */
if (!find_route_name (route_name.c_str(), ++number, name, true)) {
fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
}
}
}
-
+
boost::shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
if (route == 0) {
update_latency (true);
update_latency (false);
-
+
set_dirty();
-
+
if (save) {
save_state (_current_snapshot_name);
}
-
+
reassign_track_numbers();
update_route_record_state ();
}
if (_monitor_out && IO::connecting_legal) {
- Glib::Threads::Mutex::Lock lm (_engine.process_lock());
-
+ Glib::Threads::Mutex::Lock lm (_engine.process_lock());
+
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
if ((*x)->is_monitor()) {
/* relax */
bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
if (delta == 1 && Config->get_exclusive_solo()) {
-
+
/* new solo: disable all other solos, but not the group if its solo-enabled */
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
in_signal_flow = false;
DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed from %1\n", (*i)->name()));
-
+
if ((*i)->feeds (route, &via_sends_only)) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
if (!via_sends_only) {
} else {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tno feed from %1\n", (*i)->name()));
}
-
+
DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed to %1\n", (*i)->name()));
if (route->feeds (*i, &via_sends_only)) {
return false;
}
}
-
+
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if ((*i)->name() == name) {
return false;
for (RouteList::iterator rt = rl->begin(); rt != rl->end(); ++rt) {
PortSet& ps ((*rt)->input()->ports());
-
+
for (PortSet::iterator p = ps.begin(); p != ps.end(); ++p) {
p->get_connections (connections);
}
-
+
for (vector<string>::iterator s = connections.begin(); s != connections.end(); ++s) {
routes_using_input_from (*s, rl2);
}
-
+
/* scan all relevant routes to see if others are on or off */
-
+
bool others_are_already_on = false;
-
+
for (RouteList::iterator r = rl2.begin(); r != rl2.end(); ++r) {
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*r);
mt->set_input_active (onoff);
}
}
-
+
if (flip_others) {
/* globally reverse other routes */
-
+
for (RouteList::iterator r = rl2.begin(); r != rl2.end(); ++r) {
if ((*r) != (*rt)) {
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*r);
/* yay, new source */
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
-
+
if (fs) {
if (!fs->within_session()) {
ensure_search_path_includes (Glib::path_get_dirname (fs->path()), fs->type());
}
}
-
+
set_dirty();
boost::shared_ptr<AudioFileSource> afs;
= boost::dynamic_pointer_cast<MidiSource>(s->second);
boost::shared_ptr<FileSource> fs
= boost::dynamic_pointer_cast<FileSource>(s->second);
-
+
if (ms && fs && fs->path() == path) {
return ms;
}
string session_path;
bool in_another_session = true;
-
+
if (filepath.find (interchange_dir_string) != string::npos) {
-
+
session_path = Glib::path_get_dirname (filepath); /* now ends in audiofiles */
session_path = Glib::path_get_dirname (session_path); /* now ends in session name */
session_path = Glib::path_get_dirname (session_path); /* now ends in interchange */
} else {
in_another_session = false;
}
-
+
if (in_another_session) {
SessionDirectory sd (session_path);
if (!in_session) {
path = Glib::path_get_dirname (filepath);
}
-
+
return peak_file_helper (_session_dir->peak_path(), path, Glib::path_get_basename (filepath), !old_peak_name);
}
SessionDirectory sdir (get_best_session_directory_for_new_audio());
string base = Glib::path_get_basename (path);
string newpath = Glib::build_filename (sdir.sound_path(), base);
-
+
if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
MD5 md5;
md5.digestString (path.c_str());
md5.writeToString ();
base = md5.digestChars;
-
+
string ext = get_suffix (path);
if (!ext.empty()) {
base += '.';
base += ext;
}
-
+
newpath = Glib::build_filename (sdir.sound_path(), base);
/* if this collides, we're screwed */
uint32_t existing = 0;
for (vector<string>::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) {
-
+
/* note that we search *without* the extension so that
we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
in the event that this new name is required for
*/
const string spath = *i;
-
+
if (matching_unsuffixed_filename_exists_in (spath, name)) {
existing++;
break;
}
-
+
/* it is possible that we have the path already
* assigned to a source that has not yet been written
* (ie. the write source for a diskstream). we have to
* two Sources point to the same file with different
* notions of their removability.
*/
-
-
+
+
string possible_path = Glib::build_filename (spath, name);
if (audio_source_by_path_and_channel (possible_path, 0)) {
{
ostringstream sstr;
const string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
-
+
if (Profile->get_trx() && destructive) {
sstr << 'T';
sstr << setfill ('0') << setw (4) << cnt;
sstr << legalized_base;
} else {
sstr << legalized_base;
-
+
if (take_required || related_exists) {
sstr << '-';
sstr << cnt;
}
}
-
+
if (nchan == 2) {
if (chan == 0) {
sstr << "%L";
sstr << chan+1;
}
}
-
+
sstr << ext;
return sstr.str();
for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
possible_name = format_audio_source_name (legalized, nchan, chan, destructive, take_required, cnt, some_related_source_name_exists);
-
+
if (audio_source_name_is_unique (possible_name)) {
break;
}
-
+
some_related_source_name_exists = true;
if (cnt > limit) {
vector<space_and_path>::iterator i;
uint32_t existing = 0;
-
+
for (vector<string>::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) {
snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt);
possible_name = buf;
possible_path = Glib::build_filename (*i, possible_name);
-
+
if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
existing++;
}
Session::create_midi_source_for_session (string const & basic_name)
{
const string path = new_midi_source_path (basic_name);
-
+
if (!path.empty()) {
return boost::dynamic_pointer_cast<SMFSource> (
SourceFactory::createWritable (
{
/* the caller passes in the track the source will be used in,
so that we can keep the numbering sane.
-
+
Rationale: a track with the name "Foo" that has had N
captures carried out so far will ALREADY have a write source
named "Foo-N+1.mid" waiting to be used for the next capture.
-
+
If we call new_midi_source_name() we will get "Foo-N+2". But
there is no region corresponding to "Foo-N+1", so when
"Foo-N+2" appears in the track, the gap presents the user
with odd behaviour - why did it skip past Foo-N+1?
-
+
We could explain this to the user in some odd way, but
instead we rename "Foo-N+1.mid" as "Foo-N+2.mid", and then
use "Foo-N+1" here.
-
+
If that attempted rename fails, we get "Foo-N+2.mid" anyway.
*/
-
+
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (track);
assert (mt);
std::string name = track->steal_write_source_name ();
if (_total_free_4k_blocks_uncertain) {
return boost::optional<framecnt_t> ();
}
-
+
float sample_bytes_on_disk = 4.0; // keep gcc happy
switch (config.get_native_file_data_format()) {
string path = ((track.data_type() == DataType::AUDIO)
? new_audio_source_path (legal_playlist_name, diskstream_channels.n_audio(), chan_n, false, true)
: new_midi_source_path (legal_playlist_name));
-
+
if (path.empty()) {
goto out;
}
if (record_status() == Recording && record_arm_state_changed ) {
RecordArmStateChanged ();
}
-
+
}
void
(some_track_latency_changed ? "yes" : "no")));
DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n");
-
+
if (some_track_latency_changed || force_whole_graph) {
_engine.update_latencies ();
}
*/
reconnect_existing_routes(true, true);
#endif
-
+
}
void
_object_selection = Evoral::Range<framepos_t> (-1,-1);
#ifdef USE_TRACKS_CODE_FEATURES
follow_playhead_priority ();
-#endif
+#endif
}
}
copy = min (clk->duration - clk->offset, nframes - internal_offset);
-
+
memcpy (buf + internal_offset, &clk->data[clk->offset], copy * sizeof (Sample));
-
+
clk->offset += copy;
if (clk->offset >= clk->duration) {
SessionEvent* ev = static_cast<SessionEvent*> (p->alloc ());
DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("%1 Allocating SessionEvent from %2 ev @ %3 pool size %4 free %5 used %6\n", pthread_name(), p->name(), ev,
p->total(), p->available(), p->used()));
-
+
ev->own_pool = p;
return ev;
}
_exporting = true;
export_status->running = true;
export_status->Finished.connect_same_thread (*this, boost::bind (&Session::finalize_audio_export, this));
-
+
/* disable MMC output early */
_pre_export_mmc_enabled = _mmc->send_enabled ();
up otherwise it could be doing do_refill in its thread while we are doing
it here.
*/
-
+
_butler->wait_until_finished ();
/* get everyone to the right position */
post_transport ();
return 0;
}
-
+
_engine.main_thread()->get_buffers ();
process_export (nframes);
_engine.main_thread()->drop_buffers ();
_engine.freewheel (false);
export_freewheel_connection.disconnect();
-
+
_mmc->enable_send (_pre_export_mmc_enabled);
/* maybe write CUE/TOC */
//map.insert (Property ("album_artist_sort", ""));
//map.insert (Property ("artist_sort", ""));
//map.insert (Property ("title_sort", ""));
-
+
/*** Globals ***/
user_map.insert (Property ("user_name", ""));
user_map.insert (Property ("user_email", ""));
treat RecordStrobe like RecordPause. This violates the MMC
specification.
*/
-
+
if (Config->get_mmc_control()) {
maybe_enable_record();
}
msg[8] = timecode.frames;
// Send message at offset 0, sent time is for the start of this cycle
-
+
MidiBuffer& mb (_midi_ports->mtc_output_port()->get_midi_buffer (nframes));
mb.push_back (Port::port_offset(), sizeof (msg), msg);
} else {
_mmc->send (c, 0);
}
-
+
}
bool
{
vector<boost::shared_ptr<Playlist> > pl;
get (pl);
-
+
vector<boost::shared_ptr<Playlist> > pl_tr;
for (vector<boost::shared_ptr<Playlist> >::iterator i = pl.begin(); i != pl.end(); ++i) {
Session::no_roll (pframes_t nframes)
{
PT_TIMING_CHECK (4);
-
+
framepos_t end_frame = _transport_frame + nframes; // FIXME: varispeed + no_roll ??
int ret = 0;
int declick = (config.get_use_transport_fades() ? get_transport_declick_required() : false);
const framepos_t start_frame = _transport_frame;
const framepos_t end_frame = _transport_frame + floor (nframes * _transport_speed);
-
+
if (_process_graph) {
DEBUG_TRACE(DEBUG::ProcessThreads,"calling graph/process-routes\n");
if (_process_graph->process_routes (nframes, start_frame, end_frame, declick, need_butler) < 0) {
Session::process_with_events (pframes_t nframes)
{
PT_TIMING_CHECK (3);
-
+
SessionEvent* ev;
pframes_t this_nframes;
framepos_t end_frame;
return max_framepos;
}
-
+
bool const punching_in = (config.get_punch_in () && _locations->auto_punch_location());
bool const punching_out = (config.get_punch_out () && _locations->auto_punch_location());
if ((*i)->is_auditioner ()) { // REQUIRES REVIEW Can audiotioner be in Record Safe mode?
continue;
}
-
+
boost::shared_ptr<Track> t;
-
+
if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
t->set_record_safe (yn, (group_override ? (void*) t->route_group () : (void *) this));
}
}
-
+
set_dirty ();
}
for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
(*i)->realtime_handle_transport_stopped ();
}
-
+
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
/* the duration change is not guaranteed to have happened, but is likely */
-
+
todo = PostTransportWork (todo | PostTransportDuration);
if (abort) {
if (clear_state && !Config->get_loop_is_mode()) {
unset_play_loop ();
}
-
+
reset_slave_state ();
_transport_speed = 0;
PostTransportWork ptw;
boost::shared_ptr<RouteList> r = routes.reader ();
uint64_t before;
-
+
int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
finished = true;
ptw = post_transport_work();
if (get_play_loop() && !Config->get_seamless_loop()) {
DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
-
+
/* this locate might be happening while we are
* loop recording.
*
} else if (loc) {
set_track_loop (false);
}
-
+
} else {
/* no more looping .. should have been noticed elsewhere */
}
-
+
boost::shared_ptr<RouteList> rl = routes.reader();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
(*i)->non_realtime_locate (_transport_frame);
// Next stop will put us where we need to be.
return false;
}
-
+
/* Note that the order of checking each AutoReturnTarget flag defines
the priority each flag.
Region Selection
Last Locate
*/
-
+
if (autoreturn & RangeSelectionStart) {
if (!_range_selection.empty()) {
jump_to = _range_selection.from;
}
}
}
-
+
if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
/* don't try to handle loop play when synced to JACK */
-
+
if (!synced_to_engine()) {
Location *location = _locations->auto_loop_location();
-
+
if (location) {
jump_to = location->start();
}
}
}
-
+
if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
if (!_object_selection.empty()) {
jump_to = _object_selection.from;
if (jump_to < 0 && (autoreturn & LastLocate)) {
jump_to = _last_roll_location;
}
-
+
return jump_to >= 0;
}
#else
if (_engine.connected() && !_engine.freewheeling()) {
// need to queue this in the next RT cycle
_send_timecode_update = true;
-
+
if (!dynamic_cast<MTC_Slave*>(_slave)) {
send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
/* This (::non_realtime_stop()) gets called by main
process thread, which will lead to confusion
when calling AsyncMIDIPort::write().
-
+
Something must be done. XXX
*/
send_mmc_locate (_transport_frame);
clear_events (SessionEvent::AutoLoop);
clear_events (SessionEvent::AutoLoopDeclick);
set_track_loop (false);
-
-
+
+
if (Config->get_seamless_loop()) {
/* likely need to flush track buffers: this will locate us to wherever we are */
add_post_transport_work (PostTransportLocate);
play_loop = true;
have_looped = false;
-
+
if (loc) {
unset_play_range ();
Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
{
bool need_butler = false;
-
+
/* Locates for seamless looping are fairly different from other
* locates. They assume that the diskstream buffers for each track
* already have the correct data in them, and thus there is no need to
DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
-
+
if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
/* already at the desired position. Not forced to locate,
*/
bool transport_was_stopped = !transport_rolling();
-
+
if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
(!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
add_post_transport_work (todo);
need_butler = true;
-
+
} else {
/* this is functionally what clear_clicks() does but with a tentative lock */
// located outside the loop: cancel looping directly, this is called from event handling context
have_looped = false;
-
+
if (!Config->get_loop_is_mode()) {
set_play_loop (false, _transport_speed);
} else {
}
boost::shared_ptr<RouteList> rl = routes.reader();
-
+
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-
+
if (tr && tr->record_enabled ()) {
// tell it we've looped, so it can deal with the record state
tr->transport_looped (_transport_frame);
if (Config->get_monitoring_model() == HardwareMonitoring) {
set_track_monitor_input_status (true);
}
-
+
if (synced_to_engine ()) {
if (clear_state) {
/* do this here because our response to the slave won't
if (Config->get_loop_is_mode() && play_loop) {
Location *location = _locations->auto_loop_location();
-
+
if (location != 0) {
if (_transport_frame != location->start()) {
}
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
-
+
if (!get_transport_declick_required()) {
/* stop has not yet been scheduled */
}
SubState new_bits;
-
+
if (actively_recording() && /* we are recording */
worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
-
+
/* we need to capture the audio that is still somewhere in the pipeline between
wherever it was generated and the process callback. This means that even though
the user (or something else) has asked us to stop, we have to roll
we still need playback to "stop" now, however, which is why we schedule
a declick below.
*/
-
+
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
_transport_frame, _worst_input_latency,
_transport_frame + _worst_input_latency,
abort));
-
+
SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
_transport_frame + _worst_input_latency,
0, 0, abort);
-
+
merge_event (ev);
/* request a declick at the start of the next process cycle() so that playback ceases.
does not stop the transport too early.
*/
new_bits = SubState (PendingDeclickOut|StopPendingCapture);
-
+
} else {
-
+
/* Not recording, schedule a declick in the next process() cycle and then stop at its end */
-
+
new_bits = PendingDeclickOut;
DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
}
-
+
/* we'll be called again after the declick */
transport_sub_state = SubState (transport_sub_state|new_bits);
pending_abort = abort;
} else {
DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
-
+
/* declick was scheduled, but we've been called again, which means it is really time to stop
-
+
XXX: we should probably split this off into its own method and call it explicitly.
*/
}
DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
-
+
// need to queue this for next process() cycle
_send_timecode_update = true;
break;
}
time -= position;
-
+
ev.set(buf, size, time);
ev.set_event_type(midi_parameter_type(ev.buffer()[0]));
ev.set_id(Evoral::next_event_id());
static bool compile = true;
const int nmatches = 2;
regmatch_t matches[nmatches];
-
+
if (Glib::file_test (file, Glib::FILE_TEST_EXISTS)) {
if (!Glib::file_test (file, Glib::FILE_TEST_IS_REGULAR)) {
/* exists but is not a regular file */
} else {
compile = false;
}
-
+
if (regexec (&compiled_pattern, file.c_str(), nmatches, matches, 0)) {
return false;
}
_flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
}
-
-
+
+
fmt = SF_FORMAT_RF64;
_flags = Flag (_flags & ~Broadcast);
break;
-
+
default:
fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
abort(); /*NOTREACHED*/
}
}
#endif
-
+
if (!_broadcast_info) {
_broadcast_info = new BroadcastInfo;
}
/* Set the broadcast flag if the BWF info is already there. We need
* this when recovering or using existing files.
*/
-
+
if (bwf_info_exists) {
_flags = Flag (_flags | Broadcast);
}
}
}
}
-
+
return 0;
}
SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const
{
assert (cnt >= 0);
-
+
framecnt_t nread;
float *ptr;
framecnt_t real_cnt;
curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
// Allow redirection
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
-
+
// Allow connections to time out (without using signals)
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 30);
error << string_compose (_("%1: this session uses destructive tracks, which are not supported"), PROGRAM_NAME) << endmsg;
return -1;
}
-
+
if (version < 3000) {
/* a source with an XML node must necessarily already exist,
and therefore cannot be removable/writable etc. etc.; 2.X
try {
boost::shared_ptr<AudioPlaylistSource> ap (new AudioPlaylistSource (s, node));
-
+
if (setup_peakfile (ap, true)) {
return boost::shared_ptr<Source>();
}
int chn, Source::Flag flags, bool announce, bool defer_peaks)
{
if (type == DataType::AUDIO) {
-
+
if (!(flags & Destructive)) {
try {
// Work input until "buf" reaches 16 byte alignment
while ( ((intptr_t)buf) % 32 != 0 && nframes > 0) {
-
+
// Load the next float into the work buffer
work = _mm256_set1_ps(*buf);
if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
return false;
}
-
+
return true;
}
if (str.find (template_suffix) == str.length() - strlen (template_suffix)) {
return true;
}
-
+
return false;
}
}
new_start.bars = start().bars;
-
+
double ticks = BBT_Time::ticks_per_beat * meter.divisions_per_bar() * _bar_offset;
new_start.beats = (uint32_t) floor (ticks/BBT_Time::ticks_per_beat);
new_start.ticks = 0; /* (uint32_t) fmod (ticks, BBT_Time::ticks_per_beat); */
/* remember the 1-based counting properties of beats */
new_start.beats += 1;
-
+
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("from bar offset %1 and dpb %2, ticks = %3->%4 beats = %5\n",
_bar_offset, meter.divisions_per_bar(), ticks, new_start.ticks, new_start.beats));
}
return false;
-}
-
+}
+
void
TempoMap::remove_meter (const MeterSection& tempo, bool complete_operation)
{
TempoMap::remove_meter_locked (const MeterSection& tempo)
{
Metrics::iterator i;
-
+
for (i = metrics.begin(); i != metrics.end(); ++i) {
if (dynamic_cast<MeterSection*> (*i) != 0) {
if (tempo.frame() == (*i)->frame()) {
/* we need to (potentially) update the BBT times of tempo
sections based on this new meter.
*/
-
+
if ((section->start().beats != 1) || (section->start().ticks != 0)) {
-
+
BBT_Time corrected = section->start();
corrected.beats = 1;
corrected.ticks = 0;
-
+
warning << string_compose (_("Meter changes can only be positioned on the first beat of a bar. Moving from %1 to %2"),
section->start(), corrected) << endmsg;
-
+
section->set_start (corrected);
}
}
-
+
/* Look for any existing MetricSection that is of the same type and
in the same bar as the new one, and remove it before adding
(*i)->start().beats == section->start().beats) {
if (!(*i)->movable()) {
-
+
/* can't (re)move this section, so overwrite
* its data content (but not its properties as
* a section).
*/
-
+
*(dynamic_cast<Tempo*>(*i)) = *(dynamic_cast<Tempo*>(section));
need_add = false;
} else {
if ((*i)->start().bars == section->start().bars) {
if (!(*i)->movable()) {
-
+
/* can't (re)move this section, so overwrite
* its data content (but not its properties as
* a section
*/
-
+
*(dynamic_cast<Meter*>(*i)) = *(dynamic_cast<Meter*>(section));
need_add = false;
} else {
metrics.erase (i);
-
+
}
break;
break;
}
}
-
+
metrics.insert (i, section);
}
}
{
Glib::Threads::RWLock::WriterLock lm (lock);
TempoSection& first (first_tempo());
-
+
if (ts.start() != first.start()) {
remove_tempo_locked (ts);
add_tempo_locked (tempo, where, true);
{
/* new tempos always start on a beat */
where.ticks = 0;
-
+
TempoSection* ts = new TempoSection (where, tempo.beats_per_minute(), tempo.note_type());
-
+
/* find the meter to use to set the bar offset of this
* tempo section.
*/
-
+
const Meter* meter = &first_meter();
-
+
/* as we start, we are *guaranteed* to have m.meter and m.tempo pointing
at something, because we insert the default tempo and meter during
TempoMap construction.
-
+
now see if we can find better candidates.
*/
-
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
-
+
const MeterSection* m;
-
+
if (where < (*i)->start()) {
break;
}
-
+
if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
meter = m;
}
}
-
+
ts->update_bar_offset_from_bbt (*meter);
-
+
/* and insert it */
-
+
do_insert (ts);
if (recompute) {
recompute_map (false);
}
-}
+}
void
TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_Time& where)
{
Glib::Threads::RWLock::WriterLock lm (lock);
MeterSection& first (first_meter());
-
+
if (ms.start() != first.start()) {
remove_meter_locked (ms);
add_meter_locked (meter, where, true);
add_meter_locked (meter, where, true);
}
-
+
#ifndef NDEBUG
if (DEBUG_ENABLED(DEBUG::TempoMap)) {
dump (std::cerr);
round the start time appropriately. remember that
`where' is based on the existing tempo map, not
the result after we insert the new meter.
-
+
*/
-
+
if (where.beats != 1) {
where.beats = 1;
where.bars++;
}
-
+
/* new meters *always* start on a beat. */
where.ticks = 0;
-
+
do_insert (new MeterSection (where, meter.divisions_per_bar(), meter.note_divisor()));
if (recompute) {
recompute_map (true);
}
-
+
}
void
const TempoSection *t = 0;
/* CALLER MUST HOLD LOCK */
-
+
for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
if ((t = dynamic_cast<const TempoSection *> (*i)) != 0) {
return *t;
*/
int additional_minutes = 1;
-
+
while (1) {
if (!_map.empty() && _map.back().bar >= (bbt.bars + 1)) {
break;
TempoSection* ts;
MeterSection* ms;
-
+
if ((ts = dynamic_cast<TempoSection*>(*i)) != 0) {
/* reassign the BBT time of this tempo section
return;
}
- BBTPointList::const_iterator i = _map.end();
+ BBTPointList::const_iterator i = _map.end();
Metrics::iterator next_metric;
--i;
*/
if (tempo->start().ticks != 0) {
-
- double next_beat_frames = tempo->frames_per_beat (_frame_rate);
-
+
+ double next_beat_frames = tempo->frames_per_beat (_frame_rate);
+
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("bumped into non-beat-aligned tempo metric at %1 = %2, adjust next beat using %3\n",
tempo->start(), current_frame, tempo->bar_offset()));
-
+
/* back up to previous beat */
current_frame_exact -= beat_frames;
current_frame = llrint(current_frame_exact);
*/
tempo->set_frame (bar_start_frame +
llrint ((ts->bar_offset() * meter->divisions_per_bar() * beat_frames)));
-
+
/* advance to the location of
* the new (adjusted) beat. do
* this by figuring out the
* merit a reloop ...
*/
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Adjusted last beat to %1\n", current_frame));
-
+
} else {
-
+
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("bumped into beat-aligned tempo metric at %1 = %2\n",
tempo->start(), current_frame));
tempo->set_frame (current_frame);
}
} else if ((ms = dynamic_cast<MeterSection*>(*next_metric)) != 0) {
-
+
meter = ms;
/* new meter section: always defines the
* start of a bar.
*/
-
+
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("bumped into meter section at %1 vs %2 (%3)\n",
meter->start(), current, current_frame));
-
+
assert (current.beats == 1);
meter->set_frame (current_frame);
}
-
+
beat_frames = meter->frames_per_grid (*tempo, _frame_rate);
-
+
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("New metric with beat frames = %1 dpb %2 meter %3 tempo %4\n",
beat_frames, meter->divisions_per_bar(), *((Meter*)meter), *((Tempo*)tempo)));
-
+
++next_metric;
if (next_metric != metrics.end() && ((*next_metric)->start() == current)) {
*last = i;
}
}
-
+
return m;
}
if (!lm.locked()) {
throw std::logic_error ("TempoMap::bbt_time_rt() could not lock tempo map");
}
-
+
if (_map.empty() || _map.back().frame < frame) {
throw std::logic_error (string_compose ("map not long enough to reach %1", frame));
}
warning << string_compose (_("tempo map asked for frame time at bar < 1 (%1)\n"), bbt) << endmsg;
return 0;
}
-
+
if (bbt.beats < 1) {
throw std::logic_error ("beats are counted from one");
}
{
BBT_Time when;
bbt_time (pos, when);
-
+
Glib::Threads::RWLock::ReaderLock lm (lock);
return bbt_duration_at_unlocked (when, bbt, dir);
}
double rem;
/* compute the distance to the previous and next subdivision */
-
+
if ((rem = fmod ((double) the_beat.ticks, (double) ticks_one_subdivisions_worth)) > ticks_one_subdivisions_worth/2.0) {
-
+
/* closer to the next subdivision, so shift forward */
the_beat.ticks = lrint (the_beat.ticks + (ticks_one_subdivisions_worth - rem));
}
} else if (rem > 0) {
-
+
/* closer to previous subdivision, so shift backward */
if (rem > the_beat.ticks) {
DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("round from %1 (%3|%4 @ %5) to %6 in direction %2\n", frame, dir, (*fi).bar, (*fi).beat, (*fi).frame,
(type == Bar ? "bar" : "beat")));
-
+
switch (type) {
case Bar:
if (dir < 0) {
return (*fi).frame;
} else {
-
+
/* true rounding: find nearest bar */
BBTPointList::const_iterator prev = fi;
} else {
return (*next).frame;
}
-
+
}
break;
the beat before frame.
*/
++next;
-
+
if ((next == _map.end()) || (frame - (*prev).frame) < ((*next).frame - frame)) {
return (*prev).frame;
} else {
metrics.clear();
nlist = node.children();
-
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
XMLNode* child = *niter;
const TempoSection* tempo;
MeterSection *m;
TempoSection *t;
-
+
meter = &first_meter ();
tempo = &first_tempo ();
-
+
BBT_Time start;
BBT_Time end;
-
+
// cerr << "\n###################### TIMESTAMP via AUDIO ##############\n" << endl;
-
+
bool first = true;
MetricSection* prev = 0;
-
+
for (i = metrics.begin(); i != metrics.end(); ++i) {
-
+
BBT_Time bbt;
TempoMetric metric (*meter, *tempo);
-
+
if (prev) {
metric.set_start (prev->start());
metric.set_frame (prev->frame());
// metric will be at frames=0 bbt=1|1|0 by default
// which is correct for our purpose
}
-
+
BBTPointList::const_iterator bi = bbt_before_or_at ((*i)->frame());
bbt_time ((*i)->frame(), bbt, bi);
-
+
// cerr << "timestamp @ " << (*i)->frame() << " with " << bbt.bars << "|" << bbt.beats << "|" << bbt.ticks << " => ";
-
+
if (first) {
first = false;
} else {
-
+
if (bbt.ticks > BBT_Time::ticks_per_beat/2) {
/* round up to next beat */
bbt.beats += 1;
}
-
+
bbt.ticks = 0;
-
+
if (bbt.beats != 1) {
/* round up to next bar */
bbt.bars += 1;
bbt.beats = 1;
}
}
-
+
// cerr << bbt << endl;
-
+
(*i)->set_start (bbt);
-
+
if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
tempo = t;
// cerr << "NEW TEMPO, frame = " << (*i)->frame() << " start = " << (*i)->start() <<endl;
fatal << _("programming error: unhandled MetricSection type") << endmsg;
abort(); /*NOTREACHED*/
}
-
+
prev = (*i);
}
-
+
recompute_map (true);
}
bool moved = false;
std::list<MetricSection*> metric_kill_list;
-
+
TempoSection* last_tempo = NULL;
MeterSection* last_meter = NULL;
bool tempo_after = false; // is there a tempo marker at the first sample after the removed range?
if (moved) {
recompute_map (true);
}
- }
+ }
PropertyChanged (PropertyChange ());
return moved;
}
if (pos < 0 && f == 0) {
f = pos;
}
-
+
if (f > pos) {
break;
}
-
+
tempo = t;
}
}
while (next_tempo != metrics.end ()) {
++next_tempo;
-
+
if (next_tempo != metrics.end() && dynamic_cast<const TempoSection*>(*next_tempo)) {
break;
}
keep going to get the previous tempo (or
metrics.rend())
*/
-
+
if (f <= pos) {
if (tempo == 0) {
/* first tempo with position at or
*/
while (!!beats) {
-
+
/* Distance to the start of this section in frames */
framecnt_t distance_frames = (pos - tempo->frame());
* traversed before we change the
* frames_per_beat value.
*/
-
+
pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
bars = 0;
DEBUG_TRACE (DEBUG::TempoMath,
string_compose ("frame %1 walk by %2 frames, start with tempo = %3 @ %4\n",
pos, distance, *((const Tempo*)tempo), tempo->frame()));
-
+
Evoral::Beats beats = Evoral::Beats();
while (distance) {
while (next_tempo != metrics.end ()) {
++next_tempo;
-
+
if (next_tempo != metrics.end() && dynamic_cast<const TempoSection*>(*next_tempo)) {
break;
}
AudioRegionReadTest::readTest ()
{
int const N = 1024;
-
+
Sample buf[N];
Sample mbuf[N];
float gbuf[N];
for (int i = 64; i < P; ++i) {
CPPUNIT_ASSERT_EQUAL (i, int (buf[i]));
}
-
+
/* Offset read: 256 frames from 128 frames into the region, with fades
(though the fade should not affect it, as it is finished before the read starts)
*/
for (int i = 0; i < N; ++i) {
buf[i] = 0;
}
-
+
_ar[0]->read_at (buf, mbuf, gbuf, P + 128, 256, 0);
check_staircase (buf, 128, 256);
}
assert (s);
int const signal_length = 4096;
-
+
Sample staircase[signal_length];
for (int i = 0; i < signal_length; ++i) {
staircase[i] = i;
}
s->write (staircase, signal_length);
-
+
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, 100);
TestNeedingSession::tearDown ();
}
-
+
/* No change since we just cleared them */
CPPUNIT_ASSERT_EQUAL (false, property.changed());
-
+
property->add (1, 2, false, false);
property->add (3, 4, false, false);
Meter meter(4.0, 4.0);
map.add_meter (meter, BBT_Time(1, 1, 0));
-
+
/* add some good stuff here */
}
_ar[1]->fade_in()->curve().get_vector (0, 128, fade_in, 128);
_ar[1]->inverse_fade_in()->curve().get_vector (0, 128, fade_out, 128);
-
+
/* Crossfading _r[0] to _r[1] using _r[1]'s fade in and inverse fade in.
_r[0] also has a standard region fade out to add to the fun.
*/
for (int i = 128; i < 256; ++i) {
-
+
float region_fade_out = 1;
if (i >= 192) {
/* Ardour fades out from 1 to VERY_SMALL_SIGNAL, which is 0.0000001,
*/
float r0 = i * region_fade_out;
r0 *= fade_out[i - 128];
-
+
float const r1 = (i - 128) * fade_in[i - 128];
CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
}
_ar[0]->set_default_fade_in ();
_ar[0]->set_default_fade_out ();
_ar[1]->set_default_fade_out ();
-
+
_playlist->add_region (_r[0], 0);
_r[0]->set_length (256);
_ar[0]->inverse_fade_out()->curve().get_vector (0, 128, fade_in, 128);
_ar[0]->fade_out()->curve().get_vector (0, 128, fade_out, 128);
-
+
/* Crossfading _r[0] to _r[1] using _r[0]'s fade out and inverse fade out.
_r[1] also has a standard region fade in to add to the fun.
*/
float r0 = i * fade_out[i - 128];
float r1 = (i - 128) * region_fade_in;
r1 *= fade_in[i - 128];
-
+
CPPUNIT_ASSERT_DOUBLES_EQUAL (r0 + r1, buf[i], 1e-16);
}
_ar[0]->set_default_fade_in ();
_ar[0]->set_default_fade_out ();
_ar[1]->set_default_fade_out ();
-
+
_playlist->add_region (_r[0], 0);
_r[0]->set_length (256);
ControlSurfacesTest::instantiateAndTeardownTest ()
{
_session->new_audio_track (1, 2, Normal, 0, 1, "Test");
-
+
ControlProtocolManager& m = ControlProtocolManager::instance ();
for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
m.activate (**i);
int const bpm = 120;
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
-
+
TempoMap map (sampling_rate);
Tempo tempo (bpm);
Meter meter (4, 4);
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
int const bpm = 120;
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
-
+
TempoMap map (sampling_rate);
Tempo tempo (bpm);
Meter meter (4, 4);
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
int const bpm = 120;
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
-
+
TempoMap map (sampling_rate);
Tempo tempo (bpm);
Meter meter (4, 4);
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
/*
120bpm at bar 1, 240bpm at bar 2, 160bpm at bar 3
-
+
120bpm = 24e3 samples per beat
160bpm = 18e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm 160bpm
0 beats 4 beats 8 beats
0 frames 96e3 frames 144e3 frames
std::string command_line;
CPPUNIT_ASSERT (get_default_jack_command_line (command_line));
-
+
CPPUNIT_ASSERT (write_jack_config_file (config_path, command_line));
}
ARDOUR::init (false, true, localedir);
Session* s = 0;
-
+
try {
s = load_session (argv[1], argv[2]);
} catch (failed_constructor& e) {
public:
MIDIClock_SlaveTest () : MIDIClock_Slave (new TestSlaveSessionProxy) {}
-
+
void setUp() {
}
mtdm->process (256, in, out);
memcpy (in, out, 256 * sizeof (float));
}
-
+
for (int i = 0; i < 64; ++i) {
mtdm->process (256, in, out);
memcpy (in, out, 256 * sizeof (float));
PlaylistEquivalentRegionsTest::setUp ()
{
AudioRegionTest::setUp ();
-
+
_playlist_b = PlaylistFactory::create (DataType::AUDIO, *_session, "testB");
}
CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
_ar[0]->set_length (1024);
_audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
-
+
for (int i = 0; i < 64; ++i) {
/* Note: this specific float casting is necessary so that the rounding
is done here the same as it is done in AudioPlaylist.
*/
CPPUNIT_ASSERT_DOUBLES_EQUAL (float (i * float (i / 63.0)), _buf[i], 1e-16);
}
-
+
for (int i = 64; i < 256; ++i) {
CPPUNIT_ASSERT_EQUAL (i, int (_buf[i]));
}
CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_in_is_xfade());
CPPUNIT_ASSERT_EQUAL (false, _ar[0]->fade_out_is_xfade());
#endif
-
+
_audio_playlist->add_region (_ar[1], 128);
_ar[1]->set_default_fade_in ();
_ar[1]->set_default_fade_out ();
CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_in_is_xfade());
CPPUNIT_ASSERT_EQUAL (false, _ar[1]->fade_out_is_xfade());
#endif
-
+
CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_in->back()->when);
CPPUNIT_ASSERT_EQUAL (double (64), _ar[1]->_fade_out->back()->when);
-
+
_ar[1]->set_length (1024);
_audio_playlist->read (_buf, _mbuf, _gbuf, 0, 256, 0);
CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_in->back()->when);
CPPUNIT_ASSERT_EQUAL (double (64), _ar[0]->_fade_out->back()->when);
_ar[0]->set_length (1024);
-
+
_audio_playlist->add_region (_ar[1], 0);
_ar[1]->set_default_fade_in ();
_ar[1]->set_default_fade_out ();
_ar[0]->set_fade_in_length (0);
_ar[0]->set_fade_out_length (0);
_ar[0]->set_length (256);
-
+
_audio_playlist->add_region (_ar[1], 0);
/* These calls will result in a 64-sample fade */
_ar[1]->set_fade_in_length (0);
for (int i = (256 + 64); i < (256 + 64 + 128); ++i) {
CPPUNIT_ASSERT_DOUBLES_EQUAL (i + i - (256 + 64) + 64, _buf[i], 1e-16);
}
-
+
/* Then _ar[1] + _ar[0] (faded out) for 64 samples */
for (int i = (256 + 64 + 128); i < 512; ++i) {
float const ar0_without_fade = i - 256;
public:
void setUp ();
void tearDown ();
-
+
void singleReadTest ();
void overlappingReadTest ();
void transparentReadTest ();
ARDOUR::Sample* _buf;
ARDOUR::Sample* _mbuf;
float* _gbuf;
-
+
void check_staircase (ARDOUR::Sample *, int, int);
};
ARDOUR::init (false, true, localedir);
Session* s = 0;
-
+
try {
s = load_session (argv[1], argv[2]);
} catch (failed_constructor& e) {
/*
120bpm at bar 1, 240bpm at bar 4
-
+
120bpm = 24e3 samples per beat
240bpm = 12e3 samples per beat
*/
-
+
/*
-
+
120bpm 240bpm
0 beats 12 beats
0 frames 288e3 frames
CPPUNIT_ASSERT_EQUAL (qc.size(), pc.size());
XMLNodeList::const_iterator k = pc.begin ();
XMLNodeList::const_iterator l = qc.begin ();
-
+
while (k != pc.end ()) {
check_nodes (*k, *l, ignore_properties);
++k;
TestUI* test_ui = new TestUI();
CppUnit::TestResult testresult;
-
+
CppUnit::TestResultCollector collectedresults;
testresult.addListener (&collectedresults);
-
+
CppUnit::BriefTestProgressListener progress;
testresult.addListener (&progress);
-
+
CppUnit::TestRunner testrunner;
testrunner.addTest (CppUnit::TestFactoryRegistry::getRegistry ().makeTest ());
testrunner.run (testresult);
-
+
CppUnit::CompilerOutputter compileroutputter (&collectedresults, std::cerr);
compileroutputter.write ();
delete test_ui;
ARDOUR::cleanup ();
-
+
return collectedresults.wasSuccessful () ? 0 : 1;
}
bool sync (Session* s) {
bool changed = false;
-
+
double sp = s->transport_speed();
framecnt_t fr = s->transport_frame();
-
+
if (speed != sp) {
speed = sp;
changed = true;
MidiClockTicker::set_session (Session* s)
{
SessionHandlePtr::set_session (s);
-
+
if (_session) {
_session->TransportStateChange.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_state_changed, this));
_session->TransportLooped.connect_same_thread (_session_connections, boost::bind (&MidiClockTicker::transport_looped, this));
send_position_event (llrint (_pos->midi_beats), 0, nframes);
} else if (_pos->speed == 1.0f) {
send_stop_event (0, nframes);
-
+
if (_pos->frame == 0) {
send_start_event (0, nframes);
} else {
if (_pos->speed == 1.0f) {
if (_session->get_play_loop()) {
assert(_session->locations()->auto_loop_location());
-
+
if (_pos->frame == _session->locations()->auto_loop_location()->start()) {
send_start_event (0, nframes);
} else {
send_continue_event (0, nframes);
}
-
+
} else if (_pos->frame == 0) {
send_start_event (0, nframes);
} else {
send_continue_event (0, nframes);
}
-
+
// send_midi_clock_event (0);
-
+
} else if (_pos->speed == 0.0f) {
send_stop_event (0, nframes);
send_position_event (llrint (_pos->midi_beats), 0, nframes);
root.add_property (X_("saved-meter-point"), enum_2_string (_saved_meter_point));
root.add_child_nocopy (_rec_enable_control->get_state());
root.add_child_nocopy (_diskstream->get_state ());
-
+
return root;
-}
+}
int
Track::set_state (const XMLNode& node, int version)
}
}
}
-
+
const XMLProperty* prop;
if ((prop = node.property (X_("monitoring"))) != 0) {
if (!t) {
return;
}
-
+
t->set_record_enabled (val >= 0.5 ? true : false, this);
}
if (!t) {
return 0;
}
-
+
return (t->record_enabled() ? 1.0 : 0.0);
}
if (yn && record_safe ()) {
return;
}
-
+
if (!_session.writable()) {
return;
}
}
bool will_follow;
-
+
if (yn) {
will_follow = _diskstream->prep_record_enable ();
} else {
if (_diskstream->record_safe ()) {
return;
}
-
+
if (!_session.writable()) {
return;
}
if (!_session.writable()) { /* REQUIRES REVIEW */
return;
}
-
+
if (_freeze_record.state == Frozen) { /* REQUIRES REVIEW */
return;
}
-
+
if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) {
_route_group->apply (&Track::set_record_safe, yn, _route_group);
return;
}
-
+
_diskstream->set_record_safe (yn);
}
be_silent = false;
break;
}
-
+
//if we have an internal generator, let it play regardless of monitoring state
if (_have_internal_generator) {
be_silent = false;
}
-
+
_amp->apply_gain_automation (false);
/* if have_internal_generator, or .. */
} else {
BufferSet& bufs = _session.get_route_buffers (n_process_buffers());
-
+
fill_buffers_with_input (bufs, _input, nframes);
if (_meter_point == MeterInput) {
Track::monitoring_state () const
{
/* Explicit requests */
-
+
if (_monitoring & MonitorInput) {
return MonitoringInput;
}
-
+
if (_monitoring & MonitorDisk) {
return MonitoringDisk;
}
/* This is an implementation of the truth table in doc/monitor_modes.pdf;
I don't think it's ever going to be too pretty too look at.
*/
-
+
// GZ: NOT USED IN TRACKS
//bool const auto_input = _session.config.get_auto_input ();
//bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
//bool const tape_machine_mode = Config->get_tape_machine_mode ();
-
+
bool const roll = _session.transport_rolling ();
bool const track_rec = _diskstream->record_enabled ();
bool session_rec = _session.actively_recording ();
-
+
if (track_rec) {
if (!session_rec && roll) {
Track::monitoring_state () const
{
/* Explicit requests */
-
+
if (_monitoring & MonitorInput) {
return MonitoringInput;
}
-
+
if (_monitoring & MonitorDisk) {
return MonitoringDisk;
}
} else {
return MonitoringDisk;
}
-
+
}
}
string::size_type pos;
string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=: ";
Glib::ustring legal;
-
+
/* this is the one place in Ardour where we need to iterate across
* potential multibyte characters, and thus we need Glib::ustring
*/
throw failed_constructor();
}
Session::vst_current_loading_id = 0;
-
+
_plugin = _state->plugin;
}
namespace AudioGrapher
{
-class SndfileHandle;
+class SndfileHandle;
class LIBAUDIOGRAPHER_API BroadcastInfo
{
#endif
return typeid(obj).name();
}
-
+
/// Returns name of ProcessContext::Flag
static std::string process_context_flag_name (FlagField::Flag flag);
};
{
flags.set (flag);
}
-
+
/// Prints debug output if \a context contains flags that are not supported by this class
template<typename SelfType, typename ContextType>
void check_flags (SelfType & self, ProcessContext<ContextType> context)
{
if (!Debuggable<L>::debug_level (DebugFlags)) { return; }
FlagField unsupported = flags.unsupported_flags_of (context.flags());
-
+
for (FlagField::iterator it = unsupported.begin(); it != unsupported.end(); ++it) {
Debuggable<L>::debug_stream() << boost::str (boost::format
("%1% does not support flag %2%")
, boost::equality_comparable<FlagField>
{
public:
-
+
typedef uint8_t Flag;
typedef uint32_t storage_type;
-
+
/// Bi-directional iterator for flag set. Iterates over flags that are set in this field.
class iterator
: public std::iterator<std::bidirectional_iterator_tag, Flag>
public:
iterator (FlagField const & parent, Flag position) : parent (parent), position (position) {}
iterator (iterator const & other) : parent (other.parent), position (other.position) {}
-
+
value_type operator*() const { return position; }
value_type const * operator->() const { return &position; }
-
+
iterator & operator++()
{
do {
return *this;
}
iterator operator++(int) { iterator copy (*this); ++(*this); return copy; }
-
+
iterator & operator--()
{
do {
return *this;
}
iterator operator--(int) { iterator copy (*this); --(*this); return copy; }
-
+
bool operator< (iterator const & other) const { return position < other.position; }
-
+
private:
FlagField const & parent;
Flag position;
};
-
+
public:
-
+
FlagField() : _flags (0) {}
FlagField(FlagField const & other) : _flags (other._flags) {}
-
+
inline bool has (Flag flag) const { return _flags & (1 << flag); }
inline storage_type flags () const { return _flags; }
inline operator bool() const { return _flags; }
/// Returns the flags in \a other that are not set in this field
inline FlagField unsupported_flags_of (FlagField const & other) const { return ~(_flags | ~other._flags); }
-
+
/// Set all flags that are set in \a other
inline FlagField & operator+= (FlagField const & other) { _flags |= other._flags; return *this; }
-
+
/** Checks whether this field has all the flags set that are set in \a other
* NOTE: Can NOT be used for strict weak ordering!
* \return \a true if \a other has flags set that this field does not
private:
FlagField(storage_type flags) : _flags (flags) {}
static Flag max() { return CHAR_BIT * sizeof (storage_type) + 1; }
-
+
storage_type _flags;
};
buffer = new T[chunk_size];
add_supported_flag (ProcessContext<T>::EndOfInput);
}
-
+
~Chunker()
{
delete [] buffer;
}
-
+
/** Outputs data in \a context in chunks with the size specified in the constructor.
* Note that some calls might not produce any output, while others may produce several.
* \n RT safe
void process (ProcessContext<T> const & context)
{
check_flags (*this, context);
-
+
framecnt_t frames_left = context.frames();
framecnt_t input_position = 0;
-
+
while (position + frames_left >= chunk_size) {
// Copy from context to buffer
framecnt_t const frames_to_copy = chunk_size - position;
TypeUtils<T>::copy (&context.data()[input_position], &buffer[position], frames_to_copy);
-
+
// Update counters
position = 0;
input_position += frames_to_copy;
if (frames_left) { c_out.remove_flag(ProcessContext<T>::EndOfInput); }
ListedSource<T>::output (c_out);
}
-
+
if (frames_left) {
// Copy the rest of the data
TypeUtils<T>::copy (&context.data()[input_position], &buffer[position], frames_left);
position += frames_left;
}
-
+
if (context.has_flag (ProcessContext<T>::EndOfInput) && position > 0) {
ProcessContext<T> c_out (context, buffer, position);
ListedSource<T>::output (c_out);
}
}
using Sink<T>::process;
-
+
private:
framecnt_t chunk_size;
framecnt_t position;
T * buffer;
-
+
};
} // namespace
{
private:
typedef boost::shared_ptr<IdentityVertex<T> > OutputPtr;
-
+
public:
/// Constructor. \n RT safe
DeInterleaver()
, max_frames (0)
, buffer (0)
{}
-
+
~DeInterleaver() { reset(); }
-
+
typedef boost::shared_ptr<Source<T> > SourcePtr;
-
+
/// Inits the deinterleaver. Must be called before using. \n Not RT safe
void init (unsigned int num_channels, framecnt_t max_frames_per_channel)
{
channels = num_channels;
max_frames = max_frames_per_channel;
buffer = new T[max_frames];
-
+
for (unsigned int i = 0; i < channels; ++i) {
outputs.push_back (OutputPtr (new IdentityVertex<T>));
}
}
-
+
/// Returns an output indexed by \a channel \n RT safe
SourcePtr output (unsigned int channel)
{
if (throw_level (ThrowObject) && channel >= channels) {
throw Exception (*this, "channel out of range");
}
-
+
return outputs[channel];
}
-
+
/// Deinterleaves data and outputs it to the outputs. \n RT safe
void process (ProcessContext<T> const & c)
{
framecnt_t frames = c.frames();
T const * data = c.data();
-
+
framecnt_t const frames_per_channel = frames / channels;
-
+
if (throw_level (ThrowProcess) && c.channels() != channels) {
throw Exception (*this, "wrong amount of channels given to process()");
}
-
+
if (throw_level (ThrowProcess) && frames_per_channel > max_frames) {
throw Exception (*this, "too many frames given to process()");
}
-
+
unsigned int channel = 0;
for (typename std::vector<OutputPtr>::iterator it = outputs.begin(); it != outputs.end(); ++it, ++channel) {
if (!*it) { continue; }
-
+
for (unsigned int i = 0; i < frames_per_channel; ++i) {
buffer[i] = data[channel + (channels * i)];
}
-
+
ProcessContext<T> c_out (c, buffer, frames_per_channel, 1);
(*it)->process (c_out);
}
}
-
+
using Sink<T>::process;
-
+
private:
void reset ()
channels = 0;
max_frames = 0;
}
-
+
std::vector<OutputPtr> outputs;
unsigned int channels;
framecnt_t max_frames;
, public Throwing<>
{
public:
-
+
/// Constructs an interleaver \n RT safe
Interleaver()
: channels (0)
, max_frames (0)
, buffer (0)
{}
-
+
~Interleaver() { reset(); }
-
+
/// Inits the interleaver. Must be called before using. \n Not RT safe
void init (unsigned int num_channels, framecnt_t max_frames_per_channel)
{
reset();
channels = num_channels;
max_frames = max_frames_per_channel;
-
+
buffer = new T[channels * max_frames];
-
+
for (unsigned int i = 0; i < channels; ++i) {
inputs.push_back (InputPtr (new Input (*this, i)));
}
}
-
+
/** Returns the input indexed by \a channel \n RT safe
* \n The \a process function of returned Sinks are also RT Safe
*/
if (throw_level (ThrowObject) && channel >= channels) {
throw Exception (*this, "Channel out of range");
}
-
+
return boost::static_pointer_cast<Sink<T> > (inputs[channel]);
}
-
+
private:
class Input : public Sink<T>
public:
Input (Interleaver & parent, unsigned int channel)
: frames_written (0), parent (parent), channel (channel) {}
-
+
void process (ProcessContext<T> const & c)
{
if (parent.throw_level (ThrowProcess) && c.channels() > 1) {
frames_written = c.frames();
parent.write_channel (c, channel);
}
-
+
using Sink<T>::process;
-
+
framecnt_t frames() { return frames_written; }
void reset() { frames_written = 0; }
-
+
private:
framecnt_t frames_written;
Interleaver & parent;
unsigned int channel;
};
-
+
void reset ()
{
inputs.clear();
channels = 0;
max_frames = 0;
}
-
+
void reset_channels ()
{
for (unsigned int i = 0; i < channels; ++i) {
}
}
-
+
void write_channel (ProcessContext<T> const & c, unsigned int channel)
{
if (throw_level (ThrowProcess) && c.frames() > max_frames) {
reset_channels();
throw Exception (*this, "Too many frames given to an input");
}
-
+
for (unsigned int i = 0; i < c.frames(); ++i) {
buffer[channel + (channels * i)] = c.data()[i];
}
-
+
framecnt_t const ready_frames = ready_to_output();
if (ready_frames) {
ProcessContext<T> c_out (c, buffer, ready_frames, channels);
typedef boost::shared_ptr<Input> InputPtr;
std::vector<InputPtr> inputs;
-
+
unsigned int channels;
framecnt_t max_frames;
T * buffer;
/// Process a const ProcessContext \see alloc_buffer() \n RT safe
void process (ProcessContext<float> const & c);
-
+
/// Process a non-const ProcsesContext in-place \n RT safe
void process (ProcessContext<float> & c);
bool enabled;
float target;
float gain;
-
+
float * buffer;
framecnt_t buffer_size;
};
public:
/// Constructor \n RT safe
PeakReader() : peak (0.0) {}
-
+
/// Returns the highest absolute of the values found so far. \n RT safe
float get_peak() { return peak; }
-
+
/// Resets the peak to 0 \n RT safe
void reset() { peak = 0.0; }
peak = Routines::compute_peak (c.data(), c.frames(), peak);
ListedSource<float>::output(c);
}
-
+
using Sink<float>::process;
-
+
private:
float peak;
};
D_Tri = GDitherTri, ///< Triangular dithering
D_Shaped = GDitherShaped ///< Actually noise shaping, only works for 46kHzish signals
};
-
+
/** Sample format converter that does dithering.
* This class can only convert floats to either \a float, \a int32_t, \a int16_t, or \a uint8_t
*/
*/
SampleFormatConverter (ChannelCount channels);
~SampleFormatConverter ();
-
+
/** Initialize and allocate buffers for processing.
* \param max_frames maximum number of frames that is allowed to be used in calls to \a process()
* \param type dither type from \a DitherType
/// Set whether or not clipping to [-1.0, 1.0] should occur when TOut = float. Clipping is off by default
void set_clip_floats (bool yn) { clip_floats = yn; }
-
+
/// Processes data without modifying it
void process (ProcessContext<float> const & c_in);
-
+
/// This version is only different in the case when \a TOut = float, and float clipping is on.
void process (ProcessContext<float> & c_in);
throw Exception (*this,
"Silence trimmer constructor and reset() must be called with a non-zero parameter!");
}
-
+
if (silence_buffer_size != silence_buffer_size_) {
silence_buffer_size = silence_buffer_size_;
delete [] silence_buffer;
silence_buffer = new T[silence_buffer_size];
TypeUtils<T>::zero_fill (silence_buffer, silence_buffer_size);
}
-
+
in_beginning = true;
in_end = false;
trim_beginning = false;
add_to_beginning = 0;
add_to_end = 0;
}
-
+
/** Tells that \a frames_per_channel frames of silence per channel should be added to beginning
* Needs to be called before starting processing.
* \n RT safe
}
add_to_beginning = frames_per_channel;
}
-
+
/** Tells that \a frames_per_channel frames of silence per channel should be added to end
* Needs to be called before end is reached.
* \n RT safe
}
add_to_end = frames_per_channel;
}
-
+
/** Tells whether ot nor silence should be trimmed from the beginning
* Has to be called before starting processing.
* \n RT safe
}
trim_beginning = yn;
}
-
+
/** Tells whether ot nor silence should be trimmed from the end
* Has to be called before the is reached.
* \n RT safe
debug_stream () << DebugUtils::demangled_name (*this) <<
"::process()" << std::endl;
}
-
+
check_flags (*this, c);
-
+
if (throw_level (ThrowStrict) && in_end) {
throw Exception(*this, "process() after reaching end of input");
}
// If adding to end, delay end of input propagation
if (add_to_end) { c.remove_flag(ProcessContext<T>::EndOfInput); }
-
+
framecnt_t frame_index = 0;
-
+
if (in_beginning) {
-
+
bool has_data = true;
-
+
// only check silence if doing either of these
// This will set both has_data and frame_index
if (add_to_beginning || trim_beginning) {
has_data = find_first_non_zero_sample (c, frame_index);
}
-
+
// Added silence if there is silence to add
if (add_to_beginning) {
-
+
if (debug_level (DebugVerbose)) {
debug_stream () << DebugUtils::demangled_name (*this) <<
" adding to beginning" << std::endl;
}
-
+
ConstProcessContext<T> c_copy (c);
if (has_data) { // There will be more output, so remove flag
c_copy().remove_flag (ProcessContext<T>::EndOfInput);
add_to_beginning *= c.channels();
output_silence_frames (c_copy, add_to_beginning);
}
-
+
// If we are not trimming the beginning, output everything
// Then has_data = true and frame_index = 0
// Otherwise these reflect the silence state
if (has_data) {
-
+
if (debug_level (DebugVerbose)) {
debug_stream () << DebugUtils::demangled_name (*this) <<
" outputting whole frame to beginning" << std::endl;
}
-
+
in_beginning = false;
ConstProcessContext<T> c_out (c, &c.data()[frame_index], c.frames() - frame_index);
ListedSource<T>::output (c_out);
}
-
+
} else if (trim_end) { // Only check zero samples if trimming end
-
+
if (find_first_non_zero_sample (c, frame_index)) {
-
+
if (debug_level (DebugVerbose)) {
debug_stream () << DebugUtils::demangled_name (*this) <<
" flushing intermediate silence and outputting frame" << std::endl;
}
-
+
// context contains non-zero data
output_silence_frames (c, silence_frames); // flush intermediate silence
ListedSource<T>::output (c); // output rest of data
} else { // whole context is zero
-
+
if (debug_level (DebugVerbose)) {
debug_stream () << DebugUtils::demangled_name (*this) <<
" no, output, adding frames to silence count" << std::endl;
}
-
+
silence_frames += c.frames();
}
-
+
} else { // no need to do anything special
-
+
if (debug_level (DebugVerbose)) {
debug_stream () << DebugUtils::demangled_name (*this) <<
" outputting whole frame in middle" << std::endl;
}
-
+
ListedSource<T>::output (c);
}
-
+
// Finally, if in end, add silence to end
if (in_end && add_to_end) {
c.set_flag (ProcessContext<T>::EndOfInput);
debug_stream () << DebugUtils::demangled_name (*this) <<
" adding to end" << std::endl;
}
-
+
add_to_end *= c.channels();
output_silence_frames (c, add_to_end, true);
}
}
return false;
}
-
+
void output_silence_frames (ProcessContext<T> const & c, framecnt_t & total_frames, bool adding_to_end = false)
{
bool end_of_input = c.has_flag (ProcessContext<T>::EndOfInput);
c.remove_flag (ProcessContext<T>::EndOfInput);
-
+
while (total_frames > 0) {
framecnt_t frames = std::min (silence_buffer_size, total_frames);
if (max_output_frames) {
frames = std::min (frames, max_output_frames);
}
frames -= frames % c.channels();
-
+
total_frames -= frames;
ConstProcessContext<T> c_out (c, silence_buffer, frames);
-
+
// boolean commentation :)
bool const no_more_silence_will_be_added = adding_to_end || (add_to_end == 0);
bool const is_last_frame_output_in_this_function = (total_frames == 0);
bool in_beginning;
bool in_end;
-
+
bool trim_beginning;
bool trim_end;
-
+
framecnt_t silence_frames;
framecnt_t max_output_frames;
-
+
framecnt_t add_to_beginning;
framecnt_t add_to_end;
-
+
framecnt_t silence_buffer_size;
T * silence_buffer;
};
/// Init converter \n Not RT safe
void init (framecnt_t in_rate, framecnt_t out_rate, int quality = 0);
-
+
/// Returns max amount of frames that will be output \n RT safe
framecnt_t allocate_buffers (framecnt_t max_frames);
-
+
/** Does sample rate conversion.
* Note that outpt size may vary a lot.
* May or may not output several contexts of data.
bool active;
uint32_t channels;
framecnt_t max_frames_in;
-
+
float * leftover_data;
framecnt_t leftover_frames;
framecnt_t max_leftover_frames;
typedef std::vector<typename Source<T>::SinkPtr> OutputVec;
public:
-
+
/** Constructor
* \n RT safe
* \param thread_pool a thread pool from which all tasks are scheduled
, readers (0)
, wait_timeout (wait_timeout_milliseconds)
{ }
-
+
virtual ~Threader () {}
-
+
/// Adds output \n RT safe
void add_output (typename Source<T>::SinkPtr output) { outputs.push_back (output); }
-
+
/// Clears outputs \n RT safe
void clear_outputs () { outputs.clear (); }
-
+
/// Removes a specific output \n RT safe
void remove_output (typename Source<T>::SinkPtr output) {
typename OutputVec::iterator new_end = std::remove(outputs.begin(), outputs.end(), output);
outputs.erase (new_end, outputs.end());
}
-
+
/// Processes context concurrently by scheduling each output separately to the given thread pool
void process (ProcessContext<T> const & c)
{
wait_mutex.lock();
-
+
exception.reset();
-
+
unsigned int outs = outputs.size();
g_atomic_int_add (&readers, outs);
for (unsigned int i = 0; i < outs; ++i) {
thread_pool.push (sigc::bind (sigc::mem_fun (this, &Threader::process_output), c, i));
}
-
+
wait();
}
-
+
using Sink<T>::process;
-
+
private:
void wait()
}
wait_mutex.unlock();
-
+
if (exception) {
throw *exception;
}
}
-
+
void process_output(ProcessContext<T> const & c, unsigned int output)
{
try {
if(!exception) { exception.reset (new ThreaderException (*this, e)); }
exception_mutex.unlock();
}
-
+
if (g_atomic_int_dec_and_test (&readers)) {
wait_cond.signal();
}
Glib::Threads::Cond wait_cond;
gint readers;
long wait_timeout;
-
+
Glib::Threads::Mutex exception_mutex;
boost::shared_ptr<ThreaderException> exception;
ProcessContext (T * data, framecnt_t frames, ChannelCount channels)
: _data (data), _frames (frames), _channels (channels)
{ validate_data(); }
-
+
/// Normal copy constructor
ProcessContext (ProcessContext<T> const & other)
: Throwing<throwLevel>(), _data (other._data), _frames (other._frames), _channels (other._channels), _flags (other._flags)
{ /* No need to validate data */ }
-
+
/// "Copy constructor" with unique data, frame and channel count, but copies flags
template<typename Y>
ProcessContext (ProcessContext<Y> const & other, T * data, framecnt_t frames, ChannelCount channels)
: Throwing<throwLevel>(), _data (data), _frames (frames), _channels (channels), _flags (other.flags())
{ validate_data(); }
-
+
/// "Copy constructor" with unique data and frame count, but copies channel count and flags
template<typename Y>
ProcessContext (ProcessContext<Y> const & other, T * data, framecnt_t frames)
: Throwing<throwLevel>(), _data (data), _frames (frames), _channels (other.channels()), _flags (other.flags())
{ validate_data(); }
-
+
/// "Copy constructor" with unique data, but copies frame and channel count + flags
template<typename Y>
ProcessContext (ProcessContext<Y> const & other, T * data)
: Throwing<throwLevel>(), _data (data), _frames (other.frames()), _channels (other.channels()), _flags (other.flags())
{ /* No need to validate data */ }
-
+
/// Make new Context out of the beginning of this context
ProcessContext beginning (framecnt_t frames)
{
% DebugUtils::demangled_name (*this) % frames % _frames));
}
validate_data ();
-
+
return ProcessContext (*this, _data, frames);
}
-
+
virtual ~ProcessContext () {}
-
+
/// \a data points to the array of data to process
inline T const * data() const { return _data; }
inline T * data() { return _data; }
-
+
/// \a frames tells how many frames the array pointed by data contains
inline framecnt_t const & frames() const { return _frames; }
-
+
/** \a channels tells how many interleaved channels \a data contains
* If \a channels is greater than 1, each channel contains \a frames / \a channels frames of data
*/
inline ChannelCount const & channels() const { return _channels; }
-
+
/// Returns the amount of frames per channel
inline framecnt_t frames_per_channel() const { return _frames / _channels; }
/* Flags */
-
+
inline bool has_flag (Flag flag) const { return _flags.has (flag); }
inline void set_flag (Flag flag) const { _flags.set (flag); }
inline void remove_flag (Flag flag) const { _flags.remove (flag); }
inline FlagField const & flags () const { return _flags; }
-
+
protected:
T * const _data;
framecnt_t _frames;
ChannelCount _channels;
-
+
mutable FlagField _flags;
private:
/// Allocates uninitialized memory
AllocatingProcessContext (framecnt_t frames, ChannelCount channels)
: ProcessContext<T> (new T[frames], frames, channels) {}
-
+
/// Allocates and copies data from raw buffer
AllocatingProcessContext (T const * data, framecnt_t frames, ChannelCount channels)
: ProcessContext<T> (new T[frames], frames, channels)
{ TypeUtils<float>::copy (data, ProcessContext<T>::_data, frames); }
-
+
/// Copy constructor, copies data from other ProcessContext
AllocatingProcessContext (ProcessContext<T> const & other)
: ProcessContext<T> (other, new T[other._frames])
{ TypeUtils<float>::copy (ProcessContext<T>::_data, other._data, other._frames); }
-
+
/// "Copy constructor" with uninitialized data, unique frame and channel count, but copies flags
template<typename Y>
AllocatingProcessContext (ProcessContext<Y> const & other, framecnt_t frames, ChannelCount channels)
: ProcessContext<T> (other, new T[frames], frames, channels) {}
-
+
/// "Copy constructor" with uninitialized data, unique frame count, but copies channel count and flags
template<typename Y>
AllocatingProcessContext (ProcessContext<Y> const & other, framecnt_t frames)
: ProcessContext<T> (other, new T[frames], frames, other.channels()) {}
-
+
/// "Copy constructor" uninitialized data, that copies frame and channel count + flags
template<typename Y>
AllocatingProcessContext (ProcessContext<Y> const & other)
: ProcessContext<T> (other, new T[other._frames]) {}
-
+
~AllocatingProcessContext () { delete [] ProcessContext<T>::_data; }
};
/// Basic constructor with data, frame and channel count
ConstProcessContext (T const * data, framecnt_t frames, ChannelCount channels)
: context (const_cast<T *>(data), frames, channels) {}
-
+
/// Copy constructor from const ProcessContext
ConstProcessContext (ProcessContext<T> const & other)
: context (const_cast<ProcessContext<T> &> (other)) {}
-
+
/// "Copy constructor", with unique data, frame and channel count, but copies flags
template<typename ProcessContext>
ConstProcessContext (ProcessContext const & other, T const * data, framecnt_t frames, ChannelCount channels)
: context (other, const_cast<T *>(data), frames, channels) {}
-
+
/// "Copy constructor", with unique data and frame count, but copies channel count and flags
template<typename ProcessContext>
ConstProcessContext (ProcessContext const & other, T const * data, framecnt_t frames)
: context (other, const_cast<T *>(data), frames) {}
-
+
/// "Copy constructor", with unique data, but copies frame and channel count + flags
template<typename ProcessContext>
ConstProcessContext (ProcessContext const & other, T const * data)
{
public:
typedef uint32_t uint_type;
-
+
typedef float (*compute_peak_t) (float const *, uint_type, float);
typedef void (*apply_gain_to_buffer_t) (float *, uint_type, float);
-
+
static void override_compute_peak (compute_peak_t func) { _compute_peak = func; }
static void override_apply_gain_to_buffer (apply_gain_to_buffer_t func) { _apply_gain_to_buffer = func; }
-
+
/** Computes peak in float buffer
* \n RT safe
* \param data buffer from which the peak is computed
data[i] *= gain;
}
}
-
+
static compute_peak_t _compute_peak;
static apply_gain_to_buffer_t _apply_gain_to_buffer;
};
class /*LIBAUDIOGRAPHER_API*/ Sink {
public:
virtual ~Sink () {}
-
+
/** Process given data.
* The data can not be modified, so in-place processing is not allowed.
* At least this function must be implemented by deriving classes
*/
virtual void process (ProcessContext<T> const & context) = 0;
-
+
/** Process given data
* Data may be modified, so in place processing is allowed.
* The default implementation calls the non-modifying version,
class Sndfile : public SndfileWriter<T>, public SndfileReader<T>
{
public:
-
+
Sndfile (std::string const & filename, SndfileBase::Mode mode = SndfileBase::ReadWrite, int format = 0,
ChannelCount channels = 0, framecnt_t samplerate = 0)
: SndfileHandle (filename, mode, format, channels, samplerate)
{}
-
+
Sndfile (Sndfile const & other) : SndfileHandle (other) {}
using SndfileHandle::operator=;
-
+
};
} // namespace
Write = SFM_WRITE,
ReadWrite = SFM_RDWR
};
-
+
protected:
SndfileBase () {}
};
, public Throwing<>
{
public:
-
+
SndfileReader (std::string const & path) : SndfileHandle (path) {}
virtual ~SndfileReader () {}
SndfileReader (SndfileReader const & other) : SndfileHandle (other) {}
using SndfileHandle::operator=;
-
+
/** Read data into buffer in \a context, only the data is modified (not frame count)
* Note that the data read is output to the outputs, as well as read into the context
* \return number of frames read
("Wrong number of channels given to process(), %1% instead of %2%")
% context.channels() % channels()));
}
-
+
framecnt_t const frames_read = SndfileHandle::read (context.data(), context.frames());
ProcessContext<T> c_out = context.beginning (frames_read);
-
+
if (frames_read < context.frames()) {
c_out.set_flag (ProcessContext<T>::EndOfInput);
}
this->output (c_out);
return frames_read;
}
-
+
protected:
/// SndfileHandle has to be constructed directly by deriving classes
SndfileReader () {}
broadcast_info->write_to_file (this);
}
}
-
+
virtual ~SndfileWriter () {}
-
+
SndfileWriter (SndfileWriter const & other)
: SndfileHandle (other)
{
framecnt_t get_frames_written() const { return frames_written; }
void reset_frames_written_count() { frames_written = 0; }
-
+
/// Writes data to file
void process (ProcessContext<T> const & c)
{
check_flags (*this, c);
-
+
if (throw_level (ThrowStrict) && c.channels() != channels()) {
throw Exception (*this, boost::str (boost::format
("Wrong number of channels given to process(), %1% instead of %2%")
% c.channels() % channels()));
}
-
+
framecnt_t const written = write (c.data(), c.frames());
frames_written += written;
FileWritten (path);
}
}
-
+
using Sink<T>::process;
-
+
PBD::Signal1<void, std::string> FileWritten;
protected:
{
public:
virtual ~Source () { }
-
+
typedef boost::shared_ptr<Sink<T> > SinkPtr;
-
+
/// Adds an output to this source. All data generated is forwarded to \a output
virtual void add_output (SinkPtr output) = 0;
-
+
/// Removes all outputs added
virtual void clear_outputs () = 0;
-
+
/// Removes a specific output from this source
virtual void remove_output (SinkPtr output) = 0;
};
class LIBAUDIOGRAPHER_API TypeUtilsBase
{
protected:
-
+
template<typename T, bool b>
static void do_zero_fill(T * buffer, framecnt_t frames, const boost::integral_constant<bool, b>&)
{ std::uninitialized_fill_n (buffer, frames, T()); }
class /*LIBAUDIOGRAPHER_API*/ TypeUtils : private TypeUtilsBase
{
BOOST_STATIC_ASSERT (boost::has_trivial_destructor<T>::value);
-
+
typedef boost::integral_constant<bool,
boost::is_floating_point<T>::value ||
boost::is_signed<T>::value> zero_fillable;
*/
inline static void zero_fill (T * buffer, framecnt_t frames)
{ do_zero_fill(buffer, frames, zero_fillable()); }
-
+
/** Copies \a frames frames of data from \a source to \a destination
* The source and destination may NOT overlap.
* \n RT safe
*/
inline static void copy (T const * source, T * destination, framecnt_t frames)
{ std::uninitialized_copy (source, &source[frames], destination); }
-
+
/** Moves \a frames frames of data from \a source to \a destination
* The source and destination may overlap in any way.
* \n RT safe
namespace AudioGrapher {
-/* XXX: copied from libardour */
+/* XXX: copied from libardour */
typedef int64_t framecnt_t;
-
+
typedef uint8_t ChannelCount;
typedef float DefaultSampleType;
void add_output (typename Source<T>::SinkPtr output) { outputs.push_back(output); }
void clear_outputs () { outputs.clear(); }
void remove_output (typename Source<T>::SinkPtr output) { outputs.remove(output); }
-
+
protected:
-
+
typedef std::list<typename Source<T>::SinkPtr> SinkList;
-
+
/// Helper for derived classes
void output (ProcessContext<T> const & c)
{
DebugUtils::process_context_flag_name (FlagField::Flag flag)
{
std::ostringstream ret;
-
+
switch (flag) {
case ProcessContext<>::EndOfInput:
ret << "EndOfInput";
ret << flag;
break;
}
-
+
return ret.str();
}
{
target = pow (10.0f, target_dB * 0.05f);
}
-
+
Normalizer::~Normalizer()
{
delete [] buffer;
if (throw_level (ThrowProcess) && c.frames() > buffer_size) {
throw Exception (*this, "Too many frames given to process()");
}
-
+
if (enabled) {
memcpy (buffer, c.data(), c.frames() * sizeof(float));
Routines::apply_gain_to_buffer (buffer, c.frames(), gain);
}
-
+
ProcessContext<float> c_out (c, buffer);
ListedSource<float>::output (c_out);
}
gdither_free (dither);
dither = 0;
}
-
+
delete[] data_out;
data_out_size = 0;
data_out = 0;
-
+
clip_floats = false;
}
SampleFormatConverter<TOut>::process (ProcessContext<float> const & c_in)
{
float const * const data = c_in.data();
-
+
check_frame_and_channel_count (c_in.frames (), c_in.channels ());
/* Do conversion */
{
framecnt_t frames = c_in.frames();
float * data = c_in.data();
-
+
if (clip_floats) {
for (framecnt_t x = 0; x < frames; ++x) {
if (data[x] > 1.0f) {
// Make copy of data and pass it to non-const version
check_frame_and_channel_count (c_in.frames(), c_in.channels());
TypeUtils<float>::copy (c_in.data(), data_out, c_in.frames());
-
+
ProcessContext<float> c (c_in, data_out);
process (c);
}
("Wrong channel count given to process(), %1% instead of %2%")
% channels_ % channels));
}
-
+
if (throw_level (ThrowProcess) && frames > data_out_size) {
throw Exception (*this, boost::str (boost::format
("Too many frames given to process(), %1% instad of %2%")
SampleRateConverter::init (framecnt_t in_rate, framecnt_t out_rate, int quality)
{
reset();
-
+
if (in_rate == out_rate) {
src_data.src_ratio = 1;
return;
SampleRateConverter::allocate_buffers (framecnt_t max_frames)
{
if (!active) { return max_frames; }
-
+
framecnt_t max_frames_out = (framecnt_t) ceil (max_frames * src_data.src_ratio);
if (data_out_size < max_frames_out) {
max_frames_in = max_frames;
data_out_size = max_frames_out;
}
-
+
return max_frames_out;
}
SampleRateConverter::process (ProcessContext<float> const & c)
{
check_flags (*this, c);
-
+
if (!active) {
output (c);
return;
", data_out: " << src_data.data_out <<
", output_frames: " << src_data.output_frames << std::endl;
}
-
+
err = src_process (src_state, &src_data);
if (throw_level (ThrowProcess) && err) {
throw Exception (*this, str (format
("No output frames genereated with %1% leftover frames")
% leftover_frames));
}
-
+
} while (leftover_frames > frames);
-
+
// src_data.end_of_input has to be checked to prevent infinite recursion
if (!src_data.end_of_input && c.has_flag(ProcessContext<float>::EndOfInput)) {
set_end_of_input (c);
void SampleRateConverter::set_end_of_input (ProcessContext<float> const & c)
{
src_data.end_of_input = true;
-
+
float f;
ProcessContext<float> const dummy (c, &f, 0, channels);
-
+
/* No idea why this has to be done twice for all data to be written,
* but that just seems to be the way it is...
*/
active = false;
max_frames_in = 0;
src_data.end_of_input = false;
-
+
if (src_state) {
src_delete (src_state);
}
-
+
leftover_frames = 0;
max_leftover_frames = 0;
if (leftover_data) {
free (leftover_data);
}
-
+
data_out_size = 0;
delete [] data_out;
data_out = 0;
{
chunker->add_output (sink);
framecnt_t frames_output = 0;
-
+
ProcessContext<float> const context (random_data, frames, 1);
-
+
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_output);
-
+
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (2 * frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[frames], frames));
-
+
sink->reset();
-
+
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_output);
-
+
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (2 * frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[frames], frames));
}
-
+
void testAsynchronousProcess()
{
assert (frames % 2 == 0);
-
+
chunker->add_output (sink);
framecnt_t frames_output = 0;
-
+
ProcessContext<float> const half_context (random_data, frames / 2, 1);
ProcessContext<float> const context (random_data, frames, 1);
-
+
// 0.5
chunker->process (half_context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_output);
-
+
// 1.5
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_output);
-
+
// 2.5
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), frames / 2));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[frames / 2], frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[ 3 * frames / 2], frames / 2));
-
+
sink->reset();
-
+
// 3.5
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_output);
-
+
// 4.0
chunker->process (half_context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[frames / 2], frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, &sink->get_array()[ 3 * frames / 2], frames / 2));
}
-
+
void testChoppingProcess()
{
sink.reset (new AppendingVectorSink<float>());
-
+
assert (frames % 2 == 0);
chunker.reset (new Chunker<float>(frames / 4));
-
+
chunker->add_output (sink);
framecnt_t frames_output = 0;
-
+
ProcessContext<float> const half_context (random_data, frames / 2, 1);
ProcessContext<float> const context (random_data, frames, 1);
-
+
// 0.5
chunker->process (half_context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) frames / 2, frames_output);
-
+
// 1.5
chunker->process (context);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) frames / 2 * 3, frames_output);
-
+
// 2.5
chunker->process (context);
frames_output = sink->get_data().size();
void testEndOfInputFlagHandling()
{
boost::shared_ptr<ProcessContextGrabber<float> > grabber(new ProcessContextGrabber<float>());
-
+
assert (frames % 2 == 0);
chunker.reset (new Chunker<float>(frames));
chunker->add_output (grabber);
-
+
ProcessContext<float> const half_context (random_data, frames / 2, 1);
ProcessContext<float> const context (random_data, frames, 1);
context.set_flag(ProcessContext<>::EndOfInput);
-
+
// Process 0.5 then 1.0
chunker->process (half_context);
chunker->process (context);
void testInvalidInputSize()
{
deinterleaver->init (channels, frames_per_channel);
-
+
ProcessContext<float> c (random_data, 2 * total_frames, channels);
-
+
// Too many, frames % channels == 0
CPPUNIT_ASSERT_THROW (deinterleaver->process (c.beginning (total_frames + channels)), Exception);
-
+
// Too many, frames % channels != 0
CPPUNIT_ASSERT_THROW (deinterleaver->process (c.beginning (total_frames + 1)), Exception);
-
+
// Too few, frames % channels != 0
CPPUNIT_ASSERT_THROW (deinterleaver->process (c.beginning (total_frames - 1)), Exception);
}
void assert_outputs (framecnt_t expected_frames)
{
framecnt_t generated_frames = 0;
-
+
generated_frames = sink_a->get_data().size();
CPPUNIT_ASSERT_EQUAL (expected_frames, generated_frames);
-
+
generated_frames = sink_b->get_data().size();
CPPUNIT_ASSERT_EQUAL (expected_frames, generated_frames);
-
+
generated_frames = sink_c->get_data().size();
CPPUNIT_ASSERT_EQUAL (expected_frames, generated_frames);
}
void testOutputSize()
{
deinterleaver->init (channels, frames_per_channel);
-
+
deinterleaver->output (0)->add_output (sink_a);
deinterleaver->output (1)->add_output (sink_b);
deinterleaver->output (2)->add_output (sink_c);
-
+
// Test maximum frame input
ProcessContext<float> c (random_data, total_frames, channels);
deinterleaver->process (c);
assert_outputs (frames_per_channel);
-
+
// Now with less frames
framecnt_t const less_frames = frames_per_channel / 4;
deinterleaver->process (c.beginning (less_frames * channels));
assert_outputs (less_frames);
}
-
+
void testZeroInput()
{
deinterleaver->init (channels, frames_per_channel);
-
+
deinterleaver->output (0)->add_output (sink_a);
deinterleaver->output (1)->add_output (sink_b);
deinterleaver->output (2)->add_output (sink_c);
-
+
// Input zero frames
ProcessContext<float> c (random_data, total_frames, channels);
deinterleaver->process (c.beginning (0));
-
+
// ...and now test regular input
deinterleaver->process (c);
assert_outputs (frames_per_channel);
channels = 3;
frames_per_channel = 128;
total_frames = channels * frames_per_channel;
-
+
random_data_a = TestUtils::init_random_data (total_frames, 1.0);
random_data_b = TestUtils::init_random_data (frames_per_channel, 1.0);
random_data_c = TestUtils::init_random_data (frames_per_channel, 1.0);
deinterleaver.reset (new DeInterleaver<float>());
interleaver.reset (new Interleaver<float>());
-
+
sink_a.reset (new VectorSink<float>());
sink_b.reset (new VectorSink<float>());
sink_c.reset (new VectorSink<float>());
{
deinterleaver->init (channels, frames_per_channel);
interleaver->init (channels, frames_per_channel);
-
+
deinterleaver->output (0)->add_output (interleaver->input (0));
deinterleaver->output (1)->add_output (interleaver->input (1));
deinterleaver->output (2)->add_output (interleaver->input (2));
-
+
interleaver->add_output (sink_a);
-
+
// Process and assert
ProcessContext<float> c (random_data_a, total_frames, channels);
deinterleaver->process (c);
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_a, sink_a->get_array(), total_frames));
-
+
// And a second round...
framecnt_t less_frames = (frames_per_channel / 10) * channels;
deinterleaver->process (c.beginning (less_frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_a, sink_a->get_array(), less_frames));
}
-
+
void testDeInterleavedInput()
{
deinterleaver->init (channels, frames_per_channel);
interleaver->init (channels, frames_per_channel);
-
+
interleaver->add_output (deinterleaver);
-
+
deinterleaver->output (0)->add_output (sink_a);
deinterleaver->output (1)->add_output (sink_b);
deinterleaver->output (2)->add_output (sink_c);
-
+
ProcessContext<float> c_a (random_data_a, frames_per_channel, 1);
ProcessContext<float> c_b (random_data_b, frames_per_channel, 1);
ProcessContext<float> c_c (random_data_c, frames_per_channel, 1);
-
+
// Process and assert
interleaver->input (0)->process (c_a);
interleaver->input (1)->process (c_b);
interleaver->input (2)->process (c_c);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_a, sink_a->get_array(), frames_per_channel));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_b, sink_b->get_array(), frames_per_channel));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_c, sink_c->get_array(), frames_per_channel));
-
+
// And a second round...
framecnt_t less_frames = frames_per_channel / 5;
interleaver->input (0)->process (c_a.beginning (less_frames));
interleaver->input (1)->process (c_b.beginning (less_frames));
interleaver->input (2)->process (c_c.beginning (less_frames));
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_a, sink_a->get_array(), less_frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_b, sink_b->get_array(), less_frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data_c, sink_c->get_array(), less_frames));
-
+
}
private:
boost::shared_ptr<Interleaver<float> > interleaver;
boost::shared_ptr<DeInterleaver<float> > deinterleaver;
-
+
boost::shared_ptr<VectorSink<float> > sink_a;
boost::shared_ptr<VectorSink<float> > sink_b;
boost::shared_ptr<VectorSink<float> > sink_c;
float * random_data_a;
float * random_data_b;
float * random_data_c;
-
+
framecnt_t frames_per_channel;
framecnt_t total_frames;
unsigned int channels;
interleaver.reset (new Interleaver<float>());
sink.reset (new VectorSink<float>());
-
+
interleaver->init (channels, frames);
}
{
ProcessContext<float> c (random_data, frames + 1, 1);
CPPUNIT_ASSERT_THROW (interleaver->input (0)->process (c), Exception);
-
+
interleaver->input (0)->process (c.beginning (frames));
interleaver->input (1)->process (c.beginning (frames));
CPPUNIT_ASSERT_THROW (interleaver->input (2)->process (c.beginning (frames - 1)), Exception);
interleaver->input (0)->process (c.beginning (0));
interleaver->input (1)->process (c.beginning (0));
interleaver->input (2)->process (c.beginning (0));
-
+
// NOTE zero input is allowed to be a NOP
-
+
// ...now test regular input
interleaver->input (0)->process (c);
interleaver->input (1)->process (c);
interleaver->add_output (sink);
ProcessContext<float> c (random_data, frames, 1);
interleaver->input (0)->process (c);
- CPPUNIT_ASSERT_THROW (interleaver->input (0)->process (c), Exception);
+ CPPUNIT_ASSERT_THROW (interleaver->input (0)->process (c), Exception);
}
{
float target = 0.0;
random_data = TestUtils::init_random_data(frames, 0.5);
-
+
normalizer.reset (new Normalizer(target));
peak_reader.reset (new PeakReader());
sink.reset (new VectorSink<float>());
-
+
ProcessContext<float> const c (random_data, frames, 1);
peak_reader->process (c);
-
+
float peak = peak_reader->get_peak();
normalizer->alloc_buffer (frames);
normalizer->set_peak (peak);
normalizer->add_output (sink);
normalizer->process (c);
-
+
peak_reader->reset();
ConstProcessContext<float> normalized (sink->get_array(), frames, 1);
peak_reader->process (normalized);
-
+
peak = peak_reader->get_peak();
CPPUNIT_ASSERT (-FLT_EPSILON <= (peak - 1.0) && (peak - 1.0) <= 0.0);
}
{
reader.reset (new PeakReader());
ProcessContext<float> c (random_data, frames, 1);
-
+
float peak = 1.5;
random_data[10] = peak;
reader->process (c);
CPPUNIT_ASSERT_EQUAL(peak, reader->get_peak());
-
+
peak = 2.0;
random_data[10] = peak;
reader->process (c);
CPPUNIT_ASSERT_EQUAL(peak, reader->get_peak());
-
+
peak = -2.1;
random_data[10] = peak;
reader->process (c);
{
boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
-
+
converter->init (frames, D_Tri, 32);
converter->add_output (sink);
framecnt_t frames_output = 0;
-
+
{
ProcessContext<float> pc(random_data, frames / 2, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames / 2, frames_output);
}
-
+
{
ProcessContext<float> pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
}
-
+
{
ProcessContext<float> pc(random_data, frames + 1, 1);
CPPUNIT_ASSERT_THROW(converter->process (pc), Exception);
boost::shared_ptr<SampleFormatConverter<float> > converter (new SampleFormatConverter<float>(1));
boost::shared_ptr<VectorSink<float> > sink (new VectorSink<float>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 32);
converter->add_output (sink);
-
+
converter->set_clip_floats (false);
ProcessContext<float> const pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_equals(sink->get_array(), random_data, frames));
-
+
// Make sure a few samples are < -1.0 and > 1.0
random_data[10] = -1.5;
random_data[20] = 1.5;
-
+
converter->set_clip_floats (true);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
-
+
for (framecnt_t i = 0; i < frames; ++i) {
// fp comparison needs a bit of tolerance, 1.01 << 1.5
CPPUNIT_ASSERT(sink->get_data()[i] < 1.01);
boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 32);
converter->add_output (sink);
-
+
ProcessContext<float> pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
}
-
+
void testInt24()
{
boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(1));
boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 24);
converter->add_output (sink);
-
+
ProcessContext<float> pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
}
-
+
void testInt16()
{
boost::shared_ptr<SampleFormatConverter<int16_t> > converter (new SampleFormatConverter<int16_t>(1));
boost::shared_ptr<VectorSink<int16_t> > sink (new VectorSink<int16_t>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 16);
converter->add_output (sink);
-
+
ProcessContext<float> pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
}
-
+
void testUint8()
{
boost::shared_ptr<SampleFormatConverter<uint8_t> > converter (new SampleFormatConverter<uint8_t>(1));
boost::shared_ptr<VectorSink<uint8_t> > sink (new VectorSink<uint8_t>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 8);
converter->add_output (sink);
-
+
ProcessContext<float> pc(random_data, frames, 1);
converter->process (pc);
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
CPPUNIT_ASSERT (TestUtils::array_filled(sink->get_array(), frames));
}
-
+
void testChannelCount()
{
boost::shared_ptr<SampleFormatConverter<int32_t> > converter (new SampleFormatConverter<int32_t>(3));
boost::shared_ptr<VectorSink<int32_t> > sink (new VectorSink<int32_t>());
framecnt_t frames_output = 0;
-
+
converter->init(frames, D_Tri, 32);
converter->add_output (sink);
-
+
ProcessContext<float> pc(random_data, 4, 1);
CPPUNIT_ASSERT_THROW (converter->process (pc), Exception);
-
+
framecnt_t new_frame_count = frames - (frames % 3);
converter->process (ProcessContext<float> (pc.data(), new_frame_count, 3));
frames_output = sink->get_data().size();
void setUp()
{
frames = 128;
-
+
random_data = TestUtils::init_random_data(frames);
random_data[0] = 0.5;
random_data[frames - 1] = 0.5;
-
+
zero_data = new float[frames];
memset(zero_data, 0, frames * sizeof(float));
-
+
half_random_data = TestUtils::init_random_data(frames);
memset(half_random_data, 0, (frames / 2) * sizeof(float));
-
+
trimmer.reset (new SilenceTrimmer<float> (frames / 2));
sink.reset (new AppendingVectorSink<float>());
-
+
trimmer->set_trim_beginning (true);
trimmer->set_trim_end (true);
}
void testFullBuffers()
{
trimmer->add_output (sink);
-
+
{
ProcessContext<float> c (zero_data, frames, 1);
trimmer->process (c);
framecnt_t frames_processed = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL ((framecnt_t) 0, frames_processed);
}
-
+
{
ProcessContext<float> c (random_data, frames, 1);
trimmer->process (c);
CPPUNIT_ASSERT_EQUAL (frames, frames_processed);
CPPUNIT_ASSERT (TestUtils::array_equals (sink->get_array(), random_data, frames));
}
-
+
{
ProcessContext<float> c (zero_data, frames, 1);
trimmer->process (c);
framecnt_t frames_processed = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_processed);
}
-
+
{
ProcessContext<float> c (random_data, frames, 1);
trimmer->process (c);
CPPUNIT_ASSERT (TestUtils::array_equals (&sink->get_array()[frames], zero_data, frames));
CPPUNIT_ASSERT (TestUtils::array_equals (&sink->get_array()[2 * frames], random_data, frames));
}
-
+
{
ProcessContext<float> c (zero_data, frames, 1);
trimmer->process (c);
CPPUNIT_ASSERT_EQUAL (3 * frames, frames_processed);
}
}
-
+
void testPartialBuffers()
{
trimmer->add_output (sink);
trimmer->reset (frames / 4);
trimmer->set_trim_beginning (true);
trimmer->set_trim_end (true);
-
+
{
ProcessContext<float> c (half_random_data, frames, 1);
trimmer->process (c);
CPPUNIT_ASSERT_EQUAL (frames / 2, frames_processed);
CPPUNIT_ASSERT (TestUtils::array_equals (sink->get_array(), &half_random_data[frames / 2], frames / 2));
}
-
+
{
ProcessContext<float> c (zero_data, frames, 1);
trimmer->process (c);
framecnt_t frames_processed = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames / 2, frames_processed);
}
-
+
{
ProcessContext<float> c (half_random_data, frames, 1);
trimmer->process (c);
CPPUNIT_ASSERT (TestUtils::array_equals (&sink->get_array()[frames + frames / 2], half_random_data, frames));
}
}
-
+
void testExceptions()
{
{
CPPUNIT_ASSERT_THROW (trimmer->reset (0), Exception);
}
}
-
+
void testAddSilenceBeginning()
{
trimmer->add_output (sink);
-
+
framecnt_t silence = frames / 2;
trimmer->add_silence_to_beginning (silence);
-
+
{
ProcessContext<float> c (random_data, frames, 1);
trimmer->process (c);
}
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (sink->get_array(), zero_data, silence));
CPPUNIT_ASSERT (TestUtils::array_equals (&sink->get_array()[silence], random_data, frames));
}
-
+
void testAddSilenceEnd()
{
trimmer->add_output (sink);
-
+
framecnt_t silence = frames / 3;
trimmer->add_silence_to_end (silence);
-
+
{
ProcessContext<float> c (random_data, frames, 1);
trimmer->process (c);
}
-
+
{
ProcessContext<float> c (random_data, frames, 1);
c.set_flag (ProcessContext<float>::EndOfInput);
trimmer->process (c);
}
-
+
framecnt_t frames_processed = sink->get_data().size();
framecnt_t total_frames = 2 * frames + silence;
CPPUNIT_ASSERT_EQUAL (total_frames, frames_processed);
assert (frames % 2 == 0);
framecnt_t const half_frames = frames / 2;
framecnt_t frames_output = 0;
-
+
converter->init (44100, 44100);
converter->add_output (sink);
-
+
ProcessContext<float> c (random_data, half_frames, 1);
converter->process (c);
ProcessContext<float> c2 (&random_data[half_frames], half_frames, 1);
c2.set_flag (ProcessContext<float>::EndOfInput);
converter->process (c2);
-
+
frames_output = sink->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink->get_array(), frames));
}
assert (frames % 2 == 0);
framecnt_t const half_frames = frames / 2;
framecnt_t frames_output = 0;
-
+
converter->init (44100, 88200);
converter->allocate_buffers (half_frames);
converter->add_output (sink);
-
+
ProcessContext<float> c (random_data, half_frames, 1);
converter->process (c);
ProcessContext<float> c2 (&random_data[half_frames], half_frames, 1);
assert (frames % 2 == 0);
framecnt_t const half_frames = frames / 2;
framecnt_t frames_output = 0;
-
+
converter->init (88200, 44100);
converter->allocate_buffers (half_frames);
converter->add_output (sink);
-
+
ProcessContext<float> c (random_data, half_frames, 1);
converter->process (c);
ProcessContext<float> c2 (&random_data[half_frames], half_frames, 1);
c2.set_flag (ProcessContext<float>::EndOfInput);
converter->process (c2);
-
+
frames_output = sink->get_data().size();
framecnt_t tolerance = 3;
CPPUNIT_ASSERT (half_frames - tolerance < frames_output && frames_output < half_frames + tolerance);
}
-
+
void testRespectsEndOfInput()
{
assert (frames % 2 == 0);
framecnt_t const half_frames = frames / 2;
-
+
converter->init (44100, 48000);
converter->allocate_buffers (half_frames);
converter->add_output (grabber);
-
+
ProcessContext<float> c (random_data, half_frames, 1);
converter->process (c);
ProcessContext<float> c2 (&random_data[half_frames], half_frames / 2, 1);
c2.set_flag (ProcessContext<float>::EndOfInput);
converter->process (c2);
-
+
for (std::list<ProcessContext<float> >::iterator it = grabber->contexts.begin(); it != grabber->contexts.end(); ++it) {
std::list<ProcessContext<float> >::iterator next = it; ++next;
if (next == grabber->contexts.end()) {
}
}
}
-
+
private:
boost::shared_ptr<SampleRateConverter > converter;
{
frames = 128;
random_data = TestUtils::init_random_data (frames, 1.0);
-
+
zero_data = new float[frames];
memset (zero_data, 0, frames * sizeof(float));
-
+
thread_pool = new Glib::ThreadPool (3);
threader.reset (new Threader<float> (*thread_pool));
-
+
sink_a.reset (new VectorSink<float>());
sink_b.reset (new VectorSink<float>());
sink_c.reset (new VectorSink<float>());
sink_d.reset (new VectorSink<float>());
sink_e.reset (new VectorSink<float>());
sink_f.reset (new VectorSink<float>());
-
+
throwing_sink.reset (new ThrowingSink<float>());
}
{
delete [] random_data;
delete [] zero_data;
-
+
thread_pool->shutdown();
delete thread_pool;
}
threader->add_output (sink_d);
threader->add_output (sink_e);
threader->add_output (sink_f);
-
+
ProcessContext<float> c (random_data, frames, 1);
threader->process (c);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_b->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_c->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_e->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_f->get_array(), frames));
}
-
+
void testRemoveOutput()
{
threader->add_output (sink_a);
threader->add_output (sink_d);
threader->add_output (sink_e);
threader->add_output (sink_f);
-
+
ProcessContext<float> c (random_data, frames, 1);
threader->process (c);
-
+
// Remove a, b and f
threader->remove_output (sink_a);
threader->remove_output (sink_b);
threader->remove_output (sink_f);
-
+
ProcessContext<float> zc (zero_data, frames, 1);
threader->process (zc);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_b->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(zero_data, sink_c->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(zero_data, sink_e->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_f->get_array(), frames));
}
-
+
void testClearOutputs()
{
threader->add_output (sink_a);
threader->add_output (sink_d);
threader->add_output (sink_e);
threader->add_output (sink_f);
-
+
ProcessContext<float> c (random_data, frames, 1);
threader->process (c);
-
+
threader->clear_outputs();
ProcessContext<float> zc (zero_data, frames, 1);
threader->process (zc);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_b->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_c->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_e->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_f->get_array(), frames));
}
-
+
void testExceptions()
{
threader->add_output (sink_a);
threader->add_output (throwing_sink);
threader->add_output (sink_e);
threader->add_output (throwing_sink);
-
+
ProcessContext<float> c (random_data, frames, 1);
CPPUNIT_ASSERT_THROW (threader->process (c), Exception);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_b->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals(random_data, sink_c->get_array(), frames));
private:
Glib::ThreadPool * thread_pool;
-
+
boost::shared_ptr<Threader<float> > threader;
boost::shared_ptr<VectorSink<float> > sink_a;
boost::shared_ptr<VectorSink<float> > sink_b;
boost::shared_ptr<VectorSink<float> > sink_d;
boost::shared_ptr<VectorSink<float> > sink_e;
boost::shared_ptr<VectorSink<float> > sink_f;
-
+
boost::shared_ptr<ThrowingSink<float> > throwing_sink;
float * random_data;
AllocatingProcessContext<float> c (random_data, frames, channels);
c.set_flag (ProcessContext<float>::EndOfInput);
file->process (c);
-
+
TypeUtils<float>::zero_fill (c.data (), c.frames());
-
+
file->seek (0, SEEK_SET);
file->read (c);
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, c.data(), c.frames()));
public:
void setUp()
{
-
+
}
void tearDown()
{
-
+
}
void testZeroFillPod()
CPPUNIT_ASSERT_EQUAL (zero, buf[i]);
}
}
-
+
void testZeroFillNonPod()
{
/* does not compile on OS X Lion
}
*/
}
-
+
void testMoveBackward()
{
int seq[8] = { 0, 1, 2, 3,
4, 5, 6, 7 };
-
+
TypeUtils<int>::move (&seq[4], &seq[2], 4);
-
+
for (int i = 2; i < 2 + 4; ++i) {
CPPUNIT_ASSERT_EQUAL (i + 2, seq[i]);
}
}
-
+
void testMoveForward()
{
int seq[8] = { 0, 1, 2, 3,
4, 5, 6, 7 };
-
+
TypeUtils<int>::move (&seq[2], &seq[4], 4);
-
+
for (int i = 4; i < 4 + 4; ++i) {
CPPUNIT_ASSERT_EQUAL (i - 2, seq[i]);
}
int const seq2[4] = { 5, 6, 7, 8 };
int seq3[8] = { 0, 0, 0, 0,
0, 0, 0, 0 };
-
+
TypeUtils<int>::copy (seq1, seq3, 4);
for (int i = 0; i < 4; ++i) {
CPPUNIT_ASSERT_EQUAL (seq1[i], seq3[i]);
}
-
+
for (int i = 4; i < 8; ++i) {
CPPUNIT_ASSERT_EQUAL (0, seq3[i]);
}
-
+
TypeUtils<int>::copy (seq2, &seq3[4], 4);
for (int i = 0; i < 4; ++i) {
CPPUNIT_ASSERT_EQUAL (seq1[i], seq3[i]);
}
private:
-
+
struct NonPodType {
NonPodType() : data (42) {}
bool operator== (NonPodType const & other) const
{ return data == other.data; }
int data;
};
-
+
};
unsigned int const granularity = 4096;
float * data = new float[frames];
srand (std::time (NULL));
-
+
for (framecnt_t i = 0; i < frames; ++i) {
do {
int biased_int = (rand() % granularity) - (granularity / 2);
contexts.push_back (c);
}
using AudioGrapher::Sink<T>::process;
-
+
typedef std::list<AudioGrapher::ProcessContext<T> > ContextList;
ContextList contexts;
-
+
};
#endif // AUDIOGRAPHER_TESTS_UTILS_H
{
frames = 128;
random_data = TestUtils::init_random_data(frames);
-
+
zero_data = new float[frames];
memset (zero_data, 0, frames * sizeof(float));
vertex.reset (new IdentityVertex<float>());
vertex->add_output (sink_a);
vertex->add_output (sink_b);
-
+
framecnt_t frames_output = 0;
-
+
ProcessContext<float> c (random_data, frames, 1);
vertex->process (c);
-
+
frames_output = sink_a->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
-
+
frames_output = sink_b->get_data().size();
CPPUNIT_ASSERT_EQUAL (frames, frames_output);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink_b->get_array(), frames));
}
-
+
void testRemoveOutput()
{
vertex.reset (new IdentityVertex<float>());
vertex->add_output (sink_a);
vertex->add_output (sink_b);
-
+
ProcessContext<float> c (random_data, frames, 1);
vertex->process (c);
-
+
vertex->remove_output (sink_a);
ProcessContext<float> zc (zero_data, frames, 1);
vertex->process (zc);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals (zero_data, sink_b->get_array(), frames));
}
-
+
void testClearOutputs()
{
vertex.reset (new IdentityVertex<float>());
vertex->add_output (sink_a);
vertex->add_output (sink_b);
-
+
ProcessContext<float> c (random_data, frames, 1);
vertex->process (c);
-
+
vertex->clear_outputs ();
ProcessContext<float> zc (zero_data, frames, 1);
vertex->process (zc);
-
+
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink_a->get_array(), frames));
CPPUNIT_ASSERT (TestUtils::array_equals (random_data, sink_b->get_array(), frames));
}
pthread_mutex_lock (&_process_callback_mutex);
/* Freewheelin' */
-
+
// clear input buffers
for (std::vector<ASIOBackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
pthread_mutex_lock (&_process_callback_mutex);
/* Freewheelin' */
-
+
// clear input buffers
for (std::vector<CoreBackendPort*>::const_iterator it = _system_inputs.begin (); it != _system_inputs.end (); ++it) {
memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample));
if (all_devices.find (_target_driver) == all_devices.end()) {
all_devices.insert (make_pair (_target_driver, std::set<string>()));
}
-
+
/* store every device we've found, by driver name.
*
* This is so we do not confuse ALSA, FFADO, netjack etc. devices
for (vector<string>::const_iterator d = currently_available.begin(); d != currently_available.end(); ++d) {
all.insert (*d);
}
-
+
for (DeviceList::const_iterator d = all.begin(); d != all.end(); ++d) {
if (find (currently_available.begin(), currently_available.end(), *d) == currently_available.end()) {
statuses.push_back (DeviceStatus (*d, false));
statuses.push_back (DeviceStatus (*d, false));
}
}
-
+
return statuses;
}
JACKAudioBackend::available_sample_rates (const string& device) const
{
vector<float> f;
-
+
if (device == _target_device && available()) {
f.push_back (sample_rate());
return f;
f.push_back (96000.0);
f.push_back (192000.0);
f.push_back (384000.0);
-
+
return f;
}
JACKAudioBackend::available_buffer_sizes (const string& device) const
{
vector<uint32_t> s;
-
+
if (device == _target_device && available()) {
s.push_back (buffer_size());
return s;
}
_target_input_channels = cnt;
-
+
return 0;
}
}
options.realtime = true;
options.ports_max = 2048;
-
+
ARDOUR::set_midi_option (options, _target_midi_option);
/* this must always be true for any server instance we start ourselves
return -1;
}
}
-
+
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
/* get the buffer size and sample rates established */
jack_sample_rate_callback (jack_get_sample_rate (_priv_jack));
jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
-
+
/* Now that we have buffer size and sample rate established, the engine
can go ahead and do its stuff
*/
if (!jack_port_type_get_buffer_size) {
warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
}
-
+
set_jack_callbacks ();
-
+
if (jack_activate (_priv_jack) == 0) {
_running = true;
} else {
{
_running = false; // no 'engine halted message'.
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
+
_jack_connection->close ();
_current_buffer_size = 0;
if (onoff == _freewheeling) {
/* already doing what has been asked for */
-
+
return 0;
}
GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
pframes_t nframes = jack_cycle_wait (_priv_jack);
-
+
if (engine.process_callback (nframes)) {
return 0;
}
}
}
}
-
+
jack_free (ports);
}
if (_target_driver.empty() || _target_device.empty()) {
return appname;
}
-
+
if (_target_driver == "ALSA") {
-
+
if (_target_device == "Hammerfall DSP") {
appname = "hdspconf";
} else if (_target_device == "M Audio Delta 1010") {
JACKAudioBackend* engine;
boost::function<void()> f;
size_t stacksize;
-
+
ThreadData (JACKAudioBackend* e, boost::function<void()> fp, size_t stacksz)
: engine (e) , f (fp) , stacksize (stacksz) {}
};
{
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
- if (_priv_jack) {
+ if (_priv_jack) {
int ret = jack_client_close (_priv_jack);
_jack = 0;
ardour_port_flags_to_jack_flags (PortFlags flags)
{
uint32_t jack_flags = 0;
-
+
if (flags & IsInput) {
jack_flags |= JackPortIsInput;
}
jack_port_t* port = (jack_port_t*) p;
const char** ports;
-
+
if (process_callback_safe) {
ports = jack_port_get_connections ((jack_port_t*)port);
} else {
}
jack_free (ports);
-
+
return s.size();
}
JACKAudioBackend::connect (const std::string& src, const std::string& dst)
{
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
+
int r = jack_connect (_priv_jack, src.c_str(), dst.c_str());
return r;
}
JACKAudioBackend::set_latency_range (PortHandle port, bool for_playback, LatencyRange r)
{
jack_latency_range_t range;
-
+
range.min = r.min;
range.max = r.max;
{
jack_latency_range_t range;
LatencyRange ret;
-
+
jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
ret.min = range.min;
*/
jack_client_t* jack_client = (jack_client_t*) AudioEngine::instance()->port_engine().private_handle();
-
+
if (jack_client) {
jack_session_reply (jack_client, event);
}
/* BBT info */
TempoMetric metric (tempo_map.metric_at (tf));
-
+
try {
tempo_map.bbt_time_rt (tf, bbt);
-
+
pos->bar = bbt.bars;
pos->beat = bbt.beats;
pos->tick = bbt.ticks;
-
+
// XXX still need to set bar_start_tick
-
+
pos->beats_per_bar = metric.meter().divisions_per_bar();
pos->beat_type = metric.meter().note_divisor();
pos->ticks_per_beat = Timecode::BBT_Time::ticks_per_beat;
pos->beats_per_minute = metric.tempo().beats_per_minute();
-
+
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
-
+
} catch (...) {
/* no message */
}
MMRESULT rslt;
lpMidiHdr->dwBytesRecorded = 0;
lpMidiHdr->dwFlags = 0;
-
+
/* note: no error checking -- can this actually fail? */
rslt = midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR));
assert(rslt == MMSYSERR_NOERROR);
if ( !engine.thread_initialised_for_audio_processing () ) {
std::cerr << "\tWavesAudioBackend::_audio_device_callback (): It's an attempt to call process callback from the thread which didn't initialize it " << std::endl;
-
+
AudioEngine::thread_init_callback (this);
}
_midi_device_manager.stop ();
_unregister_system_audio_ports ();
_unregister_system_midi_ports ();
-
+
return retVal;
}
{
_pm_input_id = _pm_output_id = pmNoDevice;
int count = Pm_CountDevices ();
-
+
for (int i = 0; i < count; i++) {
-
+
const PmDeviceInfo* pm_device_info = Pm_GetDeviceInfo (i);
-
+
if (pm_device_info == NULL) {
continue;
}
if (is_input () ) {
// COMMENTED DBG LOGS */ std::cout << "WavesMidiDevice::open (): INPUT" << _pm_input_id << "-[" << name () << "]" << std::endl;
-
+
if (!_input_pm_stream) {
// create queue
if (!_input_queue) {
_input_queue = NULL;
}
- // output
+ // output
if ( output_pm_stream ) {
// close stream
PmError err = Pm_Close (output_pm_stream);
#ifndef __WCFourCC_h__
#define __WCFourCC_h__
-
+
/* Copy to include
#include "BasicTypes/WCFourCC.h"
*/
#define kDefaultFourCC WCFourCC::kDefaultFourCC_prv()
static const WCFourCC kZeroFourCC(0, wvNS::wvBO::compiler_byte_order);
-
+
#endif //#if !defined(__WCFourCC_h__)
#endif
namespace wvNS {
-
+
namespace wvBO // namespace Waves::ByteOrder
{
typedef int byte_order_type; // we use int rather than enum because some compilers cannot resolve enum constants at compile-time. There are only two options anyway :-)
#ifndef __WUComPtr_h__
#define __WUComPtr_h__
-
+
/* Copy to include
#include "BasicTypes/WUComPtr.h"
*/
//================================================================================
inline uint32_t vfpConvertDPtr(const void* InPointer, void* pData)
//================================================================================
-{
+{
uint64_t *pL = (uint64_t *)pData;
*pL = (uint64_t)InPointer;
return (uint32_t)sizeof(uint64_t);
// #ifdef for x32 - intptr_t is 32 bit
// retVal.LSW = int32_t(in_PtrToPack);
// retVal.MSW = 0;
-
+
return retVal;
}
// and unpack it to intptr_t type
{
intptr_t retVal;
-
+
// This unpacking is xPlatform coding for x32 and x64
// #ifdef for x64 - intptr_t is 64 bit so use intptr_t instead of int64_t
int64_t PtrAt64 = static_cast<int64_t>(in_ComPtrToUnpack.MSW);
#ifndef __WUMathConsts_h__
#define __WUMathConsts_h__
-
+
/* Copy to include:
#include "BasicTypes/WUMathConsts.h"
*/
//********************************************************************************
// Files
-//! file (and resource container) opening permissions
+//! file (and resource container) opening permissions
// Note: When opening with eFMWriteOnly on existing file, writing to the file will append, not overwrite, Shai, 9/8/2007.
enum WEPermitions{ eFMReadOnly, eFMWriteOnly, eFMReadWrite};
eWavesPreferencesFolder2, // Mac: "/Users/username/Library/Preferences/Waves Audio"
// Win: "C:\Users\username\AppData\Roaming\Waves Audio\Preferences"
-
+
eNumberOfSystemFolders
};
template<class T> inline T WUMin(const T &a, const T &b) {return (a < b) ? a : b;} // requires only < to be defined for T
template<class T> inline T WUMax(const T &a,const T &b) {return (a < b) ? b : a;} // requires only < to be defined for T
template<class T> inline T WUMinMax(const T &Smallest, const T &Biggest, const T &Val) // requires only < to be defined for T
-{
+{
return ((Val < Smallest) ? Smallest : ((Biggest < Val) ? Biggest : Val));
}
-/*
+/*
// Min and Max
template<class T> inline T WUMin(T a,T b) {return (a < b) ? a : b;} // requires only < to be defined for T
template<class T> inline T WUMax(T a,T b) {return (a < b) ? b : a;} // requires only < to be defined for T
{
return ((X < SMALLEST) ? SMALLEST : ((BIGGEST < X) ? BIGGEST : X));
}
- */
+ */
// Absolute value
#ifdef PLATFORM_WINDOWS
void UMicrosecondsAccumulator::Stop()
{
UMicroseconds stop_time;
-
+
m_accumulator += stop_time.GetNativeTime() - m_start_time.GetNativeTime();
}
m_accumulator += inaccum_to_add.GetAccumulatedTime();
return *this;
}
-
+
} // namespace wvNS {
#ifndef __UMicroseconds_h__
#define __UMicroseconds_h__
-
+
/* Copy to include
#include "UMicroseconds.h"
*/
{
public:
UMicrosecondsAccumulator() : m_start_time(0), m_accumulator(0) {}
-
+
void Start();
void Stop();
void Clear();
-
+
UMicroseconds GetAccumulatedTime() const;
-
+
UMicrosecondsAccumulator& operator+=(const UMicrosecondsAccumulator&);
-
+
protected:
UMicroseconds m_start_time;
UMicroseconds m_accumulator;
now.ReadTime();
} while ((now.MicroSeconds() - than.MicroSeconds()) < amt);
}
-
+
} // namespace wvNS {
#endif //#ifndef __UMicroseconds_h__
typedef intptr_t spos_t; // signed position, defined to intptr_t because Windows does not have ssize_t
static const pos_t npos = UINTPTR_MAX; // Same as size_max
- WCFixedStringBase(char* const in_begin, const size_t in_MaxFixedStringLength) :
+ WCFixedStringBase(char* const in_begin, const size_t in_MaxFixedStringLength) :
m_begin(in_begin),
m_MaxFixedStringLength(in_MaxFixedStringLength),
m_end(in_begin)
#endif
#ifdef __APPLE__
std::snprintf(buf, tempBufSize, "%.*f", in_precision, in_double);
- #endif
- #ifdef __linux__
+ #endif
+ #ifdef __linux__
snprintf(buf, tempBufSize, "%.*f", in_precision, in_double);
- #endif
+ #endif
operator<<(buf);
}
// WCFixedStringBase& operator<<(const unsigned char in_uint) {
// return operator<<(static_cast<const unsigned long long>(in_uint));
// }
-//
+//
// WCFixedStringBase& operator<<(const size_t in_uint) {
// return operator<<(static_cast<const uint64_t>(in_uint));
// }
-//
+//
#if defined(__APPLE__) || defined(PLATFORM_WINDOWS) || defined(__linux__) // both 32 & 64 bit
WCFixedStringBase& operator<<(const unsigned int in_uint) {
return operator<<(static_cast<uint64_t>(in_uint));
}
#endif
-//
+//
#if defined(PLATFORM_WINDOWS) || defined(__linux__) // both 32 & 64 bit
WCFixedStringBase& operator<<(const unsigned long in_uint) {
return operator<<(static_cast<uint64_t>(in_uint));
ptrdiff_t compare(const WCFixedStringBase& in_to_compare) const
{
- ptrdiff_t retVal = compare(in_to_compare.c_str());
+ ptrdiff_t retVal = compare(in_to_compare.c_str());
return retVal;
}
ptrdiff_t case_insensitive_compare(const WCFixedStringBase& in_to_compare) const
{
- ptrdiff_t retVal = case_insensitive_compare(in_to_compare.c_str());
+ ptrdiff_t retVal = case_insensitive_compare(in_to_compare.c_str());
return retVal;
}
bool retVal = (0 == where) || (0 == ::strlen(in_begin_text));
return retVal;
}
-
+
// return true if in_end_text is found at th end OR if in_end_text is empty
bool ends_with(const char* in_end_text) const
{
}
}
-protected:
+protected:
~WCFixedStringBase() {}
char* const m_begin;
return retVal;
}
-protected:
+protected:
char m_fixedString[kMaxFixedStringLength + 1]; // the "+ 1" is so that *m_end is always valid, and we can put the '\0' there};
};
-inline bool operator==(const WCFixedStringBase& in_left, const WCFixedStringBase& in_right)
+inline bool operator==(const WCFixedStringBase& in_left, const WCFixedStringBase& in_right)
{
return 0 == in_left.compare(in_right.c_str());
}
return 0 == in_left.compare(in_right);
}
-inline bool operator!=(const WCFixedStringBase& in_left, const WCFixedStringBase& in_right)
+inline bool operator!=(const WCFixedStringBase& in_left, const WCFixedStringBase& in_right)
{
return 0 != in_left.compare(in_right.c_str());
}
class WCFixedStringPair : public std::pair< WCFixedString<kSizeOfFirst>, WCFixedString<kSizeOfSecond> >
{
public:
- WCFixedStringPair(const char* const in_firstStr = 0, const char* const in_secondStr = 0) :
+ WCFixedStringPair(const char* const in_firstStr = 0, const char* const in_secondStr = 0) :
std::pair< WCFixedString<kSizeOfFirst>, WCFixedString<kSizeOfSecond> >(in_firstStr, in_secondStr) {}
- WCFixedStringPair(const WCFixedStringBase& in_firstStr, const char* const in_secondStr = 0) :
+ WCFixedStringPair(const WCFixedStringBase& in_firstStr, const char* const in_secondStr = 0) :
std::pair< WCFixedString<kSizeOfFirst>, WCFixedString<kSizeOfSecond> >(in_firstStr, in_secondStr) {}
- WCFixedStringPair(const WCFixedStringBase& in_firstStr, const WCFixedStringBase& in_secondStr) :
+ WCFixedStringPair(const WCFixedStringBase& in_firstStr, const WCFixedStringBase& in_secondStr) :
std::pair< WCFixedString<kSizeOfFirst>, WCFixedString<kSizeOfSecond> >(in_firstStr, in_secondStr) {}
};
const WTErr eIPC_OpenPipeFailed = -14208;
const WTErr eIPC_SendMsgFailed = -14209;
const WTErr eIPC_SendCommandInvalid = -14210;
-const WTErr eIPC_QtTestMode = -14211;
-const WTErr eIPC_ChangePermissionOnPipe = -14212;
-const WTErr eIPC_ConnectionLost = -14213;
+const WTErr eIPC_QtTestMode = -14211;
+const WTErr eIPC_ChangePermissionOnPipe = -14212;
+const WTErr eIPC_ConnectionLost = -14213;
-const WTErr eIPC_InvalidRole = -14213;
+const WTErr eIPC_InvalidRole = -14213;
const WTErr eIPC_CreateNamedPipeM2SFailed = -14214;
const WTErr eIPC_CreateNamedPipeS2MFailed = -14215;
-const WTErr eIPC_ChangePermissionOnPipeM2S = -14216;
-const WTErr eIPC_ChangePermissionOnPipeS2M = -14217;
-const WTErr eIPC_OpenReadPipeFailed = -14218;
-const WTErr eIPC_OpenReadPipeDIsableSigPipe = -14219;
-const WTErr eIPC_OpenWritePipeFailed = -14220;
-const WTErr eIPC_WritePipeFailed = -14221;
-const WTErr eIPC_WritePipeNotOpen = -14222;
-const WTErr eIPC_WriteBufferResizeFailed = -14223;
-const WTErr eIPC_NotConnectedSendMsgFailed = -14224;
-const WTErr eIPC_OpenWritePipeWorkerStoping = -14225;
-const WTErr eIPC_SoketSendFailed = -14226;
-const WTErr eIPC_PtonFailed = -14227;
-const WTErr eIPC_SocketFailed = -14228;
-const WTErr eIPC_BindFailed = -14229;
-const WTErr eIPC_ListenFailed = -14230;
-const WTErr eIPC_ConnectFailed = -14231;
+const WTErr eIPC_ChangePermissionOnPipeM2S = -14216;
+const WTErr eIPC_ChangePermissionOnPipeS2M = -14217;
+const WTErr eIPC_OpenReadPipeFailed = -14218;
+const WTErr eIPC_OpenReadPipeDIsableSigPipe = -14219;
+const WTErr eIPC_OpenWritePipeFailed = -14220;
+const WTErr eIPC_WritePipeFailed = -14221;
+const WTErr eIPC_WritePipeNotOpen = -14222;
+const WTErr eIPC_WriteBufferResizeFailed = -14223;
+const WTErr eIPC_NotConnectedSendMsgFailed = -14224;
+const WTErr eIPC_OpenWritePipeWorkerStoping = -14225;
+const WTErr eIPC_SoketSendFailed = -14226;
+const WTErr eIPC_PtonFailed = -14227;
+const WTErr eIPC_SocketFailed = -14228;
+const WTErr eIPC_BindFailed = -14229;
+const WTErr eIPC_ListenFailed = -14230;
+const WTErr eIPC_ConnectFailed = -14231;
const WTErr eIPC_WsaStartupFailed = -14232;
const WTErr eIPC_UdpSocketCreateFailed = -14233;
const WTErr eIPC_UdpSocketConnectFailed = -14234;
const WTErr eIPC_UdpSocketBinFailed = -14235;
-const WTErr eIPC_SetBufferPreambleFailed = -14226;
+const WTErr eIPC_SetBufferPreambleFailed = -14226;
// Database errors
const WTErr eDB_BatchRollback = -15501;
#ifndef __safe_delete_h__
#define __safe_delete_h__
-
+
/* Copy to include:
#include "safe_delete.h"
void obtain();
bool tryobtain();
void release();
-
+
private:
ThreadMutexInited(const ThreadMutexInited&); // cannot be copied
ThreadMutexInited& operator=(const ThreadMutexInited&); // cannot be copied
public:
ThreadMutex() {init();}
};
-
+
//--------------------------------------------------------
class DllExport ThreadConditionSignal : public noncopyableobject
{
#if ! defined(__STDC_LIMIT_MACROS)
#define __STDC_LIMIT_MACROS
#endif
-
+
#include <stddef.h>
#include </usr/include/stdint.h>
#endif
null_type(const null_type *) {} // this allows 0 to be implicitly converted to null_type
};
inline null_type null() { return null_type(); }
-
+
// This is a byte, guaranteed to be unsigned regardless of your compiler's char signedness
typedef uint8_t byte_type;
AKUPARA_SIGNED_UNSIGNED_INTEGER_PAIR(1, char )
AKUPARA_SIGNED_UNSIGNED_INTEGER_PAIR(2, short )
AKUPARA_SIGNED_UNSIGNED_INTEGER_PAIR(3, int )
-
+
//AKUPARA_SIGNED_UNSIGNED_INTEGER_PAIR(4, int32_t )// 64BitConversion
template<>
struct
public:
pad_to_cache_line() {}
template<typename _arg_type> pad_to_cache_line(_arg_type arg) : base_type(arg) {}
- };
+ };
//---------------------------------------------------------------------
} // namespace atomic
namespace machine
{
const unsigned int k_bytes_per_cache_line = 64; // this is true for P4 & K8
-
+
// Flags for operations supported by this machine
//-------------------------------------
template<> struct implements_add <4> : public true_type {};
template<> struct implements_fetch_and_add<4> : public true_type {};
//-------------------------------------
-
+
// CAS
return fetch_and_add(operand_address, -subtrahend);
}
//--------------------------------------------------------------------------------
-
-
+
+
// Memory barriers
//--------------------------------------------------------------------------------
inline void memory_barrier_readwrite()
const std::string& WCMRAudioDevice::DeviceName () const
{
return (m_DeviceName);
-
+
}
const std::vector<std::string>& WCMRAudioDevice::InputChannels ()
{
return (m_InputChannels);
-
+
}
WCMRAudioDevice::ConnectionStates WCMRAudioDevice::ConnectionStatus ()
{
return (m_ConnectionStatus);
-
+
}
bool WCMRAudioDevice::Active ()
{
return (m_IsActive);
-
+
}
if (newState) {
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
}
-
+
//This will most likely be overridden, the base class simply
//changes the member.
m_IsStreaming = newState;
bool wasActive = Active();
WTErr err = SetStreaming(false);
-
+
if (err == eNoErr)
err = SetActive(false);
{
if (pLeftChannel)
*pLeftChannel = m_LeftMonitorChannel;
- if (pRightChannel)
+ if (pRightChannel)
*pRightChannel = m_RightMonitorChannel;
- if (pGain)
+ if (pGain)
*pGain = m_MonitorGain;
- return;
+ return;
}
{
if (m_pTheClient)
m_pTheClient->AudioDeviceManagerNotification (forReason, pParam);
- return;
+ return;
}
virtual bool Active();///<Active status - mainly significant for ASIO, as certain ops can only be performed on active devices!
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
-
+
virtual bool Streaming();///<Streaming Status?
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr ResetDevice ();
virtual bool IsProcessActive();
-
+
virtual WTErr DoIdle();///<Do Idle Processing
-
+
virtual const std::vector<float>& InputLevels();///<Retrieve Input Levels (for VU display)?
-
+
virtual const std::vector<float>& OutputLevels();///<Retrieve Output Levels (for VU display)?
void GetMonitorInfo (int *pLeftChannel = NULL, int *pRightChannel = NULL, float *pGain = NULL);///<Retrieve current monitor channel pair and gain - optional, will not be available with AG
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
+
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
virtual WTErr SendCustomCommand (int customCommand, void *pCommandParam); ///< Send a custom command to the audiodevice...
protected:
WCMRAudioDeviceManager *m_pMyManager; ///< The manager who's managing this device, can be used for sending notifications!
-
+
std::string m_DeviceName; ///< Name of the device.
std::vector<std::string> m_InputChannels; ///< List of input channel names.
std::vector<std::string> m_OutputChannels; ///< List of output channel names.
std::vector<int> m_SamplingRates; ///< List of available sampling rates.
std::vector<int> m_BufferSizes; ///< List of available buffer sizes.
-
+
int m_CurrentSamplingRate; ///< Currently selected sampling rate.
int m_CurrentBufferSize; ///< Currently selected buffer size.
bool m_IsStreaming; ///< Flag for streaming status.
std::vector<float> m_InputLevels; ///< List of input levels.
std::vector<float> m_OutputLevels; ///< List of output levels.
-
+
int m_LeftMonitorChannel; ///< The device channel to use for monitoring left channel data.
int m_RightMonitorChannel; ///< The device channel to use for monitoring right channel data.
float m_MonitorGain; ///< Amount of gain to apply for monitoring signal.
mutable wvNS::wvThread::ThreadMutex m_AudioDeviceInfoVecMutex; // mutex to lock device info list
DeviceInfoVec m_DeviceInfoVec;
-
+
eAudioDeviceFilter m_eAudioDeviceFilter;
WCMRAudioDevice* m_CurrentDevice;
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr DoIdle();///<Do Idle Processing
-
+
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
+
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
virtual int AudioCallback (float *pOutputBuffer, unsigned long framesPerBuffer, int64_t inSampleTime, uint64_t inCycleStartTime);
-
+
AudioDeviceID DeviceID () {return m_DeviceID;}
virtual uint32_t GetLatency (bool isInput); ///< Get latency.
// int m_CurrentIOCycle; ///< The location in m_IOCyclesTymesTaken array, where the next cycle's value will go.
// int m_CyclesToAccumulate; ///< The number of cycles to accumulate the values for - maximum for last one second.
// unsigned int m_CyclePeriod; ///< The number of host time units for a cycle period - determined by buffer size and sampling rate
-
+
AudioUnit m_AUHALAudioUnit;///< The AUHAL AudioUnit
uint32_t m_ToneDataSamples;
uint32_t m_NextSampleToUse;
#endif //WV_USE_TONE_GEN
-
+
WTErr UpdateDeviceInfo ();
WTErr UpdateDeviceId ();
WTErr UpdateDeviceName();
#if WV_USE_TONE_GEN
void SetupToneGenerator ();
#endif //WV_USE_TONE_GEN
-
+
static OSStatus StaticAudioIOProc(void *inRefCon, AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData);
OSStatus AudioIOProc(AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData);
-
+
static OSStatus StaticPropertyChangeProc (AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput,
AudioDevicePropertyID inPropertyID, void *inClientData);
void PropertyChangeProc (AudioDevicePropertyID inPropertyID);
bool m_UseMultithreading; ///< Flag indicates whether to use multi-threading for audio processing.
bool m_bNoCopyAudioBuffer;
-
+
private:
// helper functions for this class only
WTErr getDeviceAvailableSampleRates(DeviceID deviceId, std::vector<int>& sampleRates);
//same size, nothing to do.
if (oldSize == newSize)
return eNoErr;
-
+
//see if this is one of our supported rates...
std::vector<int>::iterator intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
if (intIter == m_BufferSizes.end())
//Can't change, perhaps use an "invalid param" type of error
return eCommandLineParameter;
}
-
+
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
return eGenericErr;
}
-
+
return WCMRAudioDevice::SetCurrentBufferSize(newSize);
}
// VERY ROUGH IMPLEMENTATION:
while(Streaming()) {
-
+
uint64_t cycleEndTimeNanos = audioCallbackData.acdCycleStartTimeNanos + cyclePeriodNanos;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::AudioCallback, (void *)&audioCallbackData);
-
+
audioCallbackData.acdSampleTime += buffer_size;
-
+
int64_t timeToSleepUsecs = ((int64_t)cycleEndTimeNanos - (int64_t)__get_time_nanos())/1000;
-
+
if (timeToSleepUsecs > 0) {
_usleep (timeToSleepUsecs);
}
{
32, 64, 96, 128, 192, 256, 512, 1024, 2048
};
-
+
///< The default SR.
static const int DEFAULT_SR = 44100;
///< Number of stalls to wait before notifying user...
static const int NUM_STALLS_FOR_NOTIFICATION = 100; // 100 corresponds to 100 x 42 ms idle timer - about 4 seconds.
static const int CHANGE_CHECK_COUNTER_PERIOD = 100; // 120 corresponds to 120 x 42 ms idle timer - about 4 seconds.
-
+
#define HUNDRED_NANO_TO_MILLI_CONSTANT 10000
#define CONSUMPTION_CALCULATION_INTERVAL 500 // Milli Seconds
}
else
std::cout << "API::Device " << m_DeviceName << " Device does not support any sample rate of ours" << std::endl;
-
+
//should use a valid current buffer size
if (m_BufferSizes.size())
{
m_CurrentBufferSize = m_BufferSizes[0];
}
}
-
+
//build our input/output level lists
for (unsigned int currentChannel = 0; currentChannel < m_InputChannels.size(); currentChannel++)
{
{
stopStreaming();
}
-
+
//If device is active (meaning stream is open) we need to close it.
if (Active())
{
WTErr WCMRPortAudioDevice::UpdateDeviceInfo ()
{
std::cout << "API::Device (ID:)" << m_DeviceID << " Updating device info" << std::endl;
-
+
SignalObjectAndWait(m_hUpdateDeviceInfoRequestedEvent, m_hUpdateDeviceInfoDone, INFINITE, false);
return eNoErr;
//get device info
const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
-
+
//update name.
m_DeviceName = pDeviceInfo->name;
////////////////////////////////////////////////////////////////////////////////////
//update list of supported SRs...
m_SamplingRates.clear();
-
+
// now iterate through our standard SRs and check if they are supported by device
// store them for this device
for(int sr=0; gAllSampleRates[sr] > 0; sr++)
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
long minSize, maxSize, preferredSize, granularity;
PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
-
+
if (err == paNoError)
{
std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
-
+
m_BufferSizes.push_back (preferredSize);
useDefaultBuffers = false;
}
{
std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
}
-
+
if (useDefaultBuffers)
{
std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
m_InputChannels.push_back (chNameStream.str());
}
-
-
+
+
//Update output channels
m_OutputChannels.clear();
for (int channel = 0; channel < maxOutputChannels; channel++)
{
const char* channelName[32]; // 32 is max leth declared by PortAudio for this operation
std::stringstream chNameStream;
-
+
PaError error = PaAsio_GetOutputChannelName(m_DeviceID, channel, channelName);
-
+
chNameStream << (channel+1) << " - ";
if (error == paNoError)
{
chNameStream << "Output " << (channel+1);
}
-
+
m_OutputChannels.push_back (chNameStream.str());
}
}
pOutS = &outputParameters;
PaStream *portAudioStream = NULL;
-
+
//sometimes devices change buffer size if sample rate changes
//it updates buffer size during stream opening
//we need to find out how device would behave with current sample rate
//try opening test stream to load device driver for current sample rate and buffer size
paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
-
+
if (portAudioStream)
{
// close test stream
{
AUTO_FUNC_DEBUG;
//ToDo: Perhaps for ASIO devices that are active, we should retrive the SR from the device...
-
+
return (m_CurrentSamplingRate);
}
WTErr WCMRPortAudioDevice::ResetDevice()
{
std::cout << "API::Device: " << m_DeviceName << " Reseting device" << std::endl;
-
+
SignalObjectAndWait(m_hResetRequestedEvent, m_hResetDone, INFINITE, false);
if (ConnectionStatus() == DeviceErrors)
//changes the status.
int oldRate = CurrentSamplingRate();
bool oldActive = Active();
-
+
//no change, nothing to do
if (oldRate == newRate)
return (retVal);
retVal = eCommandLineParameter;
return (retVal);
}
-
+
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
return (retVal);
}
-
+
//make the change...
m_CurrentSamplingRate = newRate;
PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
retVal = eWrongObjectState;
}
-
+
return (retVal);
}
AUTO_FUNC_DEBUG;
//ToDo: May want to do something more to extract the actual status!
return (m_ConnectionStatus);
-
+
}
AUTO_FUNC_DEBUG;
PaError paErr = paNoError;
-
+
// if device is not active activate it
if (!Active() )
{
paDitherOff,
WCMRPortAudioDevice::TheCallback,
this);
-
+
if(paErr != paNoError)
{
std::cout << "Cannot open streamm with buffer: "<< m_CurrentBufferSize << " Error: " << Pa_GetErrorText (paErr) << std::endl;
-
+
if (paErr == paUnanticipatedHostError)
std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
}
m_lastErr = eAsioFailed;
}
-
+
}
std::cout << "Activation is DONE "<< std::endl;
AUTO_FUNC_DEBUG;
PaError paErr = paNoError;
-
+
if (Active() )
{
if (Streaming())
{
stopStreaming ();
}
-
+
if (m_PortAudioStream)
{
//close the stream first
m_SampleCounter = 0;
std::cout << "API::Device" << m_DeviceName << " Starting device stream" << std::endl;
-
+
//get device info
const PaDeviceInfo *pDeviceInfo = Pa_GetDeviceInfo(m_DeviceID);
-
+
unsigned int inChannelCount = pDeviceInfo->maxInputChannels;
unsigned int outChannelCount = pDeviceInfo->maxOutputChannels;
-
+
// Prepare for streaming - tell Engine to do the initialization for process callback
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
m_lastErr = eGenericErr;
}
}
-
+
if (callerIsWaiting)
SetEvent(m_hStartStreamingDone);
}
// Reinitialize PA
Pa_Terminate();
Pa_Initialize();
-
+
std::cout << "Updating device state... " << std::endl;
// update device info
updateDeviceInfo();
};
const size_t hEventsSize = sizeof(hEvents)/sizeof(hEvents[0]);
-
+
initDevice();
for(;;)
AUTO_FUNC_DEBUG;
//This will most likely be overridden, the base class simply
//changes the member.
-
+
m_MonitorGain = newGain;
return (eNoErr);
}
{
AUTO_FUNC_DEBUG;
WTErr retVal = eNoErr;
-
+
if (Active() && !m_ResetRequested )
{
#ifdef PLATFORM_WINDOWS
// show control panel for the device
if (PaAsio_ShowControlPanel (m_DeviceID, pParam) != paNoError)
retVal = eGenericErr;
-
+
// restore previous state for the device
SetActive(true);
if (wasStreaming)
}
#else
pParam = pParam;
-#endif //_windows
+#endif //_windows
}
-
+
return (retVal);
}
(statusFlags & (paInputOverflow | paOutputUnderflow)) != 0);
else
return (true);
-
+
}
//Don't try to access after this call returns!
m_pInputData = NULL;
- m_SampleCounter += framesPerBuffer;
+ m_SampleCounter += framesPerBuffer;
return m_StopRequested;
}
{
AUTO_FUNC_DEBUG;
std::cout << "API::PortAudioDeviceManager::PA Device manager constructor" << std::endl;
-
+
//Always create the None device first...
m_NoneDevice = new WCMRNativeAudioNoneDevice(this);
WCMRPortAudioDeviceManager::~WCMRPortAudioDeviceManager()
{
AUTO_FUNC_DEBUG;
-
+
std::cout << "API::Destroying PortAudioDeviceManager " << std::endl;
try
{
std::cout << "API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName << std::endl;
TRACE_MSG ("API::PortAudioDeviceManager::Creating PA device: " << devInfo.m_DeviceId << ", Device Name: " << devInfo.m_DeviceName);
-
+
m_CurrentDevice = new WCMRPortAudioDevice (this, devInfo.m_DeviceId, m_UseMultithreading, m_bNoCopyAudioBuffer);
}
catch (...)
WTErr WCMRPortAudioDeviceManager::getDeviceAvailableBufferSizes(DeviceID deviceId, std::vector<int>& buffers)
{
WTErr retVal = eNoErr;
-
+
buffers.clear();
//make PA request to get actual device buffer sizes
WTErr WCMRPortAudioDeviceManager::generateDeviceListImpl()
{
std::cout << "API::PortAudioDeviceManager::Generating device list" << std::endl;
-
+
WTErr retVal = eNoErr;
//Initialize PortAudio and ASIO first
{
//if it's of the required type...
const PaDeviceInfo *pPaDeviceInfo = Pa_GetDeviceInfo(thisDeviceID);
-
+
if (Pa_GetHostApiInfo(pPaDeviceInfo->hostApi)->type == paASIO)
{
//build a device object...
WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const
{
WTErr retVal = eNoErr;
-
+
buffers.clear();
//first check if the request has been made for None device
buffers=m_NoneDevice->BufferSizes();
return retVal;
}
-
+
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
buffers=m_CurrentDevice->BufferSizes();
virtual ConnectionStates ConnectionStatus();///< Connection Status - device available, gone, disconnected
virtual WTErr SetActive (bool newState);///<Prepare/Activate device.
-
+
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr SetMonitorChannels (int leftChannel, int rightChannel);///<Set monitor channels. - optional, will not be available with AG
virtual WTErr SetMonitorGain (float newGain);///<Set monitor gain. - optional, will not be available with AG
-
+
virtual WTErr ShowConfigPanel (void *pParam);///< Show Control Panel - in case of ASIO this will work only with Active device!
virtual int AudioCallback (const float *pInputBuffer, float *pOutputBuffer, unsigned long framesPerBuffe, bool dropsDetectedr);
static long StaticASIOMessageHook (void *pRefCon, long selector, long value, void* message, double* opt);
long ASIOMessageHook (long selector, long value, void* message, double* opt);
#endif //PLATFORM_WINDOWS
-
+
protected:
static DWORD WINAPI __DoIdle__(LPVOID lpThreadParameter);
PaError testStateValidness(int sampleRate, int bufferSize);
///////////////////////////////////////////////////////////
-
+
static int TheCallback (const void *pInputBuffer, void *pOutputBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* /*pTimeInfo*/, PaStreamCallbackFlags /*statusFlags*/, void *pUserData );
public:
WCMRPortAudioDeviceManager(WCMRAudioDeviceManagerClient *pTheClient, eAudioDeviceFilter eCurAudioDeviceFilter,
bool useMultithreading = true, bool bNocopy = false); ///< constructor
-
+
virtual ~WCMRPortAudioDeviceManager(void); ///< destructor
protected:
/* this could be smaller in the case of small _arc values
but I can't be bothered to optimize it.
*/
-
+
bbox.x0 = _center.x - _radius;
bbox.y0 = _center.y - _radius;
bbox.x1 = _center.x + _radius;
if (_radius <= 0.0 || _arc_degrees <= 0.0) {
return;
}
-
+
Duple c = item_to_window (Duple (_center.x, _center.y));
context->arc (c.x, c.y, _radius, _start_degrees * (M_PI/180.0), _arc_degrees * (M_PI/180.0));
Arc::set_radius (Coord r)
{
begin_change ();
-
+
_radius = r;
_bounding_box_dirty = true;
end_change ();
-}
+}
void
Arc::set_arc (double deg)
{
begin_change ();
-
+
_arc_degrees = deg;
_bounding_box_dirty = true;
end_change ();
-}
+}
void
Arc::set_start (double deg)
{
begin_change ();
-
+
_start_degrees = deg;
-
+
_bounding_box_dirty = true;
end_change ();
-}
+}
bool
Arc::covers (Duple const & point) const
double angle_degs = atan (p.y/p.x) * 2.0 * M_PI;
double radius = sqrt (p.x * p.x + p.y * p.y);
-
+
return (angle_degs >= _start_degrees) &&
(angle_degs <= (_start_degrees + _arc_degrees)) &&
(radius < _radius);
setup_polygon (i);
CANVAS_DEBUG_NAME (_heads[i].polygon, string_compose ("arrow head %1", i));
}
-
+
_line = new Line (this);
CANVAS_DEBUG_NAME (_line, "arrow line");
}
Arrow::set_show_head (int which, bool show)
{
assert (which == 0 || which == 1);
-
+
begin_change ();
-
+
if (!show) {
delete _heads[which].polygon;
_heads[which].polygon = 0;
Arrow::set_head_outward (int which, bool outward)
{
assert (which == 0 || which == 1);
-
+
begin_change ();
_heads[which].outward = outward;
Arrow::set_head_height (int which, Distance height)
{
assert (which == 0 || which == 1);
-
+
begin_change ();
-
+
_heads[which].height = height;
setup_polygon (which);
Arrow::set_head_width (int which, Distance width)
{
assert (which == 0 || which == 1);
-
+
begin_change ();
-
+
_heads[which].width = width;
setup_polygon (which);
Arrow::setup_polygon (int which)
{
assert (which == 0 || which == 1);
-
+
Points points;
if ((which == 0 && _heads[which].outward) || (which == 1 && !_heads[which].outward)) {
void set_iterations (int);
double run ();
-
+
virtual void do_run (ArdourCanvas::ImageCanvas &) = 0;
virtual void finish (ArdourCanvas::ImageCanvas &) {}
test (int items_per_cell)
{
Group::default_items_per_cell = items_per_cell;
-
+
int const n_rectangles = 10000;
int const n_tests = 1000;
double const rough_size = 1000;
for (unsigned int i = 0; i < sizeof (tests) / sizeof (int); ++i) {
timeval start;
timeval stop;
-
+
gettimeofday (&start, 0);
test (tests[i]);
gettimeofday (&stop, 0);
cout << "Test " << tests[i] << ": " << seconds << "\n";
}
}
-
+
{
_items_per_cell = items;
}
-
+
void do_run (ImageCanvas& canvas)
{
Group::default_items_per_cell = _items_per_cell;
canvas.set_log_renders (false);
list<Rect> const & renders = canvas.renders ();
-
+
for (list<Rect>::const_iterator i = renders.begin(); i != renders.end(); ++i) {
canvas.render_to_image (*i);
}
return 0;
}
-
+
{
_items_per_cell = items;
}
-
+
void do_run (ImageCanvas& canvas)
{
Group::default_items_per_cell = _items_per_cell;
-
+
for (int i = 0; i < 1e4; i += 50) {
canvas.render_to_image (Rect (i, 0, i + 50, 1024));
}
return 0;
}
-
+
if (argc > 2) {
render_whole.set_iterations (atoi (argv[2]));
}
-
+
cout << render_whole.run () << "\n";
-
+
return 0;
}
#endif
render_count = 0;
-
+
boost::optional<Rect> root_bbox = _root.bounding_box();
if (!root_bbox) {
/* the root has no bounding box, so there's nothing to render */
boost::optional<Rect> draw = root_bbox->intersection (area);
if (draw) {
-
+
/* there's a common area between the root and the requested
area, so render it.
*/
{
dump_depth = 0;
_root.dump (o);
-}
+}
/** Called when an item has been shown or hidden.
* @param item Item that has been shown or hidden.
void
Canvas::item_changed (Item* item, boost::optional<Rect> pre_change_bounding_box)
{
-
+
Rect window_bbox = visible_area ();
if (pre_change_bounding_box) {
boost::optional<Rect> post_change_bounding_box = item->bounding_box ();
if (post_change_bounding_box) {
-
+
if (item->item_to_window (*post_change_bounding_box).intersection (window_bbox)) {
/* request a redraw of the item's new bounding box */
queue_draw_item_area (item, post_change_bounding_box.get ());
* added or removed, so we have no coordinates to work from as is the
* case with a motion event. Find out where the mouse is and use that.
*/
-
+
Glib::RefPtr<const Gdk::Window> pointer_window = Gdk::Display::get_default()->get_window_at_pointer (x, y);
if (pointer_window != get_window()) {
top, but we're going to reverse that for within_items so that its
first item is the upper-most item that can be chosen as _current_item.
*/
-
+
vector<Item const *>::const_iterator i;
list<Item const *> within_items;
DEBUG_TRACE (PBD::DEBUG::CanvasEnterLeave, string_compose ("CURRENT ITEM %1/%2\n", _new_current_item->whatami(), _current_item->name));
return;
}
-
+
_new_current_item = const_cast<Item*> (within_items.front());
}
/* Events delivered to canvas items are expected to be in canvas
* coordinates but @param point is in window coordinates.
*/
-
+
Duple c = window_to_canvas (point);
enter_event.x = c.x;
enter_event.y = c.y;
* Deliver "virtual" leave notifications to all items in the
* heirarchy between current and new_current.
*/
-
+
for (i = _current_item->parent(); i && i != _new_current_item; i = i->parent()) {
items_to_leave_virtual.push_back (i);
}
enter_detail = GDK_NOTIFY_NONLINEAR;
leave_detail = GDK_NOTIFY_NONLINEAR;
}
-
+
if (_current_item && !_current_item->ignore_events ()) {
leave_event.detail = leave_detail;
/* run through the items from child to parent, until one claims the event */
Item* item = const_cast<Item*> (event_item);
-
+
while (item) {
Item* parent = item->parent ();
PBD::DEBUG::CanvasEvents,
string_compose ("canvas event handled by %1 %2\n", item->whatami(), item->name.empty() ? "[unknown]" : item->name)
);
-
+
return true;
}
-
+
DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas event %3 left unhandled by %1 %2\n", item->whatami(), item->name.empty() ? "[unknown]" : item->name, event_type_string (event->type)));
if ((item = parent) == 0) {
if (bounding_box) {
queue_draw_item_area (item, bounding_box.get ());
}
-
+
if (_new_current_item == item) {
_new_current_item = 0;
}
_current_item = 0;
pick_current_item (0); // no mouse state
}
-
+
}
void
/* render canvas */
if ( _single_exposure ) {
-
+
render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
} else {
GdkRectangle* rects;
gint nrects;
-
+
gdk_region_get_rectangles (ev->region, &rects, &nrects);
for (gint n = 0; n < nrects; ++n) {
draw_context->set_identity_matrix(); //reset the cairo matrix, just in case someone left it transformed after drawing ( cough )
}
g_free (rects);
}
-
+
#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
if (getenv("ARDOUR_IMAGE_SURFACE")) {
#endif
GdkEvent copy = *((GdkEvent*)ev);
Duple winpos = Duple (ev->x, ev->y);
Duple where = window_to_canvas (winpos);
-
+
pick_current_item (winpos, ev->state);
copy.button.x = where.x;
copy.button.y = where.y;
-
+
/* Coordinates in the event will be canvas coordinates, correctly adjusted
for scroll if this GtkCanvas is in a GtkCanvasViewport.
*/
GdkEvent copy = *((GdkEvent*)ev);
Duple winpos = Duple (ev->x, ev->y);
Duple where = window_to_canvas (winpos);
-
+
pick_current_item (winpos, ev->state);
copy.button.x = where.x;
copy.button.y = where.y;
-
+
/* Coordinates in the event will be canvas coordinates, correctly adjusted
for scroll if this GtkCanvas is in a GtkCanvasViewport.
*/
*/
bool
GtkCanvas::on_button_release_event (GdkEventButton* ev)
-{
+{
/* translate event coordinates from window to canvas */
GdkEvent copy = *((GdkEvent*)ev);
Duple winpos = Duple (ev->x, ev->y);
Duple where = window_to_canvas (winpos);
-
+
pick_current_item (winpos, ev->state);
copy.button.x = where.x;
(void) toplevel->get_window()->get_pointer (pointer_x, pointer_y, mask);
Duple tooltip_window_origin (pointer_x, pointer_y);
-
+
/* convert to root window coordinates */
int win_x, win_y;
dynamic_cast<Gtk::Window*>(toplevel)->get_position (win_x, win_y);
-
+
tooltip_window_origin = tooltip_window_origin.translate (Duple (win_x, win_y));
/* we don't want the pointer to be inside the window when it is
/* ready to show */
tooltip_window->present ();
-
+
/* called from a timeout handler, don't call it again */
return false;
double _arc_degrees;
double _start_degrees;
};
-
+
}
#endif
* @todo Draws vertical lines only; could be generalised
* to draw lines at any angle.
*/
-
+
class LIBCANVAS_API Arrow : public Container
{
public:
void set_x (Coord);
void set_y0 (Coord);
void set_y1 (Coord);
-
+
bool covers (Duple const &) const;
private:
* of screen pixels, with an origin of (0, 0) at the top left. x increases
* rightwards and y increases downwards.
*/
-
+
class LIBCANVAS_API Canvas
{
public:
/** Set the timeout used to display tooltips, in milliseconds
*/
static void set_tooltip_timeout (uint32_t msecs);
-
+
protected:
Root _root;
Color _bg_color;
bool on_motion_notify_event (GdkEventMotion *);
bool on_enter_notify_event (GdkEventCrossing*);
bool on_leave_notify_event (GdkEventCrossing*);
-
+
bool button_handler (GdkEventButton *);
bool motion_notify_handler (GdkEventMotion *);
bool deliver_event (GdkEvent *);
Item * _grabbed_item;
/** the item that currently has key focus or 0 */
Item * _focused_item;
-
+
bool _single_exposure;
sigc::connection tooltip_timeout_connection;
Circle (Canvas*);
Circle (Item*);
};
-
+
}
#endif
double s() const { return _s; }
double v() const { return _v; }
double a() const { return _a; }
-
+
HSV operator () (HSV& hsv) const;
std::string to_string () const;
void from_string (std::string const &);
-
+
private:
Type type;
double _s;
HSV (double h, double s, double v, double a = 1.0);
HSV (Color);
HSV (const std::string&);
-
+
double h;
double s;
double v;
std::string to_string() const;
bool is_gray() const;
-
+
Color color() const { return hsva_to_color (h,s, v, a); }
operator Color() const { return color(); }
HSV mod (SVAModifier const & svam);
-
+
HSV operator+ (const HSV&) const;
HSV operator- (const HSV&) const;
}
typedef std::vector<std::pair<double,Color> > StopList;
-
+
void set_gradient (StopList const & stops, bool is_vertical);
void set_pattern (Cairo::RefPtr<Cairo::Pattern>);
void set_font_description (Pango::FontDescription);
bool covers (Duple const &) const;
-
+
private:
void setup (Distance height, Duple position);
Rectangle* _rectangle;
bool _invert;
};
-
+
}
namespace ArdourCanvas
{
-struct Rect;
+struct Rect;
class Canvas;
class ScrollGroup;
* Any item that is being displayed on a canvas has a pointer to that canvas,
* and all except the `root group' have a pointer to their parent group.
*/
-
+
class LIBCANVAS_API Item : public Fill, public Outline
{
public:
void grab ();
void ungrab ();
-
+
void unparent ();
void reparent (Item *);
}
bool visible () const;
-
+
/** @return Our canvas, or 0 if we are not attached to one */
Canvas* canvas () const {
return _canvas;
static int default_items_per_cell;
-
+
/* This is a sigc++ signal because it is solely
concerned with GUI stuff and is thus single-threaded
*/
return false;
}
};
-
+
sigc::signal1<bool, GdkEvent*, EventAccumulator<bool> > Event;
#ifdef CANVAS_DEBUG
std::string name;
#endif
-
+
#ifdef CANVAS_COMPATIBILITY
void grab_focus ();
-#endif
+#endif
const std::string& tooltip () const { return _tooltip; }
void set_tooltip (const std::string&);
void start_tooltip_timeout ();
void stop_tooltip_timeout ();
-
+
virtual void dump (std::ostream&) const;
std::string whatami() const;
private:
Duple _points[2];
};
-
+
}
#endif
struct Line {
Line (Coord p, Distance width_, Color color_) : pos (p), width (width_), color (color_) {}
-
+
Coord pos;
Distance width;
Color color;
virtual bool has_item_at_point (Duple const & point) const = 0;
protected:
-
+
Item const & _item;
};
Distance outline_width () const {
return _outline_width;
}
-
+
virtual void set_outline_width (Distance);
bool outline () const {
Points _points;
};
-
+
}
#endif
public:
PolyLine (Canvas*);
PolyLine (Item*);
-
+
void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const;
virtual void set_steps (Points const &, bool stepped);
-
+
bool covers (Duple const &) const;
/**
* Set the distance at which a point will be considered to be covered
private:
double _threshold;
};
-
+
}
#endif
void cache_shape_computation () const;
};
-
+
}
#endif
Rectangle (Canvas*, Rect const &);
Rectangle (Item*);
Rectangle (Item*, Rect const &);
-
+
void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
void compute_bounding_box () const;
{
private:
friend class Canvas;
-
+
Root (Canvas *);
void compute_bounding_box () const;
namespace ArdourCanvas
{
-
+
class LIBCANVAS_API Ruler : public Rectangle
{
public:
double position;
Style style;
};
-
+
struct Metric {
Metric () : units_per_pixel (0) {}
virtual ~Metric() {}
/* lower and upper and sample positions, which are also canvas coordinates
*/
-
+
virtual void get_marks (std::vector<Mark>&, double lower, double upper, int maxchars) const = 0;
};
-
+
Ruler (Canvas*, const Metric& m);
Ruler (Canvas*, const Metric& m, Rect const&);
Ruler (Item*, const Metric& m);
Ruler (Item*, const Metric& m, Rect const&);
-
+
void set_range (double lower, double upper);
void set_font_description (Pango::FontDescription);
void set_metric (const Metric&);
ScrollsVertically = 0x1,
ScrollsHorizontally = 0x2
};
-
+
ScrollGroup (Canvas*, ScrollSensitivity);
ScrollGroup (Item*, ScrollSensitivity);
public:
TrackingText (Canvas*);
TrackingText (Item*);
-
+
void show_and_track (bool track_x, bool track_y);
void set_offset (Duple const &);
void set_x_offset (double);
: x (0)
, y (0)
{}
-
+
Duple (Coord x_, Coord y_)
: x (x_)
, y (y_)
{}
-
+
Coord x;
Coord y;
, x1 (0)
, y1 (0)
{}
-
+
Rect (Coord x0_, Coord y0_, Coord x1_, Coord y1_)
: x0 (x0_)
, y0 (y0_)
, x1 (x1_)
, y1 (y1_)
{}
-
+
Coord x0;
Coord y0;
Coord x1;
boost::optional<Rect> intersection (Rect const & o) const throw () {
Rect i (std::max (x0, o.x0), std::max (y0, o.y0),
std::min (x1, o.x1), std::min (y1, o.y1));
-
+
if (i.x0 > i.x1 || i.y0 > i.y1) {
return boost::optional<Rect> ();
}
-
+
return boost::optional<Rect> (i);
}
-
+
Rect extend (Rect const & o) const throw () {
return Rect (std::min (x0, o.x0), std::min (y0, o.y0),
std::max (x1, o.x1), std::max (y1, o.y1));
return Rect (canvas_safe_add (x0, amount), canvas_safe_add (y0, amount),
x1 - amount, y1 - amount);
}
-
+
bool contains (Duple const & point) const throw () {
return point.x >= x0 && point.x < x1 && point.y >= y0 && point.y < y1;
}
return Rect (std::min (x0, x1), std::min (y0, y1),
std::max (x0, x1), std::max (y0, y1));
}
-
+
bool empty() const throw () { return (x0 == x1 && y0 == y1); }
Distance width () const throw () {
typedef std::vector<Duple> Points;
}
-
+
#endif
}
class WaveViewTest;
-
+
namespace ArdourCanvas {
struct LIBCANVAS_API WaveViewThreadRequest
};
WaveViewThreadRequest () : stop (0) {}
-
+
bool should_stop () const { return (bool) g_atomic_int_get (const_cast<gint*>(&stop)); }
void cancel() { g_atomic_int_set (&stop, 1); }
-
+
RequestType type;
framepos_t start;
framepos_t end;
boost::weak_ptr<const ARDOUR::Region> region;
/* resulting image, after request has been satisfied */
-
+
Cairo::RefPtr<Cairo::ImageSurface> image;
-
+
private:
gint stop; /* intended for atomic access */
};
public:
WaveViewCache();
~WaveViewCache();
-
+
struct Entry {
/* these properties define the cache entry as unique.
/* last time the cache entry was used */
uint64_t timestamp;
-
+
Entry (int chan, Coord hght, float amp, Color fcl, double spp, framepos_t strt, framepos_t ed,
Cairo::RefPtr<Cairo::ImageSurface> img)
: channel (chan)
uint64_t image_cache_threshold () const { return _image_cache_threshold; }
void set_image_cache_threshold (uint64_t);
void clear_cache ();
-
+
void add (boost::shared_ptr<ARDOUR::AudioSource>, boost::shared_ptr<Entry>);
void use (boost::shared_ptr<ARDOUR::AudioSource>, boost::shared_ptr<Entry>);
-
+
void consolidate_image_cache (boost::shared_ptr<ARDOUR::AudioSource>,
int channel,
Coord height,
Cairo::RefPtr<Cairo::ImageSurface> _image;
PBD::Signal0<void> ImageReady;
-
+
/* Displays a single channel of waveform data for the given Region.
x = 0 in the waveview corresponds to the first waveform datum taken
from region->start() samples into the source data.
-
+
x = N in the waveview corresponds to the (N * spp)'th sample
measured from region->start() into the source data.
-
+
when drawing, we will map the zeroth-pixel of the waveview
into a window.
-
+
The waveview itself contains a set of pre-rendered Cairo::ImageSurfaces
that cache sections of the display. This is filled on-demand and
never cleared until something explicitly marks the cache invalid
* want this behaviour.
*/
void set_start_shift (double pixels);
-
+
void set_fill_color (Color);
void set_outline_color (Color);
-
+
void region_resized ();
void gain_changed ();
static void stop_drawing_thread ();
static void set_image_cache_size (uint64_t);
-
-#ifdef CANVAS_COMPATIBILITY
+
+#ifdef CANVAS_COMPATIBILITY
void*& property_gain_src () {
return _foo_void;
}
double _amplitude_above_axis;
float _region_amplitude;
double _start_shift;
-
+
/** The `start' value to use for the region; we can't use the region's
* value as the crossfade editor needs to alter it.
*/
keep updating (e.g. while recording)
*/
bool always_get_image_in_thread;
-
+
/** Set to true by render(). Used so that we know if the wave view
* has actually been displayed on screen. ::set_height() when this
* is true does not use get_image_in_thread, because it implies
* that the height is being set BEFORE the waveview is drawn.
*/
mutable bool rendered;
-
+
PBD::ScopedConnectionList invalidation_connection;
PBD::ScopedConnection image_ready_connection;
boost::shared_ptr<WaveViewCache::Entry> get_image (framepos_t start, framepos_t end, bool& full_image) const;
boost::shared_ptr<WaveViewCache::Entry> get_image_from_cache (framepos_t start, framepos_t end, bool& full_image) const;
-
+
struct LineTips {
double top;
double bot;
double spread;
bool clip_max;
bool clip_min;
-
+
LineTips() : top (0.0), bot (0.0), clip_max (false), clip_min (false) {}
};
void draw_image (Cairo::RefPtr<Cairo::ImageSurface>&, ARDOUR::PeakData*, int n_peaks, boost::shared_ptr<WaveViewThreadRequest>) const;
void draw_absent_image (Cairo::RefPtr<Cairo::ImageSurface>&, ARDOUR::PeakData*, int) const;
-
+
void cancel_my_render_request () const;
void queue_get_image (boost::shared_ptr<const ARDOUR::Region> region, framepos_t start, framepos_t end) const;
mutable boost::shared_ptr<WaveViewCache::Entry> _current_image;
mutable boost::shared_ptr<WaveViewThreadRequest> current_request;
-
+
static WaveViewCache* images;
static void drawing_thread ();
public:
Widget (Canvas*, CairoWidget&);
Widget (Item*, CairoWidget&);
-
+
void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
void compute_bounding_box () const;
double cmax;
double cmin;
double delta;
-
+
color_to_rgba (color, r, g, b, a);
-
+
if (r > g) {
cmax = max (r, b);
} else {
return;
}
- if (delta != 0.0) {
+ if (delta != 0.0) {
if (cmax == r) {
h = fmod ((g - b)/delta, 6.0);
} else if (cmax == g) {
} else {
h = ((r - g)/delta) + 4;
}
-
+
h *= 60.0;
-
+
if (h < 0.0) {
/* negative values are legal but confusing, because
they alias positive values.
HSV::shade (double factor) const
{
HSV hsv (*this);
-
+
/* algorithm derived from a google palette website
and analysis of their color palettes.
perceptual distance of sqrt ((360^2) + 1 + 1) = 360. The 450
are not evenly spread (Webers Law), so lets use 360 as an
approximation of the number of distinct achromatics.
-
+
So, scale up the achromatic difference to give about
a maximal distance between v = 1.0 and v = 0.0 of 360.
-
+
A difference of about 0.0055 will generate a return value of
2, which is roughly the limit of human perceptual
discrimination for chromatics.
const double xDE = sqrt (((sL - oL) * (sL - oL))
+ ((sA - oA) * (sA - oA))
+ ((sB - oB) * (sB - oB)));
-
+
double xDH;
if (sqrt (xDE) > (sqrt (abs (xDL)) + sqrt (abs (xDC)))) {
xDL /= whtL;
xDC /= whtC * xSC;
xDH /= whtH * xSH;
-
+
return sqrt ((xDL * xDL) + (xDC * xDC) + (xDH * xDH));
}
SVAModifier::operator () (HSV& hsv) const
{
HSV r (hsv);
-
+
switch (type) {
case Add:
r.s += _s;
double Max = MAX3(R, G, B);
double Min = MIN3(R, G, B);
double C = Max - Min;
-
-
+
+
*V = Max;
-
+
if(C > 0)
{
if(Max == R)
{
*H = (G - B) / C;
-
+
if(G < B)
*H += 6;
}
*H = 2 + (B - R) / C;
else
*H = 4 + (R - G) / C;
-
+
*H *= 60;
*S = C / Max;
}
double C = S * V;
double Min = V - C;
double X;
-
-
+
+
H -= 360*floor(H/360);
H /= 60;
X = C*(1 - fabs(H - 2*floor(H/2) - 1));
-
+
switch((int)H)
{
case 0:
double Max = MAX3(R, G, B);
double Min = MIN3(R, G, B);
double C = Max - Min;
-
-
+
+
*L = (Max + Min)/2;
-
+
if(C > 0)
{
if(Max == R)
{
*H = (G - B) / C;
-
+
if(G < B)
*H += 6;
}
*H = 2 + (B - R) / C;
else
*H = 4 + (R - G) / C;
-
+
*H *= 60;
*S = (*L <= 0.5) ? (C/(2*(*L))) : (C/(2 - 2*(*L)));
}
double C = (L <= 0.5) ? (2*L*S) : ((2 - 2*L)*S);
double Min = L - 0.5*C;
double X;
-
-
+
+
H -= 360*floor(H/360);
H /= 60;
X = C*(1 - fabs(H - 2*floor(H/2) - 1));
-
+
switch((int)H)
{
case 0:
{
double alpha = 0.5*(2*R - G - B);
double beta = 0.866025403784439*(G - B);
-
-
+
+
*I = (R + G + B)/3;
-
+
if(*I > 0)
{
*S = 1 - MIN3(R,G,B) / *I;
*H = atan2(beta, alpha)*(180/M_PI);
-
+
if(*H < 0)
*H += 360;
}
void Hsi2Rgb(double *R, double *G, double *B, double H, double S, double I)
{
H -= 360*floor(H/360);
-
+
if(H < 120)
{
*B = I*(1 - S);
* Wikipedia: http://en.wikipedia.org/wiki/CIE_1931_color_space
*/
void Xyz2Rgb(double *R, double *G, double *B, double X, double Y, double Z)
-{
+{
double R1, B1, G1, Min;
-
-
+
+
R1 = (double)( 3.2406*X - 1.5372*Y - 0.4986*Z);
G1 = (double)(-0.9689*X + 1.8758*Y + 0.0415*Z);
B1 = (double)( 0.0557*X - 0.2040*Y + 1.0570*Z);
-
+
Min = MIN3(R1, G1, B1);
-
+
/* Force nonnegative values so that gamma correction is well-defined. */
if(Min < 0)
{
* Wikipedia: http://en.wikipedia.org/wiki/CIELUV_color_space
*/
void Xyz2Luv(double *L, double *u, double *v, double X, double Y, double Z)
-{
+{
double u1, v1, Denom;
-
+
if((Denom = X + 15*Y + 3*Z) > 0)
{
{
*Y = (L + 16)/116;
*Y = WHITEPOINT_Y*LABINVF(*Y);
-
+
if(L != 0)
{
u /= L;
v /= L;
}
-
+
u = u/13 + WHITEPOINT_U;
v = v/13 + WHITEPOINT_V;
*X = (*Y) * ((9*u)/(4*v));
void Xyz2Lch(double *L, double *C, double *H, double X, double Y, double Z)
{
double a, b;
-
-
+
+
Xyz2Lab(L, &a, &b, X, Y, Z);
*C = sqrt(a*a + b*b);
*H = atan2(b, a)*180.0/M_PI;
-
+
if(*H < 0)
*H += 360;
}
{
double a = C * cos(H*(M_PI/180.0));
double b = C * sin(H*(M_PI/180.0));
-
-
+
+
Lab2Xyz(X, Y, Z, L, a, b);
}
* section of the curve. For now we rely on cairo clipping to help
* with this.
*/
-
+
setup_outline_context (context);
draw = draw.expand (4.0);
/* now clip it to the actual points in the curve */
-
+
if (draw.x0 < w1.x) {
draw.x0 = w1.x;
}
now.tv_usec += 1e6;
--now.tv_sec;
}
-
+
map<string, struct timeval>::iterator last = last_time.find (group);
if (last != last_time.end ()) {
Fill::setup_gradient_context (Cairo::RefPtr<Cairo::Context> context, Rect const & self, Duple const & draw_origin) const
{
Cairo::RefPtr<Cairo::LinearGradient> _gradient;
-
+
if (_vertical_gradient) {
_gradient = Cairo::LinearGradient::create (draw_origin.x, self.y0, draw_origin.x, self.y1);
} else {
_gradient = Cairo::LinearGradient::create (self.x0, draw_origin.y, self.x1, draw_origin.y);
}
-
+
for (StopList::const_iterator s = _stops.begin(); s != _stops.end(); ++s) {
double r, g, b, a;
color_to_rgba (s->second, r, g, b, a);
_gradient->add_color_stop_rgba (s->first, r, g, b, a);
}
-
+
context->set_source (_gradient);
}
assert (bbox);
Duple flag_size (bbox.get().width() + 10, bbox.get().height() + 4);
-
+
if (_invert) {
const Distance h = fabs(_line->y1() - _line->y0());
_text->set_position (Duple (5, h - flag_size.y + 2));
_pending->stride);
_current = _pending;
}
-
+
Rect self = item_to_window (Rect (0, 0, _width, _height));
boost::optional<Rect> draw = self.intersection (area);
begin_change ();
_need_render = true;
end_change (); // notify canvas that we need redrawing
-}
+}
, _ignore_events (false)
{
DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this));
-}
+}
Item::Item (Item* parent)
: Fill (*this)
}
find_scroll_parent ();
-}
+}
Item::Item (Item* parent, Duple const& p)
: Fill (*this)
find_scroll_parent ();
-}
+}
Item::~Item ()
{
Item::item_to_canvas (Coord& x, Coord& y) const
{
Duple d = item_to_canvas (Duple (x, y));
-
+
x = d.x;
y = d.y;
}
*/
pre_change_parent_bounding_box = item_to_parent (bbox.get());
}
-
+
_position = p;
/* only update canvas and parent if visible. Otherwise, this
will be done when ::show() is called.
*/
-
+
if (visible()) {
_canvas->item_moved (this, pre_change_parent_bounding_box);
-
+
if (_parent) {
_parent->child_changed ();
}
}
-
+
propagate_show_hide ();
}
}
Item::propagate_show_hide ()
{
/* bounding box may have changed while we were hidden */
-
+
if (_parent) {
_parent->child_changed ();
}
-
+
_canvas->item_shown_or_hidden (this);
}
}
i = i->parent();
}
-
+
_scroll_parent = const_cast<ScrollGroup*> (last_scroll_group);
}
uint32_t d2 = other.depth();
const Item* i1 = this;
const Item* i2 = &other;
-
+
/* move towards root until we are at the same level
for both items
*/
return false;
}
}
-
+
return true;
}
i2 = i2->parent ();
}
}
-
+
return i1;
}
if (visible() && _bounding_box && _canvas) {
_canvas->request_redraw (item_to_window (_bounding_box.get()));
}
-}
+}
void
Item::begin_change ()
{
if (visible()) {
_canvas->item_changed (this, _pre_change_bounding_box);
-
+
if (_parent) {
_parent->child_changed ();
}
if (i == _data.end ()) {
return 0;
}
-
+
return i->second;
}
#endif
++render_depth;
-
+
for (std::vector<Item*>::const_iterator i = items.begin(); i != items.end(); ++i) {
if (!(*i)->visible ()) {
#endif
continue;
}
-
+
boost::optional<Rect> item_bbox = (*i)->bounding_box ();
if (!item_bbox) {
#endif
continue;
}
-
+
Rect item = (*i)->item_to_window (item_bbox.get(), false);
boost::optional<Rect> d = item.intersection (area);
-
+
if (d) {
Rect draw = d.get();
if (draw.width() && draw.height()) {
_items.remove (i);
invalidate_lut ();
_bounding_box_dirty = true;
-
+
end_change ();
}
_items.erase (i);
item->unparent ();
-
+
if (with_delete) {
delete item;
}
o << _canvas->indent() << whatami() << ' ' << this << " self-Visible ? " << self_visible() << " visible ? " << visible();
o << " @ " << position();
-
+
#ifdef CANVAS_DEBUG
if (!name.empty()) {
o << ' ' << name;
o << " Items: " << _items.size();
o << " Self-Visible ? " << self_visible();
o << " Visible ? " << visible();
-
+
boost::optional<Rect> bb = bounding_box();
-
+
if (bb) {
o << endl << _canvas->indent() << " bbox: " << bb.get();
o << endl << _canvas->indent() << " CANVAS bbox: " << item_to_canvas (bb.get());
} else {
o << " bbox unset";
}
-
+
o << endl;
#endif
-
+
ArdourCanvas::dump_depth++;
-
+
for (list<Item*>::const_iterator i = _items.begin(); i != _items.end(); ++i) {
o << **i;
}
-
+
ArdourCanvas::dump_depth--;
}
}
Line::compute_bounding_box () const
{
Rect bbox;
-
+
bbox.x0 = min (_points[0].x, _points[1].x);
bbox.y0 = min (_points[0].y, _points[1].y);
bbox.x1 = max (_points[0].x, _points[1].x);
if (_outline_width <= 1.0) {
/* See Cairo FAQ on single pixel lines to understand why we add 0.5
*/
-
+
const Duple half_a_pixel (0.5, 0.5);
p0 = p0.translate (half_a_pixel);
p1 = p1.translate (half_a_pixel);
{
if (a != _points[0] || b != _points[1]) {
begin_change ();
-
+
_points[0] = a;
_points[1] = b;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (x0 != _points[0].x || x1 != _points[1].x) {
begin_change ();
-
+
_points[0].x = x0;
_points[1].x = x1;
-
+
_bounding_box_dirty = true;
end_change ();
}
-}
+}
void
Line::set_x0 (Coord x0)
{
if (x0 != _points[0].x) {
begin_change ();
-
+
_points[0].x = x0;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (y0 != _points[0].y) {
begin_change ();
-
+
_points[0].y = y0;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (x1 != _points[1].x) {
begin_change ();
-
+
_points[1].x = x1;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (y1 != _points[1].y) {
begin_change ();
-
+
_points[1].y = y1;
-
+
_bounding_box_dirty = true;
end_change ();
}
} else {
if (_orientation == Horizontal) {
-
+
_bounding_box = Rect (0, /* x0 */
_lines.front().pos - (_lines.front().width/2.0), /* y0 */
_extent, /* x1 */
);
} else {
-
+
_bounding_box = Rect (_lines.front().pos - _lines.front().width/2.0, /* x0 */
0, /* y0 */
_lines.back().pos + _lines.back().width/2.0, /* x1 */
}
boost::optional<Rect> isect = self.intersection (area);
-
+
if (!isect) {
- continue;
+ continue;
}
Rect intersection (isect.get());
LineSet::add (Coord y, Distance width, Color color)
{
begin_change ();
-
+
_lines.push_back (Line (y, width, color));
sort (_lines.begin(), _lines.end(), LineSorter());
if (!(*i)->visible()) {
continue;
}
-
+
if ((*i)->covers (point)) {
// std::cerr << "\t\t" << (*i)->whatami() << '/' << (*i)->name << " covers " << point << std::endl;
return true;
-
+
}
}
if (y >= _dimension) {
cout << "WARNING: y=" << y << ", dim=" << _dimension << ", py=" << point.y << " cellsize=" << _cell_size << "\n";
}
-
+
/* XXX: hmm */
x = min (_dimension - 1, x);
y = min (_dimension - 1, y);
if (y >= _dimension) {
cout << "WARNING: y=" << y << ", dim=" << _dimension << ", py=" << point.y << " cellsize=" << _cell_size << "\n";
}
-
+
/* XXX: hmm */
x = min (_dimension - 1, x);
y = min (_dimension - 1, y);
return false;
}
-
+
/** @param area Area in our owning item's coordinates */
vector<Item*>
OptimizingLookupTable::get (Rect const & area)
vector<Item*> vitems;
copy (items.begin (), items.end (), back_inserter (vitems));
-
+
return vitems;
}
Gdk::Cairo::set_source_pixbuf (context, _pixbuf, 0, 0);
context->paint ();
}
-
+
void
Pixbuf::compute_bounding_box () const
{
Pixbuf::set (Glib::RefPtr<Gdk::Pixbuf> pixbuf)
{
begin_change ();
-
+
_pixbuf = pixbuf;
_bounding_box_dirty = true;
void
PolyItem::compute_bounding_box () const
{
-
+
if (!_points.empty()) {
Rect bbox;
Points::const_iterator i = _points.begin();
-
+
bbox.x0 = bbox.x1 = i->x;
bbox.y0 = bbox.y1 = i->y;
_bounding_box = bbox.expand (_outline_width + 0.5);
-
+
} else {
_bounding_box = boost::optional<Rect> ();
}
-
+
_bounding_box_dirty = false;
}
Duple c2 = item_to_window (Duple (cp2->x, cp2->y));
c = item_to_window (Duple (p->x, p->y));
-
+
context->curve_to (c1.x + pixel_adjust,
c1.y + pixel_adjust,
c2.x + pixel_adjust,
c2.y + pixel_adjust,
c.x + pixel_adjust,
c.y + pixel_adjust);
-
+
++cp1;
++cp2;
++p;
if (_points != points) {
begin_change ();
-
+
_points = points;
-
+
_bounding_box_dirty = true;
end_change ();
}
Duple p = window_to_item (point);
const Points::size_type npoints = _points.size();
-
+
if (npoints < 2) {
return false;
}
double t;
Duple a (_points[j]);
Duple b (_points[i]);
-
+
/*
Clamp the line endpoints to the visible area of the canvas. If we do
not do this, we may have a line segment extending to COORD_MAX and our
math goes wrong.
*/
-
+
a.x = std::min (a.x, visible.x1);
a.y = std::min (a.y, visible.y1);
b.x = std::min (b.x, visible.x1);
b.y = std::min (b.y, visible.y1);
-
+
double d = distance_to_segment_squared (p, a, b, t, at);
-
+
if (t < 0.0 || t > 1.0) {
continue;
}
-
+
if (d < _threshold + _outline_width) {
return true;
}
-
+
}
-
+
return false;
}
{
if (_outline || _fill) {
render_path (area, context);
-
+
if (!_points.empty ()) {
/* close path */
Duple p = item_to_window (Duple (_points.front().x, _points.front().y));
Points::size_type i;
Points::size_type j = npoints -1;
bool oddNodes = false;
-
+
if (_bounding_box_dirty) {
compute_bounding_box ();
}
-
+
for (i = 0; i < npoints; i++) {
if (((_points[i].y < p.y && _points[j].y >= p.y) || (_points[j].y < p.y && _points[i].y >= p.y))) {
oddNodes ^= (p.y * multiple[i] + constant[i] < p.x);
Rectangle::render_self (Rect const & area, Cairo::RefPtr<Cairo::Context> context, Rect self) const
{
boost::optional<Rect> r = self.intersection (area);
-
+
if (!r) {
return;
}
context->rectangle (draw.x0, draw.y0, draw.width(), draw.height());
context->fill ();
}
-
+
if (_outline) {
setup_outline_context (context);
-
+
/* the goal here is that if the border is 1 pixel
* thick, it will precisely align with the corner
* coordinates of the rectangle. So if the rectangle
const double shift = _outline_width * 0.5;
self = self.translate (Duple (shift, shift));
}
-
+
if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) {
-
+
context->rectangle (self.x0, self.y0, self.width(), self.height());
} else {
context->move_to (self.x0, self.y0);
context->line_to (self.x0, self.y1);
}
-
+
if (_outline_what & TOP) {
context->move_to (self.x0, self.y0);
context->line_to (self.x1, self.y0);
context->move_to (self.x0, self.y1);
context->line_to (self.x1, self.y1);
}
-
+
if (_outline_what & RIGHT) {
context->move_to (self.x1, self.y0);
context->line_to (self.x1, self.y1);
}
}
-
+
context->stroke ();
}
}
*/
if (r != _rect) {
-
+
begin_change ();
-
+
_rect = r;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (x0 != _rect.x0) {
begin_change ();
-
+
_rect.x0 = x0;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (y0 != _rect.y0) {
begin_change ();
-
+
_rect.y0 = y0;
-
+
_bounding_box_dirty = true;
end_change();
}
{
if (x1 != _rect.x1) {
begin_change ();
-
+
_rect.x1 = x1;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
if (y1 != _rect.y1) {
begin_change ();
-
+
_rect.y1 = y1;
-
+
_bounding_box_dirty = true;
end_change ();
}
{
#ifdef CANVAS_DEBUG
name = "ROOT";
-#endif
+#endif
}
void
cr->stroke ();
/* draw ticks + text */
-
+
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create (cr);
if (_font_description) {
layout->set_font_description (*_font_description);
} else {
cr->move_to (pos.x, pos.y);
}
-
+
switch (m->style) {
case Mark::Major:
if (_divide_height >= 0) {
layout->set_text (m->label);
logical = layout->get_pixel_logical_extents ();
-
+
if (_divide_height >= 0) {
cr->move_to (pos.x + 2.0, self.y0 + _divide_height + logical.get_y() + 2.0); /* 2 pixel padding below divider */
} else {
ScrollGroup::ScrollGroup (Canvas* c, ScrollSensitivity s)
: Container (c)
- , _scroll_sensitivity (s)
+ , _scroll_sensitivity (s)
{
}
ScrollGroup::ScrollGroup (Item* parent, ScrollSensitivity s)
: Container (parent)
- , _scroll_sensitivity (s)
+ , _scroll_sensitivity (s)
{
}
context->save ();
context->rectangle (self.x0, self.y0, self.width(), self.height());
context->clip ();
-
+
Container::render (area, context);
context->restore ();
Rect self = item_to_window (Rect (0, 0, image->get_width(), image->get_height()));
boost::optional<Rect> draw = self.intersection (area);
-
+
if (!draw) {
return;
}
StatefulImage::load_states (const XMLNode& node)
{
const XMLNodeList& nodes (node.children());
-
+
_states.clear ();
-
+
for (XMLNodeList::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
State s;
States::size_type id;
const XMLProperty* prop;
-
+
if ((prop = (*i)->property ("id")) == 0) {
error << _("no ID for state") << endmsg;
continue;
error << _("no image for state") << endmsg;
continue;
}
-
+
if ((s.image = find_image (prop->value())) == 0) {
error << string_compose (_("image %1 not found for state"), prop->value()) << endmsg;
continue;
}
-
+
if (_states.size() < id) {
_states.reserve (id);
}
name) << endmsg;
return ImageHandle();
}
-
+
return Cairo::ImageSurface::create_from_png (path);
}
arrow.set_outline_width (0);
boost::optional<Rect> bbox = arrow.bounding_box ();
-
+
CPPUNIT_ASSERT (bbox.is_initialized ());
CPPUNIT_ASSERT (bbox.get().x0 == -6);
CPPUNIT_ASSERT (bbox.get().y0 == 0);
CPPUNIT_ASSERT (*i++ == &d);
/* Check raise by a number of levels */
-
+
a.raise (2);
i = canvas.root()->items().begin();
/* Change the grandchild and check its parent and grandparent */
a.set (Rect (0, 0, 48, 48));
- bbox = canvas.root()->bounding_box ();
+ bbox = canvas.root()->bounding_box ();
CPPUNIT_ASSERT (bbox.is_initialized ());
CPPUNIT_ASSERT (bbox.get().x0 == 0);
CPPUNIT_ASSERT (bbox.get().y0 == 0);
GroupTest::add_items_at_point ()
{
ImageCanvas canvas;
-
+
Group gA (canvas.root());
gA.set_position (Duple (128, 64));
if (canvas.root()->bounding_box() && canvas.root()->bounding_box().get().contains (test)) {
items_B.push_back (canvas.root());
}
-
+
for (list<Item*>::iterator j = rectangles.begin(); j != rectangles.end(); ++j) {
boost::optional<Rect> bbox = (*j)->bounding_box ();
assert (bbox);
}
}
}
-
+
{
static bool dragging = false;
static Duple offset;
-
+
if (ev->type == GDK_BUTTON_PRESS) {
GdkEventButton* b = reinterpret_cast<GdkEventButton*> (ev);
if (b->button == 1) {
cout << "Move to " << (Duple (m->x, m->y) - offset) << "\n";
}
}
-
+
return true;
}
window.add (viewport);
canvas->show ();
window.show_all ();
-
+
Gtk::Main::run (window);
return 0;
}
double Ns = sqrt (N);
int max_x = 1024;
int max_y = 1024;
-
+
for (int x = 0; x < Ns; ++x) {
for (int y = 0; y < Ns; ++y) {
Rectangle* r = new Rectangle (canvas.root ());
r->set (Rect (x * max_x / Ns, y * max_y / Ns, (x + 1) * max_x / Ns, (y + 1) * max_y / Ns));
}
}
-
+
Gtk::ScrolledWindow scroller;
scroller.add (canvas);
window.add (scroller);
canvas.show ();
window.show_all ();
-
+
Gtk::Main::run (window);
return 0;
}
overall_box.pack_start (scroller);
Gtk::HBox button_box;
-
+
Gtk::Button bigger ("Bigger");
bigger.signal_clicked().connect (sigc::ptr_fun (&bigger_clicked));
button_box.pack_start (bigger);
Gtk::Button right ("Right");
right.signal_clicked().connect (sigc::ptr_fun (&right_clicked));
button_box.pack_start (right);
-
+
overall_box.pack_start (button_box, false, false);
-
+
window.add (overall_box);
canvas.show ();
window.show_all ();
Gtk::VBox overall_vbox;
Gtk::HScrollbar h_scroll;
Gtk::VScrollbar v_scroll;
-
+
GtkCanvasViewport viewport (*h_scroll.get_adjustment(), *v_scroll.get_adjustment());
GtkCanvas* canvas = viewport.canvas ();
window.add (overall_vbox);
canvas->show ();
window.show_all ();
-
+
Gtk::Main::run (window);
return 0;
}
b.set_outline_color (0x00ff00ff);
Gtk::HBox button_box;
-
+
Gtk::Button left ("Left");
left.signal_clicked().connect (sigc::ptr_fun (&left_clicked));
button_box.pack_start (left);
hadj = new Gtk::Adjustment (0, 0, 1e3);
vadj = new Gtk::Adjustment (0, 0, 1e3);
-
+
Gtk::Viewport viewport (*hadj, *vadj);
viewport.add (canvas);
Gtk::VBox overall_box;
overall_box.pack_start (viewport);
overall_box.pack_start (button_box, false, false);
-
+
window.add (overall_box);
canvas.show ();
window.show_all ();
-
+
Gtk::Main::run (window);
return 0;
}
Rectangle d (canvas.root(), Rect (33, 33, 64, 64));
d.set_outline_width (0);
OptimizingLookupTable table (*canvas.root(), 1);
-
+
CPPUNIT_ASSERT (table._items_per_cell == 1);
CPPUNIT_ASSERT (table._cell_size.x == 32);
CPPUNIT_ASSERT (table._cell_size.y == 32);
Rectangle d (canvas.root(), Rect (33, 33, 64, 64));
d.set_outline_width (0);
OptimizingLookupTable table (*canvas.root(), 1);
-
+
vector<Item*> items = table.get (Rect (16, 16, 48, 48));
CPPUNIT_ASSERT (items.size() == 4);
-
+
items = table.get (Rect (32, 32, 33, 33));
CPPUNIT_ASSERT (items.size() == 1);
}
double const s = 8;
int const N = 1024;
-
+
for (int x = 0; x < N; ++x) {
for (int y = 0; y < N; ++y) {
Rectangle* r = new Rectangle (canvas.root());
text_group.set_position (Duple (128, 64));
Text text (&text_group);
text.set ("Hello world!");
-
+
canvas.render_to_image (Rect (0, 0, 256, 256));
canvas.write_to_png ("render_basics.png");
CPPUNIT_ASSERT (c.y1 == 130);
}
}
-
+
void
TypesTest::test_safe_add ()
{
void test_safe_add ();
};
-
+
AudioEngine engine ("test", "");
MIDI::Manager::create (engine.jack ());
CPPUNIT_ASSERT (engine.start () == 0);
-
+
Session session (engine, "tmp_session", "tmp_session");
engine.set_session (&session);
WaveViewTest::make_canvas ()
{
/* this leaks various things, but hey ho */
-
+
_canvas = new ImageCanvas (Duple (256, 256));
_wave_view = new WaveView (_canvas->root(), _audio_region);
_wave_view->set_frames_per_pixel ((double) (44100 / 1000) / 64);
gets called once; there are various singletons etc. in Ardour which don't
like being recreated.
*/
-
+
render_all_at_once ();
render_in_pieces ();
cache ();
WaveViewTest::render_all_at_once ()
{
make_canvas ();
-
+
_canvas->render_to_image (Rect (0, 0, 256, 256));
_canvas->write_to_png ("waveview_1.png");
WaveViewTest::cache ()
{
make_canvas ();
-
+
/* Whole of the render area needs caching from scratch */
-
+
_wave_view->invalidate_whole_cache ();
-
+
Rect whole (0, 0, 256, 256);
_canvas->render_to_image (whole);
CPPUNIT_ASSERT (_wave_view->_cache.front()->end() == 256);
_wave_view->invalidate_whole_cache ();
-
+
/* Render a bit in the middle */
Rect part1 (128, 0, 196, 256);
/* Now render the whole thing and check that the cache sorts itself out */
_canvas->render_to_image (whole);
-
+
CPPUNIT_ASSERT (_wave_view->_cache.size() == 3);
list<WaveView::CacheEntry*>::iterator i = _wave_view->_cache.begin ();
-
+
CPPUNIT_ASSERT ((*i)->start() == 0);
CPPUNIT_ASSERT ((*i)->end() == 128);
++i;
g.set_position (Duple (64, 72));
Line l (&g);
l.set (Duple (41, 43), Duple (44, 46));
-
+
XMLTree* tree = canvas.get_state ();
tree->write ("test.xml");
void get ();
void set ();
-private:
+private:
void check (std::string const &);
};
Text::set (string const & text)
{
begin_change ();
-
+
_text = text;
_need_redraw = true;
#else
_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _width, _height);
#endif
-
+
Cairo::RefPtr<Cairo::Context> img_context = Cairo::Context::create (_image);
#ifdef __APPLE__
*/
img_context->scale (2, 2);
#endif
-
+
/* and draw, in the appropriate color of course */
if (_outline) {
Rect self = item_to_window (Rect (0, 0, min (_clamped_width, (double)_image->get_width ()), _image->get_height ()));
boost::optional<Rect> i = self.intersection (area);
-
+
if (!i) {
return;
}
if (_need_redraw) {
_redraw ();
}
-
+
Rect intersection (i.get());
context->rectangle (intersection.x0, intersection.y0, intersection.width(), intersection.height());
Text::set_alignment (Pango::Alignment alignment)
{
begin_change ();
-
+
_alignment = alignment;
_need_redraw = true;
_bounding_box_dirty = true;
Text::set_font_description (Pango::FontDescription font_description)
{
begin_change ();
-
+
_font_description = new Pango::FontDescription (font_description);
_need_redraw = true;
_width_correction = -1.0;
end_change ();
}
-
+
void
Text::dump (ostream& o) const
{
pos = pos.translate (offset);
/* keep inside the window */
-
+
Rect r (0, 0, _canvas->width(), _canvas->height());
/* border of 200 pixels on the right, and 50 on all other sides */
r.y1 = std::max (r.y0, (r.y1 - border));
/* clamp */
-
+
if (pos.x < r.x0) {
pos.x = r.x0;
} else if (pos.x > r.x1) {
// extending the segment, parameterized as p1 + (t * (p2 - p1)),
// we find projection of point p onto the line.
// It falls where t = [(p - p1) . (p2 - p1)] / |p2 - p1|^2
-
+
t = ((dp1x * dx) + (dp1y * dy)) / segLenSquared;
if (t < kEpsilon) {
const double effective_height = _height;
/* remember: canvas (and cairo) coordinate space puts the origin at the upper left.
-
+
So, a sample value of 1.0 (0dbFS) will be computed as:
(1.0 - 1.0) * 0.5 * effective_height
tips.top = center - spread;
tips.bot = center + spread;
}
-
+
tips.top = min (effective_height, max (0.0, tips.top));
tips.bot = min (effective_height, max (0.0, tips.bot));
}
-
+
Coord
WaveView::y_extent (double s) const
} else {
p.min = 0.0;
}
-
+
compute_tips (p, tips[i]);
tips[i].spread = tips[i].bot - tips[i].top;
}
if (req->should_stop()) {
return;
}
-
+
Color alpha_one = rgba_to_color (0, 0, 0, 1.0);
set_source_rgba (wave_context, alpha_one);
wave_context->move_to (i, tips[i].top);
wave_context->line_to (i, tips[i].bot);
}
-
+
/* draw square waves and other discontiguous points clearly */
if (i > 0) {
if (tips[i-1].top + 2 < tips[i].top) {
if (req->should_stop()) {
return;
}
-
+
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create (image);
/* Here we set a source colour and use the various components as a mask. */
if (req->should_stop()) {
return;
}
-
+
context->mask (images.wave, 0, 0);
context->fill ();
req->end,
req->image));
images->add (_region->audio_source (_channel), ret);
-
+
/* consolidate cache first (removes fully-contained
* duplicate images)
*/
-
+
images->consolidate_image_cache (_region->audio_source (_channel),
req->channel, req->height, req->amplitude,
req->fill_color, req->samples_per_pixel);
boost::shared_ptr<WaveViewCache::Entry> ret;
full_image = true;
-
+
/* this is called from a ::render() call, when we need an image to
draw with.
*/
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1 needs image from %2 .. %3\n", name, start, end));
-
-
+
+
{
Glib::Threads::Mutex::Lock lmq (request_queue_lock);
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1 CR %2 stop? %3 image %4\n", this, current_request,
(current_request ? current_request->should_stop() : false),
(current_request ? current_request->image : 0)));
-
+
if (current_request && !current_request->should_stop() && current_request->image) {
/* put the image into the cache so that other
*/
if (current_request->start <= start && current_request->end >= end) {
-
+
ret.reset (new WaveViewCache::Entry (current_request->channel,
current_request->height,
current_request->amplitude,
current_request->start,
current_request->end,
current_request->image));
-
+
cache_request_result (current_request);
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: got image from completed request, spans %2..%3\n",
name, current_request->start, current_request->end));
if (!ret) {
/* no current image draw request, so look in the cache */
-
+
ret = get_image_from_cache (start, end, full_image);
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: lookup from cache gave %2 (full %3)\n",
name, ret, full_image));
}
-
-
+
+
if (!ret || !full_image) {
if ((rendered && get_image_in_thread) || always_get_image_in_thread) {
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: generating image in caller thread\n", name));
-
+
boost::shared_ptr<WaveViewThreadRequest> req (new WaveViewThreadRequest);
req->type = WaveViewThreadRequest::Draw;
req->width = desired_image_width ();
/* draw image in this (the GUI thread) */
-
+
generate_image (req, false);
/* cache the result */
/* reset this so that future missing images are
* generated in a a worker thread.
*/
-
+
get_image_in_thread = false;
} else {
* width by using an image sample count of the screen width added
* on each side of the desired image center.
*/
-
+
const framepos_t center = req->start + ((req->end - req->start) / 2);
const framecnt_t image_samples = req->width;
-
+
/* we can request data from anywhere in the Source, between 0 and its length
*/
-
+
framepos_t sample_start = max (_region_start, (center - image_samples));
framepos_t sample_end = min (center + image_samples, region_end());
const int n_peaks = llrintf ((sample_end - sample_start)/ (req->samples_per_pixel));
-
+
boost::scoped_array<ARDOUR::PeakData> peaks (new PeakData[n_peaks]);
/* Note that Region::read_peaks() takes a start position based on an
offset into the Region's **SOURCE**, rather than an offset into
the Region itself.
*/
-
+
framecnt_t peaks_read = _region->read_peaks (peaks.get(), n_peaks,
sample_start, sample_end - sample_start,
req->channel,
req->samples_per_pixel);
-
+
req->image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, n_peaks, req->height);
/* make sure we record the sample positions that were actually used */
req->start = sample_start;
req->end = sample_end;
-
+
if (peaks_read > 0) {
/* region amplitude will have been used to generate the
* amplitude_above_axis. So apply that here before
* rendering.
*/
-
+
if (_amplitude_above_axis != 1.0) {
for (framecnt_t i = 0; i < n_peaks; ++i) {
peaks[i].max *= _amplitude_above_axis;
}
} else {
cerr << "Request stopped before image generation\n";
- }
-
+ }
+
if (in_render_thread && !req->should_stop()) {
DEBUG_TRACE (DEBUG::WaveView, string_compose ("done with request for %1 at %2 CR %3 req %4 range %5 .. %6\n", this, g_get_monotonic_time(), current_request, req, req->start, req->end));
const_cast<WaveView*>(this)->ImageReady (); /* emit signal */
WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
{
assert (_samples_per_pixel != 0);
-
+
if (!_region) {
return;
}
* window coordinates. It begins at zero (in item coordinates for this
* waveview, and extends to region_length() / _samples_per_pixel.
*/
-
+
Rect self = item_to_window (Rect (0.0, 0.0, region_length() / _samples_per_pixel, _height));
// cerr << name << " RENDER " << area << " self = " << self << endl;
-
+
/* Now lets get the intersection with the area we've been asked to draw */
boost::optional<Rect> d = self.intersection (area);
/* "draw" is now a rectangle that defines the rectangle we need to
* update/render the waveview into, in window coordinate space.
*/
-
+
/* window coordinates - pixels where x=0 is the left edge of the canvas
* window. We round down in case we were asked to
* draw "between" pixels at the start and/or end.
*/
-
+
double draw_start = floor (draw.x0);
const double draw_end = floor (draw.x1);
// cerr << "Need to draw " << draw_start << " .. " << draw_end << " vs. " << area << " and self = " << self << endl;
-
+
/* image coordnates: pixels where x=0 is the start of this waveview,
* wherever it may be positioned. thus image_start=N means "an image
* that begins N pixels after the start of region that this waveview is
const framepos_t image_start = window_to_image (self.x0, draw_start);
const framepos_t image_end = window_to_image (self.x0, draw_end);
-
+
// cerr << "Image/WV space: " << image_start << " .. " << image_end << endl;
-
+
/* sample coordinates - note, these are not subject to rounding error
*
* "sample_start = N" means "the first sample we need to represent is N
* samples after the first sample of the region"
*/
-
+
framepos_t sample_start = _region_start + (image_start * _samples_per_pixel);
framepos_t sample_end = _region_start + (image_end * _samples_per_pixel);
-
+
// cerr << "Sample space: " << sample_start << " .. " << sample_end << " @ " << _samples_per_pixel << " rs = " << _region_start << endl;
/* sample_start and sample_end are bounded by the region
*/
sample_end = min (region_end(), sample_end);
-
+
// cerr << debug_name() << " will need image spanning " << sample_start << " .. " << sample_end << " region spans " << _region_start << " .. " << region_end() << endl;
double image_origin_in_self_coordinates;
boost::shared_ptr<WaveViewCache::Entry> image_to_draw;
-
+
Glib::Threads::Mutex::Lock lci (current_image_lock);
if (_current_image) {
/* check it covers the right sample range */
-
+
if (_current_image->start > sample_start || _current_image->end < sample_end) {
/* doesn't cover the area we need ... reset */
_current_image.reset ();
image_to_draw = get_image (sample_start, sample_end, full_image);
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1 image to draw = %2 (full? %3)\n", name, image_to_draw, full_image));
-
+
if (!image_to_draw) {
/* image not currently available. A redraw will be scheduled
when it is ready.
*/
image_origin_in_self_coordinates = (image_to_draw->start - _region_start) / _samples_per_pixel;
-
+
if (_start_shift && (sample_start == _region_start) && (self.x0 == draw.x0)) {
/* we are going to draw the first pixel for this region, but
we may not want this to overlap a border around the
//draw_start += _start_shift;
//image_origin_in_self_coordinates += _start_shift;
}
-
+
/* the image may only be a best-effort ... it may not span the entire
* range requested, though it is guaranteed to cover the start. So
* determine how many pixels we can actually draw.
*/
double draw_width;
-
+
if (image_to_draw != _current_image) {
lci.release ();
* will appear. So specifying (10,10) will put the upper left corner of
* the image at (10,10) in user space.
*/
-
+
context->set_source (image_to_draw->image, x, y);
context->fill ();
invalidate_image_cache ();
_height = height;
get_image_in_thread = true;
-
+
_bounding_box_dirty = true;
end_change ();
}
/* try to stop any current rendering of the request, or prevent it from
* ever starting up.
*/
-
+
if (current_request) {
current_request->cancel ();
}
-
+
Glib::Threads::Mutex::Lock lm (request_queue_lock);
/* now remove it from the queue and reset our request pointer so that
have no outstanding request (that we know about)
*/
-
+
request_queue.erase (this);
current_request.reset ();
DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1 now has no request %2\n", this));
while (run) {
/* remember that we hold the lock at this point, no matter what */
-
+
if (g_atomic_int_get (&drawing_thread_should_quit)) {
break;
}
/* remove the request from the queue (remember: the "request"
* is just a pointer to a WaveView object)
*/
-
+
requestor = *(request_queue.begin());
request_queue.erase (request_queue.begin());
bool& full_coverage)
{
ImageCache::iterator x;
-
+
if ((x = cache_map.find (src)) == cache_map.end ()) {
/* nothing in the cache for this audio source at all */
return boost::shared_ptr<WaveViewCache::Entry> ();
CacheLine& caches = x->second;
boost::shared_ptr<Entry> best_partial;
framecnt_t max_coverage = 0;
-
+
/* Find a suitable ImageSurface, if it exists.
*/
for (CacheLine::iterator c = caches.begin(); c != caches.end(); ++c) {
boost::shared_ptr<Entry> e (*c);
-
+
if (channel != e->channel
|| height != e->height
|| amplitude != e->amplitude
ImageCache::iterator x;
/* MUST BE CALLED FROM (SINGLE) GUI THREAD */
-
+
if ((x = cache_map.find (src)) == cache_map.end ()) {
return;
}
++nxt;
boost::shared_ptr<Entry> e1 (*c1);
-
+
if (channel != e1->channel
|| height != e1->height
|| amplitude != e1->amplitude
/* doesn't match current properties, ignore and move on
* to the next one.
*/
-
+
other_entries++;
c1 = nxt;
continue;
}
-
+
/* c1 now points to a cached image entry that matches current
* properties. Check all subsequent cached imaged entries to
* see if there are others that also match but represent
++nxt2;
boost::shared_ptr<Entry> e2 (*c2);
-
+
if (e1 == e2 || channel != e2->channel
|| height != e2->height
|| amplitude != e2->amplitude
c2 = nxt2;
continue;
}
-
+
if (e2->start >= e1->start && e2->end <= e1->end) {
/* c2 is fully contained by c1, so delete it */
caches.erase (c2);
WaveViewCache::add (boost::shared_ptr<ARDOUR::AudioSource> src, boost::shared_ptr<Entry> ce)
{
/* MUST BE CALLED FROM (SINGLE) GUI THREAD */
-
+
Cairo::RefPtr<Cairo::ImageSurface> img (ce->image);
image_cache_size += img->get_height() * img->get_width () * 4; /* 4 = bytes per FORMAT_ARGB32 pixel */
WaveViewCache::cache_flush ()
{
/* Build a sortable list of all cache entries */
-
+
CacheList cache_list;
for (ImageCache::const_iterator cm = cache_map.begin(); cm != cache_map.end(); ++cm) {
cache_list.push_back (make_pair (cm->first, *cl));
}
}
-
+
/* sort list in LRU order */
SortByTimestamp sorter;
sort (cache_list.begin(), cache_list.end(), sorter);
ListEntry& le (cache_list.front());
ImageCache::iterator x;
-
+
if ((x = cache_map.find (le.first)) != cache_map.end ()) {
-
+
CacheLine& cl = x->second;
-
+
for (CacheLine::iterator c = cl.begin(); c != cl.end(); ++c) {
-
+
if (*c == le.second) {
DEBUG_TRACE (DEBUG::WaveView, string_compose ("Removing cache line entry for %1\n", x->first->name()));
-
+
/* Remove this entry from this cache line */
cl.erase (c);
-
+
if (cl.empty()) {
/* remove cache line from main cache: no more entries */
cache_map.erase (x);
}
-
+
break;
}
}
-
+
Cairo::RefPtr<Cairo::ImageSurface> img (le.second->image);
uint64_t size = img->get_height() * img->get_width() * 4; /* 4 = bytes per FORMAT_ARGB32 pixel */
-
+
if (image_cache_size > size) {
image_cache_size -= size;
} else {
#else
static const bool show_bg_fades = true;
#endif
-
+
XFadeCurve::XFadeCurve (Canvas* c)
: Item (c)
, points_per_segment (32)
struct _AnimationInfo {
GTimer *timer;
-
+
gdouble start_modifier;
gdouble stop_time;
GtkWidget *widget;
destroy_animation_info_and_weak_unref (gpointer data)
{
AnimationInfo *animation_info = data;
-
+
/* force a last redraw. This is so that if the animation is removed,
* the widget is left in a sane state. */
force_widget_redraw (animation_info->widget);
-
+
g_object_weak_unref (G_OBJECT (animation_info->widget), on_animated_widget_destruction, data);
animation_info_destroy (animation_info);
}
{
if (animated_widgets)
return g_hash_table_lookup (animated_widgets, widget);
-
+
return NULL;
}
add_animation (const GtkWidget *widget, gdouble stop_time)
{
AnimationInfo *value;
-
+
/* object already in the list, do not add it twice */
if (lookup_animation_info (widget))
return;
-
+
if (animated_widgets == NULL)
animated_widgets = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, destroy_animation_info_and_weak_unref);
-
+
value = g_new(AnimationInfo, 1);
-
+
value->widget = (GtkWidget*) widget;
-
+
value->timer = g_timer_new ();
value->stop_time= stop_time;
value->start_modifier = 0.0;
g_object_weak_ref (G_OBJECT (widget), on_animated_widget_destruction, value);
g_hash_table_insert (animated_widgets, (GtkWidget*) widget, value);
-
+
start_timer ();
}
{
AnimationInfo *animation_info;
GtkWidget *widget = key;
-
+
animation_info = value;
(void) user_data;
-
+
g_assert ((widget != NULL) && (animation_info != NULL));
-
+
/* remove the widget from the hash table if it is not drawable */
if (!GTK_WIDGET_DRAWABLE (widget))
{
return TRUE;
}
-
+
if (GE_IS_PROGRESS_BAR (widget))
{
gfloat fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (widget));
-
+
/* stop animation for filled/not filled progress bars */
if (fraction <= 0.0 || fraction >= 1.0)
return TRUE;
}
-
+
force_widget_redraw (widget);
-
+
/* stop at stop_time */
if (animation_info->stop_time != 0 &&
g_timer_elapsed (animation_info->timer, NULL) > animation_info->stop_time)
return TRUE;
-
+
return FALSE;
}
animation_timeout_handler (gpointer data)
{
(void) data;
-
+
/*g_print("** TICK **\n");*/
-
+
/* enter threads as update_animation_info will use gtk/gdk. */
gdk_threads_enter ();
g_hash_table_foreach_remove (animated_widgets, update_animation_info, NULL);
/* leave threads again */
gdk_threads_leave ();
-
+
if(g_hash_table_size(animated_widgets)==0)
{
stop_timer ();
return FALSE;
}
-
+
return TRUE;
}
{
AnimationInfo *animation_info;
(void) data;
-
+
animation_info = lookup_animation_info (widget);
-
+
if (animation_info != NULL)
{
gfloat elapsed = g_timer_elapsed (animation_info->timer, NULL);
-
+
animation_info->start_modifier = elapsed - animation_info->start_modifier;
}
else
on_connected_widget_destruction (gpointer data, GObject *widget)
{
(void) widget;
-
+
connected_widgets = g_slist_remove (connected_widgets, data);
g_free (data);
}
while (item != NULL)
{
SignalInfo *signal_info = (SignalInfo*) item->data;
-
+
g_signal_handler_disconnect (signal_info->widget, signal_info->handler_id);
g_object_weak_unref (G_OBJECT (signal_info->widget), on_connected_widget_destruction, signal_info);
g_free (signal_info);
-
+
item = g_slist_next (item);
}
-
+
g_slist_free (connected_widgets);
connected_widgets = NULL;
}
clearlooks_animation_progressbar_add (GtkWidget *progressbar)
{
gdouble fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progressbar));
-
+
if (fraction < 1.0 && fraction > 0.0)
add_animation ((GtkWidget*) progressbar, 0.0);
}
if (!g_slist_find_custom (connected_widgets, widget, find_signal_info))
{
SignalInfo * signal_info = g_new (SignalInfo, 1);
-
+
signal_info->widget = widget;
signal_info->handler_id = g_signal_connect ((GObject*)widget, "toggled", G_CALLBACK (on_checkbox_toggle), NULL);
-
+
connected_widgets = g_slist_append (connected_widgets, signal_info);
g_object_weak_ref (G_OBJECT (widget), on_connected_widget_destruction, signal_info);
}
clearlooks_animation_elapsed (gpointer data)
{
AnimationInfo *animation_info = lookup_animation_info (data);
-
+
if (animation_info)
return g_timer_elapsed (animation_info->timer, NULL)
- animation_info->start_modifier;
clearlooks_animation_cleanup (void)
{
disconnect_all_signals ();
-
+
if (animated_widgets != NULL)
{
g_hash_table_destroy (animated_widgets);
animated_widgets = NULL;
}
-
+
stop_timer ();
}
#else /* !HAVE_ANIMATION */
}
*brightness = (max + min) / 2;
-
+
if (fabs(max - min) < 0.0001)
{
*hue = 0;
*saturation = 0;
- }
+ }
else
{
if (*brightness <= 0.5)
gdouble m1, m2, m3;
if (!color) return;
-
+
if (brightness <= 0.5)
m2 = brightness * (1 + saturation);
else
hue_shift[1] = hue;
hue_shift[2] = hue - 120;
- color_shift[0] = color_shift[1] = color_shift[2] = brightness;
+ color_shift[0] = color_shift[1] = color_shift[2] = brightness;
i = (saturation == 0)?3:0;
color_shift[i] = m1 + (m2 - m1) * (240 - m3) / 60;
else
color_shift[i] = m1;
- }
+ }
color->r = color_shift[0];
color->g = color_shift[1];
- color->b = color_shift[2];
- color->a = 1.0;
+ color->b = color_shift[2];
+ color->a = 1.0;
}
void
saturation = MAX(saturation, 0.0);
ge_color_from_hsb (hue, saturation, brightness, composite);
- composite->a = base->a;
+ composite->a = base->a;
}
void
saturation = MAX(saturation, 0.0);
ge_color_from_hsb (hue, saturation, brightness, composite);
- composite->a = base->a;
+ composite->a = base->a;
}
void
{
g_return_if_fail (cr && color);
- cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
+ cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);
}
void
{
g_return_if_fail (pattern && color);
- cairo_pattern_add_color_stop_rgba (pattern, offset, color->r, color->g, color->b, color->a);
+ cairo_pattern_add_color_stop_rgba (pattern, offset, color->r, color->g, color->b, color->a);
}
void
ge_shade_color(color, shade, &shaded);
}
- ge_cairo_pattern_add_color_stop_color(pattern, offset, &shaded);
+ ge_cairo_pattern_add_color_stop_color(pattern, offset, &shaded);
}
/* This function will draw a rounded corner at position x,y. If the radius
cairo_move_to (cr, x+radius, y);
else
cairo_move_to (cr, x, y);
-
+
if (corners & CR_CORNER_TOPRIGHT)
cairo_arc (cr, x+w-radius, y+radius, radius, G_PI * 1.5, G_PI * 2);
else
cairo_line_to (cr, x+w, y);
-
+
if (corners & CR_CORNER_BOTTOMRIGHT)
cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, G_PI * 0.5);
else
cairo_line_to (cr, x+w, y+h);
-
+
if (corners & CR_CORNER_BOTTOMLEFT)
cairo_arc (cr, x+radius, y+h-radius, radius, G_PI * 0.5, G_PI);
else
cairo_line_to (cr, x, y+h);
-
+
if (corners & CR_CORNER_TOPLEFT)
cairo_arc (cr, x+radius, y+radius, radius, G_PI, G_PI * 1.5);
else
g_return_if_fail (cr != NULL);
g_return_if_fail (tl != NULL);
g_return_if_fail (br != NULL);
-
+
solid_color = (tl == br) || ((tl->r == br->r) && (tl->g == br->g) && (tl->b == br->b) && (tl->a == br->a));
if (topleft_overlap)
{
- ge_cairo_set_color(cr, br);
+ ge_cairo_set_color(cr, br);
cairo_move_to(cr, x + 0.5, y + height - 0.5);
cairo_line_to(cr, x + width - 0.5, y + height - 0.5);
cairo_line_to(cr, x + width - 0.5, y + 0.5);
-
+
cairo_stroke (cr);
}
- ge_cairo_set_color(cr, tl);
+ ge_cairo_set_color(cr, tl);
cairo_move_to(cr, x + 0.5, y + height - 0.5);
cairo_line_to(cr, x + 0.5, y + 0.5);
if (!solid_color)
{
cairo_stroke(cr);
- ge_cairo_set_color(cr, br);
+ ge_cairo_set_color(cr, br);
}
cairo_move_to(cr, x + 0.5, y + height - 0.5);
cairo_save(cr);
- ge_cairo_set_color(cr, color);
+ ge_cairo_set_color(cr, color);
cairo_move_to(cr, points[0].x, points[0].y);
for (i = 1; i < npoints; i++)
cairo_line_to(cr, points[i].x, points[i].y);
}
}
-
+
if ((points[npoints-1].x != points[0].x) ||
(points[npoints-1].y != points[0].y))
{
{
cairo_save(cr);
- ge_cairo_set_color(cr, color);
+ ge_cairo_set_color(cr, color);
cairo_set_line_width (cr, 1);
cairo_move_to(cr, x1 + 0.5, y1 + 0.5);
gint *height)
{
cairo_matrix_t matrix;
-
+
cairo_matrix_init_identity (&matrix);
-
+
cairo_translate (cr, *x, *y);
*x = 0;
*y = 0;
-
+
if (mirror & CR_MIRROR_HORIZONTAL)
{
cairo_matrix_scale (&matrix, -1, 1);
cairo_matrix_init (&matrix, 0, 1, 1, 0, 0, 0);
cairo_transform (cr, &matrix);
-
+
/* swap width/height */
tmp = *width;
*x = 0;
***********************************************/
CairoPattern*
ge_cairo_color_pattern(CairoColor *base)
-{
+{
CairoPattern * result = g_new0(CairoPattern, 1);
#if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2)))
base->a);
result->operator = CAIRO_OPERATOR_SOURCE;
-
+
return result;
}
***********************************************/
CairoPattern*
ge_cairo_pixbuf_pattern(GdkPixbuf *pixbuf)
-{
+{
CairoPattern * result = g_new0(CairoPattern, 1);
cairo_t *canvas;
width = gdk_pixbuf_get_width(pixbuf);
height = gdk_pixbuf_get_height(pixbuf);
-
+
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
canvas = cairo_create(surface);
***********************************************/
CairoPattern*
ge_cairo_pixmap_pattern(GdkPixmap *pixmap)
-{
+{
CairoPattern * result = NULL;
GdkPixbuf * pixbuf;
0, 0, 0, 0, width, height);
result = ge_cairo_pixbuf_pattern(pixbuf);
-
+
g_object_unref (pixbuf);
return result;
gboolean vertical)
{
CairoPattern * result = g_new0(CairoPattern, 1);
-
+
#if ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2)))
result->type = CAIRO_PATTERN_TYPE_LINEAR;
#endif
{
if (pattern->handle)
cairo_pattern_destroy(pattern->handle);
-
+
g_free(pattern);
}
}
g_module_check_init (GModule *module)
{
(void) module;
-
+
return gtk_check_version (GTK_MAJOR_VERSION,
GTK_MINOR_VERSION,
GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
ge_shade_color (&colors->shade[6], 0.92, &shadow);
cairo_set_line_width (cr, 1.0);
-
+
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1);
-
+
cairo_move_to (cr, width, radius);
ge_cairo_rounded_corner (cr, width, height, radius, CR_CORNER_BOTTOMRIGHT);
cairo_line_to (cr, radius, height);
width -= 3;
height -= 3;
-
+
cairo_save (cr);
-
+
/* Top/Left highlight */
if (corners & CR_CORNER_BOTTOMLEFT)
cairo_move_to (cr, x, y+height-radius);
else
cairo_move_to (cr, x, y+height);
-
+
ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT);
if (corners & CR_CORNER_TOPRIGHT)
cairo_line_to (cr, x+width-radius, y);
else
cairo_line_to (cr, x+width, y);
-
+
if (params->shadow & CL_SHADOW_OUT)
ge_cairo_set_color (cr, &hilight);
else
ge_cairo_set_color (cr, &shadow);
-
+
cairo_stroke (cr);
-
+
/* Bottom/Right highlight -- this includes the corners */
cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */
ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT);
ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT);
ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT);
-
+
if (params->shadow & CL_SHADOW_OUT)
ge_cairo_set_color (cr, &shadow);
else
ge_cairo_set_color (cr, &hilight);
-
+
cairo_stroke (cr);
-
+
cairo_restore (cr);
}
pattern = cairo_pattern_create_linear (0, 0, width, height);
cairo_pattern_add_color_stop_rgb (pattern, 0, color->r, color->g, color->b);
cairo_pattern_add_color_stop_rgb (pattern, 1, bottom_shade.r, bottom_shade.g, bottom_shade.b);
-
+
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
}
{
xoff = x -(xr * 3 / 2) + 3 * i;
yoff = y -(yr * 3 / 2) + 3 * j;
-
+
cairo_rectangle (cr, width/2+0.5+xoff, height/2+0.5+yoff, 2, 2);
cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.8+contrast);
cairo_fill (cr);
CairoColor shadow;
ge_shade_color (border_normal, 0.925, &shadow);
-
+
cairo_save (cr);
-
+
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, 0.5, 0.5);
params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners);
cairo_translate (cr, -0.5, -0.5);
- }
-
+ }
+
ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1,
width-(xoffset*2)-2,
height-(yoffset*2)-2,
radius, params->corners);
-
+
if (!params->active)
{
cairo_pattern_t *pattern;
gdouble shade_size = ((100.0/height)*8.0)/100.0;
CairoColor top_shade, bottom_shade, middle_shade;
-
+
ge_shade_color (fill, 1.1, &top_shade);
ge_shade_color (fill, 0.98, &middle_shade);
ge_shade_color (fill, 0.93, &bottom_shade);
-
+
pattern = cairo_pattern_create_linear (0, 0, 0, height);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, top_shade.r, top_shade.g, top_shade.b);
cairo_pattern_add_color_stop_rgb (pattern, shade_size, fill->r, fill->g, fill->b);
else
{
cairo_pattern_t *pattern;
-
+
ge_cairo_set_color (cr, fill);
cairo_fill_preserve (cr);
ge_cairo_set_color (cr, d);
ge_cairo_stroke_rectangle (cr, 3.5, 3.5, width-7, height-7);
}
-
+
ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, width-(xoffset*2)-1, height-(yoffset*2)-1, radius, params->corners);
if (params->disabled)
clearlooks_set_border_gradient (cr, border_normal, 1.32, 0, height);
else
ge_cairo_set_color (cr, border_normal);
-
+
cairo_stroke (cr);
-
+
/* Draw the "shadow" */
if (!params->active)
{
cairo_line_to (cr, width-params->xthickness, height - params->ythickness - 1);
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1);
cairo_stroke (cr);
-
+
/* Draw topleft shadow */
clearlooks_draw_top_left_highlight (cr, fill, params, width, height, radius);
}
const CairoColor *base = &colors->base[params->state_type];
CairoColor border = colors->shade[params->disabled ? 4 : 6];
double radius = MIN (params->radius, MIN ((width - 4.0) / 2.0, (height - 4.0) / 2.0));
-
+
if (params->focus)
border = colors->spot[2];
cairo_translate (cr, x+0.5, y+0.5);
cairo_set_line_width (cr, 1.0);
-
+
/* Fill the background (shouldn't have to) */
cairo_rectangle (cr, -0.5, -0.5, width, height);
ge_cairo_set_color (cr, ¶ms->parentbg);
cairo_rectangle (cr, 1.5, 1.5, width-4, height-4);
ge_cairo_set_color (cr, base);
cairo_fill (cr);
-
+
params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners);
/* Draw the inner shadow */
ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 0.8, &shadow);
cairo_translate (cr, x+1, y+1);
-
+
ge_cairo_rounded_rectangle (cr, 1, 1, width-4, height-4, radius, params->corners);
-
+
ge_cairo_set_color (cr, &colors->bg[params->state_type]);
-
+
cairo_fill_preserve (cr);
-
+
pattern = cairo_pattern_create_linear (0, 0, 0, height);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, shadow.r, shadow.g, shadow.b);
cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0);
-
+
cairo_set_source (cr, pattern);
cairo_fill (cr);
-
+
cairo_pattern_destroy (pattern);
}
cairo_pattern_add_color_stop_rgb (pattern, 0.0, c1->r, c1->g, c1->b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, c2->r, c2->g, c2->b);
- cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1);
+ cairo_rectangle (cr, x+0.5, y+0.5, width-1, height-1);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
ge_cairo_set_color (cr, c3);
- ge_cairo_stroke_rectangle (cr, x, y, width, height);
+ ge_cairo_stroke_rectangle (cr, x, y, width, height);
}
#define TROUGH_SIZE 6
{
trough_width = width-3;
trough_height = TROUGH_SIZE-2;
-
+
translate_x = x + 0.5;
translate_y = y + 0.5 + (height/2) - (TROUGH_SIZE/2);
}
{
trough_width = TROUGH_SIZE-2;
trough_height = height-3;
-
+
translate_x = x + 0.5 + (width/2) - (TROUGH_SIZE/2);
translate_y = y + 0.5;
}
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, translate_x, translate_y);
-
+
if (!slider->fill_level)
params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0);
-
+
cairo_translate (cr, 1, 1);
-
+
if (!slider->lower && ! slider->fill_level)
clearlooks_scale_draw_gradient (cr, &colors->shade[3], /* top */
&colors->shade[2], /* bottom */
cairo_pattern_t *pattern;
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
if (params->prelight)
if (params->prelight)
{
CairoColor highlight;
- ge_shade_color (spot, 1.5, &highlight);
+ ge_shade_color (spot, 1.5, &highlight);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, highlight.r, highlight.g, highlight.b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, spot->r, spot->g, spot->b);
cairo_set_source (cr, pattern);
{
cairo_move_to (cr, 6, 0.5);
cairo_line_to (cr, 6, height-1);
-
+
cairo_move_to (cr, width-7, 0.5);
cairo_line_to (cr, width-7, height-1);
-
+
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgba (cr, border->r,
border->g,
{
double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
cairo_set_line_width (cr, 1.0);
-
+
if (!slider->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
cairo_translate (cr, x+0.5, y+0.5);
CairoColor shadow;
cairo_pattern_t *pattern;
double radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));
-
+
cairo_save (cr);
cairo_set_line_width (cr, 1.0);
-
+
/* Fill with bg color */
ge_cairo_set_color (cr, &colors->bg[params->state_type]);
-
- cairo_rectangle (cr, x, y, width, height);
+
+ cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
/* Create trough box */
/* Top shadow */
cairo_rectangle (cr, x+1, y+1, width-2, 4);
pattern = cairo_pattern_create_linear (x, y, x, y+4);
- cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3);
- cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3);
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
/* Left shadow */
cairo_rectangle (cr, x+1, y+1, 4, height-2);
pattern = cairo_pattern_create_linear (x, y, x+4, y);
- cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3);
- cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.);
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.3);
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
stroke_width = height*2;
x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */
-
+
cairo_translate (cr, x, y);
cairo_save (cr);
cairo_line_to (cr, stroke_width-x_step, 0);
cairo_line_to (cr, stroke_width/2-x_step, height);
cairo_line_to (cr, -x_step, height);
-
+
cairo_translate (cr, stroke_width, 0);
tile_pos += stroke_width;
}
-
+
cairo_set_source_rgba (cr, colors->spot[2].r,
colors->spot[2].g,
colors->spot[2].b,
0.15);
-
+
cairo_fill (cr);
cairo_restore (cr); /* rounded clip region */
ge_cairo_set_color (cr, &shadow);
cairo_stroke (cr);
}
-
+
cairo_restore (cr);
cairo_restore (cr); /* rotation, mirroring */
{
SeparatorParameters separator;
int offset = params->ythickness + 1;
-
+
params->style_functions->draw_button (cr, colors, params, x, y, width, height);
-
+
separator.horizontal = FALSE;
params->style_functions->draw_separator (cr, colors, params, &separator, x+optionmenu->linepos, y + offset, 2, height - offset*2);
}
int x, int y, int width, int height)
{
(void) widget;
-
+
cairo_save (cr);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
ge_cairo_set_color (cr, &colors->shade[5]);
(void) menubar;
ge_shade_color (&colors->bg[0], 0.96, &lower);
-
+
cairo_translate (cr, x, y);
cairo_rectangle (cr, 0, 0, width, height);
-
+
/* Draw the gradient */
pattern = cairo_pattern_create_linear (0, 0, 0, height);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, colors->bg[0].r,
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
/* Draw bottom line */
cairo_set_line_width (cr, 1.0);
cairo_move_to (cr, 0, height-0.5);
{
(void) x;
(void) y;
-
+
if (frame->gap_side == CL_GAP_TOP)
{
CLEARLOOKS_RECTANGLE_SET ((*bevel), 1.5 + frame->gap_x, -0.5,
CLEARLOOKS_RECTANGLE_SET ((*bevel), 1.5 + frame->gap_x, height - 2.5,
frame->gap_width - 3, 2.0);
CLEARLOOKS_RECTANGLE_SET ((*border), 0.5 + frame->gap_x, height - 1.5,
- frame->gap_width - 2, 2.0);
+ frame->gap_width - 2, 2.0);
}
else if (frame->gap_side == CL_GAP_LEFT)
{
CLEARLOOKS_RECTANGLE_SET ((*bevel), -0.5, 1.5 + frame->gap_x,
2.0, frame->gap_width - 3);
CLEARLOOKS_RECTANGLE_SET ((*border), -0.5, 0.5 + frame->gap_x,
- 1.0, frame->gap_width - 2);
+ 1.0, frame->gap_width - 2);
}
else if (frame->gap_side == CL_GAP_RIGHT)
{
CLEARLOOKS_RECTANGLE_SET ((*bevel), width - 2.5, 1.5 + frame->gap_x,
2.0, frame->gap_width - 3);
CLEARLOOKS_RECTANGLE_SET ((*border), width - 1.5, 0.5 + frame->gap_x,
- 1.0, frame->gap_width - 2);
+ 1.0, frame->gap_width - 2);
}
}
CairoColor hilight;
ge_shade_color (&colors->bg[GTK_STATE_NORMAL], 1.05, &hilight);
-
+
if (frame->shadow == CL_SHADOW_NONE) {
const CairoColor *bg = &colors->bg[params->state_type];
ge_cairo_set_color (cr, bg);
cairo_stroke (cr);
return;
}
-
+
if (frame->gap_x != -1)
clearlooks_get_frame_gap_clip (x, y, width, height,
frame, &bevel_clip, &frame_clip);
-
+
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x+0.5, y+0.5);
-
+
/* save everything */
cairo_save (cr);
/* Set clip for the bevel */
cairo_rectangle (cr, bevel_clip.x, bevel_clip.y, bevel_clip.width, bevel_clip.height);
cairo_clip (cr);
}
-
+
/* Draw the bevel */
if (frame->shadow == CL_SHADOW_ETCHED_IN || frame->shadow == CL_SHADOW_ETCHED_OUT)
{
shadow.shadow = frame->shadow;
clearlooks_draw_highlight_and_shade (cr, colors, &shadow, width, height, 0);
}
-
+
/* restore the previous clip region */
cairo_restore (cr);
cairo_save (cr);
CairoColor hilight;
cairo_pattern_t *pattern;
-
+
double radius;
double strip_size;
cairo_clip (cr);
cairo_new_path (cr);
- /* Translate and set line width */
+ /* Translate and set line width */
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x+0.5, y+0.5);
{
height += 3.0;
strip_size = 2.0/height; /* 2 pixel high strip */
-
+
if (tab->gap_side == CL_GAP_TOP)
cairo_translate (cr, 0.0, -3.0); /* gap at the other side */
}
{
width += 3.0;
strip_size = 2.0/width;
-
+
if (tab->gap_side == CL_GAP_LEFT)
cairo_translate (cr, -3.0, 0.0); /* gap at the other side */
}
-
+
/* Set the fill color */
fill = &colors->bg[params->state_type];
/* Set tab shape */
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1,
radius, params->corners);
-
+
/* Draw fill */
ge_cairo_set_color (cr, fill);
cairo_fill (cr);
if (!params->active)
{
ShadowParameters shadow;
-
+
shadow.shadow = CL_SHADOW_OUT;
shadow.corners = params->corners;
-
+
clearlooks_draw_highlight_and_shade (cr, colors, &shadow,
width,
height, radius);
}
-
+
if (params->active)
{
tab->gap_side == CL_GAP_BOTTOM ? height : 0 );
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
ge_shade_color (fill, 0.92, &shadow);
cairo_pattern_add_color_stop_rgba (pattern, 0.0, hilight.r, hilight.g, hilight.b, 0.4);
tab->gap_side == CL_GAP_TOP ? height-2 : 0,
tab->gap_side == CL_GAP_RIGHT ? width : 0,
tab->gap_side == CL_GAP_BOTTOM ? height : 0 );
-
+
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_fill->r, stripe_fill->g, stripe_fill->b);
}
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
if (params->active)
{
ge_cairo_set_color (cr, border2);
tab->gap_side == CL_GAP_TOP ? height-2 : 2,
tab->gap_side == CL_GAP_RIGHT ? width : 2,
tab->gap_side == CL_GAP_BOTTOM ? height : 2 );
-
+
cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_border->r, stripe_border->g, stripe_border->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, border1->r, border1->g, border1->b);
{
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y+0.5);
-
+
cairo_move_to (cr, 0.0, 0.0);
cairo_line_to (cr, width, 0.0);
ge_cairo_set_color (cr, &color);
cairo_stroke (cr);
-
+
cairo_move_to (cr, 0.0, 1.0);
cairo_line_to (cr, width, 1.0);
ge_cairo_set_color (cr, &hilight);
{
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x+0.5, y);
-
+
cairo_move_to (cr, 0.0, 0.0);
cairo_line_to (cr, 0.0, height);
ge_cairo_set_color (cr, &color);
cairo_stroke (cr);
-
+
cairo_move_to (cr, 1.0, 0.0);
cairo_line_to (cr, 1.0, height);
ge_cairo_set_color (cr, &hilight);
CairoColor hilight;
CairoColor shadow;
- ge_shade_color (border, 1.5, &hilight);
- ge_shade_color (border, 0.925, &shadow);
+ ge_shade_color (border, 1.5, &hilight);
+ ge_shade_color (border, 0.925, &shadow);
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1.0);
-
+
/* Draw highlight */
if (header->order == CL_ORDER_FIRST)
{
}
else
cairo_move_to (cr, 0.0, 0.5);
-
+
cairo_line_to (cr, width, 0.5);
-
+
ge_cairo_set_color (cr, &hilight);
cairo_stroke (cr);
-
+
/* Draw bottom border */
cairo_move_to (cr, 0.0, height-0.5);
cairo_line_to (cr, width, height-0.5);
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
- /* Draw bottom shade */
+ /* Draw bottom shade */
pattern = cairo_pattern_create_linear (0.0, height-5.0, 0.0, height-1.0);
cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.0);
cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.3);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
/* Draw resize grip */
if ((params->ltr && header->order != CL_ORDER_LAST) ||
(!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable)
{
SeparatorParameters separator;
separator.horizontal = FALSE;
-
+
if (params->ltr)
params->style_functions->draw_separator (cr, colors, params, &separator,
width-1.5, 4.0, 2, height-8.0);
(void) widget;
dark = &colors->shade[3];
ge_shade_color (fill, 1.1, &light);
-
+
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
CairoColor fill_shade;
CairoColor border = colors->spot[2];
cairo_pattern_t *pattern;
-
+
ge_shade_color (&border, 1.05, &border);
ge_shade_color (fill, 0.85, &fill_shade);
-
+
cairo_set_line_width (cr, 1.0);
ge_cairo_rounded_rectangle (cr, x + 0.5, y + 0.5, width - 1, height, widget->radius, widget->corners);
CairoColor border;
cairo_pattern_t *pattern;
cairo_save (cr);
-
+
cairo_translate (cr, x, y);
if (params->focus)
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
- ge_shade_color(&upper_color, 0.8, &border);
+
+ ge_shade_color(&upper_color, 0.8, &border);
cairo_move_to (cr, 0, 0.5);
cairo_rel_line_to (cr, width, 0);
CairoColor bg_shade;
cairo_pattern_t *pattern;
const CairoColor *border = &colors->shade[5];
-
+
(void) widget;
bg = &colors->shade[2];
ge_shade_color (bg, 0.95, &bg_shade);
-
+
cairo_set_line_width (cr, 1);
/* cairo_translate (cr, x, y); */
-
+
if (scrollbar->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
- cairo_translate (cr, x, y);
+ cairo_translate (cr, x, y);
/* Draw fill */
cairo_rectangle (cr, 1, 0, width-2, height);
/* Draw shadow */
pattern = cairo_pattern_create_linear (1, 0, 3, 0);
cairo_pattern_add_color_stop_rgb (pattern, 0, bg_shade.r, bg_shade.g, bg_shade.b);
- cairo_pattern_add_color_stop_rgb (pattern, 1.0, bg->r, bg->g, bg->b);
+ cairo_pattern_add_color_stop_rgb (pattern, 1.0, bg->r, bg->g, bg->b);
cairo_rectangle (cr, 1, 0, 4, height);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
/* Draw border */
ge_cairo_set_color (cr, border);
ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
ge_shade_color(&colors->shade[6], 1.05, &border);
-
+
if (scrollbar->horizontal)
{
if (stepper->stepper == CL_STEPPER_A)
else if (stepper->stepper == CL_STEPPER_D)
corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT;
}
-
+
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1);
-
+
ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners);
-
+
if (scrollbar->horizontal)
pattern = cairo_pattern_create_linear (0, 0, 0, height);
else
pattern = cairo_pattern_create_linear (0, 0, width, 0);
-
+
s2 = colors->bg[widget->state_type];
ge_shade_color(&s2, 1.06, &s1);
ge_shade_color(&s2, 0.98, &s3);
ge_shade_color(&s2, 0.94, &s4);
-
+
cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b);
cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b);
cairo_pattern_add_color_stop_rgb(pattern, 0.7, s3.r, s3.g, s3.b);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
cairo_translate (cr, 0.5, 0.5);
clearlooks_draw_top_left_highlight (cr, &s2, widget, width, height, (stepper->stepper == CL_STEPPER_A) ? radius : 0);
cairo_translate (cr, -0.5, -0.5);
-
+
ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners);
clearlooks_set_border_gradient (cr, &border, 1.2, (scrollbar->horizontal ? 0 : width), (scrollbar->horizontal ? height: 0));
cairo_stroke (cr);
-
+
cairo_translate (cr, 0.5, 0.5);
}
else
height += 1;
}
-
+
if (!scrollbar->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
- cairo_translate (cr, x, y);
+ cairo_translate (cr, x, y);
if (scrollbar->has_color)
{
if (widget->prelight)
ge_shade_color (&fill, 1.1, &fill);
-
+
cairo_set_line_width (cr, 1);
-
+
ge_shade_color (&fill, 1.3, &hilight);
ge_shade_color (&fill, 1.1, &shade1);
ge_shade_color (&fill, 1.05, &shade2);
ge_shade_color (&fill, 0.98, &shade3);
-
+
pattern = cairo_pattern_create_linear (1, 1, 1, height-2);
cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b);
cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b);
- cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade3.r, shade3.g, shade3.b);
+ cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade3.r, shade3.g, shade3.b);
cairo_pattern_add_color_stop_rgb (pattern, 1, fill.r, fill.g, fill.b);
cairo_rectangle (cr, 1, 1, width-2, height-2);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5);
ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3);
-
+
ge_cairo_set_color (cr, border);
ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
}
int bar_x, i;
ge_shade_color(&colors->shade[6], 1.05, &border);
-
+
s2 = colors->bg[widget->state_type];
ge_shade_color(&s2, 1.06, &s1);
ge_shade_color(&s2, 0.98, &s3);
ge_shade_color(&s2, 0.94, &s4);
-
+
pattern = cairo_pattern_create_linear(1, 1, 1, height-1);
cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b);
cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b);
cairo_set_source(cr, pattern);
cairo_fill(cr);
cairo_pattern_destroy(pattern);
-
+
clearlooks_set_border_gradient (cr, &border, 1.2, 0, height);
ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
-
+
cairo_move_to (cr, 1.5, height-1.5);
cairo_line_to (cr, 1.5, 1.5);
cairo_line_to (cr, width-1.5, 1.5);
ge_shade_color (&s2, 1.3, &s5);
cairo_set_source_rgba (cr, s5.r, s5.g, s5.b, 0.5);
cairo_stroke(cr);
-
+
/* draw handles */
cairo_set_line_width (cr, 1);
-
+
bar_x = width/2 - 4;
cairo_translate(cr, 0.5, 0.5);
for (i=0; i<3; i++)
cairo_line_to (cr, bar_x, height-5);
ge_cairo_set_color (cr, dark);
cairo_stroke (cr);
-
+
cairo_move_to (cr, bar_x+1, 4);
cairo_line_to (cr, bar_x+1, height-5);
ge_cairo_set_color (cr, light);
cairo_stroke (cr);
-
+
bar_x += 3;
}
}
-
+
}
static void
{
const CairoColor *fill = &colors->bg[params->state_type];
int num_bars = 6; /* shut up gcc warnings */
-
+
switch (handle->type)
{
case CL_HANDLE_TOOLBAR:
ge_cairo_set_color (cr, fill);
cairo_fill (cr);
}
-
+
cairo_translate (cr, x+0.5, y+0.5);
-
+
cairo_set_line_width (cr, 1);
-
+
if (handle->horizontal)
{
params->style_functions->draw_gripdots (cr, colors, 0, 0, width, height, num_bars, 2, 0.1);
cairo_pattern_add_color_stop_rgba (pt, 0.5, shadow.r, shadow.b, shadow.g, 0.5);
cairo_pattern_add_color_stop_rgba (pt, 0.5, highlight.r, highlight.g, highlight.b, 0.5);
cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b);
-
+
cairo_translate (cr, x, y);
-
+
cairo_set_line_width (cr, 2);
- cairo_arc (cr, 7, 7, 6, 0, G_PI*2);
+ cairo_arc (cr, 7, 7, 6, 0, G_PI*2);
cairo_set_source (cr, pt);
cairo_stroke (cr);
cairo_pattern_destroy (pt);
cairo_set_line_width (cr, 1);
- cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2);
-
+ cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2);
+
if (!widget->disabled)
{
ge_cairo_set_color (cr, &colors->base[0]);
cairo_fill_preserve (cr);
}
-
+
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
-
+
if (draw_bullet)
{
if (inconsistent)
cairo_arc (cr, 7, 7, 3, 0, G_PI*2);
ge_cairo_set_color (cr, dot);
cairo_fill (cr);
-
+
cairo_arc (cr, 6, 6, 1, 0, G_PI*2);
cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
cairo_fill (cr);
inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN);
draw_bullet |= inconsistent;
-
+
if (widget->disabled)
{
border = &colors->shade[5];
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1);
-
+
if (widget->xthickness > 2 && widget->ythickness > 2)
{
widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5, width-1, height-1, 1, CR_CORNER_ALL);
-
+
/* Draw the rectangle for the checkbox itself */
ge_cairo_rounded_rectangle (cr, 1.5, 1.5, width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
}
/* Draw the rectangle for the checkbox itself */
ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
}
-
+
if (!widget->disabled)
{
ge_cairo_set_color (cr, &colors->base[0]);
cairo_fill_preserve (cr);
}
-
+
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
cairo_set_line_width (cr, 1.7);
cairo_move_to (cr, 0.5 + (width*0.2), (height*0.5));
cairo_line_to (cr, 0.5 + (width*0.4), (height*0.7));
-
+
cairo_curve_to (cr, 0.5 + (width*0.4), (height*0.7),
0.5 + (width*0.5), (height*0.4),
0.5 + (width*0.70), (height*0.25));
}
-
+
ge_cairo_set_color (cr, dot);
cairo_stroke (cr);
}
arrow_width = MIN (height * 2.0 + MAX (1.0, ceil (height * 2.0 / 6.0 * 2.0) / 2.0) / 2.0, width);
line_width_2 = MAX (1.0, ceil (arrow_width / 6.0 * 2.0) / 2.0) / 2.0;
arrow_height = arrow_width / 2.0 + line_width_2;
-
+
cairo_translate (cr, x, y - arrow_height / 2.0);
cairo_move_to (cr, -arrow_width / 2.0, line_width_2);
cairo_line_to (cr, arrow_width / 2.0, line_width_2);
cairo_line_to (cr, 0, arrow_height);
cairo_close_path (cr);
-
+
ge_cairo_set_color (cr, color);
cairo_fill (cr);
-
+
cairo_restore (cr);
}
double arrow_width = MIN (height * 2 / 3.0, width);
double arrow_height = arrow_width / 2.0;
double gap_size = 1.0 * arrow_height;
-
+
cairo_save (cr);
cairo_translate (cr, x, y - (arrow_height + gap_size) / 2.0);
cairo_rotate (cr, G_PI);
clearlooks_draw_normal_arrow (cr, color, 0, 0, arrow_width, arrow_height);
cairo_restore (cr);
-
+
clearlooks_draw_normal_arrow (cr, color, x, y + (arrow_height + gap_size) / 2.0, arrow_width, arrow_height);
}
double x, double y, double width, double height)
{
double rotate;
-
+
if (dir == CL_DIRECTION_LEFT)
rotate = G_PI*1.5;
else if (dir == CL_DIRECTION_RIGHT)
rotate = 0;
else
return;
-
+
if (type == CL_ARROW_NORMAL)
{
cairo_translate (cr, x, y);
- cairo_rotate (cr, -rotate);
+ cairo_rotate (cr, -rotate);
clearlooks_draw_normal_arrow (cr, color, 0, 0, width, height);
}
else if (type == CL_ARROW_COMBO)
{
const CairoColor *color = &colors->fg[widget->state_type];
gdouble tx, ty;
-
+
tx = x + width/2.0;
ty = y + height/2.0;
-
+
if (widget->disabled)
{
_clearlooks_draw_arrow (cr, &colors->shade[0],
}
cairo_identity_matrix (cr);
-
+
_clearlooks_draw_arrow (cr, color, arrow->direction, arrow->type,
tx, ty, width, height);
}
cairo_set_source (cr, pt);
ge_cairo_rounded_rectangle (cr, x, y, width, height, radius, corners);
cairo_fill (cr);
-
+
cairo_pattern_destroy (pt);
}
/* not really sure of shading ratios... we will think */
ge_shade_color (bg_color, 0.8, &shadow);
ge_shade_color (bg_color, 1.2, &highlight);
-
+
cairo_save (cr);
-
+
/* Top/Left highlight */
if (corners & CR_CORNER_BOTTOMLEFT)
cairo_move_to (cr, x, y+height-radius);
else
cairo_move_to (cr, x, y+height);
-
+
ge_cairo_rounded_corner (cr, x, y, radius, corners & CR_CORNER_TOPLEFT);
if (corners & CR_CORNER_TOPRIGHT)
cairo_line_to (cr, x+width-radius, y);
else
cairo_line_to (cr, x+width, y);
-
+
if (params->shadow & CL_SHADOW_OUT)
cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
else
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5);
-
+
cairo_stroke (cr);
-
+
/* Bottom/Right highlight -- this includes the corners */
cairo_move_to (cr, x+width-radius, y); /* topright and by radius to the left */
ge_cairo_rounded_corner (cr, x+width, y, radius, corners & CR_CORNER_TOPRIGHT);
ge_cairo_rounded_corner (cr, x+width, y+height, radius, corners & CR_CORNER_BOTTOMRIGHT);
ge_cairo_rounded_corner (cr, x, y+height, radius, corners & CR_CORNER_BOTTOMLEFT);
-
+
if (params->shadow & CL_SHADOW_OUT)
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5);
else
cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
-
+
cairo_stroke (cr);
-
+
cairo_restore (cr);
}
double radius;
cairo_pattern_t *pattern;
-
+
cairo_save (cr);
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1.0);
ge_cairo_set_color (cr, &glow);
cairo_stroke (cr);
}
-
+
/* if (!(params->enable_glow && !params->active && !params->disabled)) */
if (!(params->prelight && params->enable_glow && !params->active)) {
if (!(params->disabled))
clearlooks_draw_glossy_gradient (cr, xoffset+1, yoffset+1,
width-(xoffset*2)-2, height-(yoffset*2)-2,
&fill, params->disabled, radius, params->corners);
-
+
/* Pressed button shadow */
if (params->active)
{
ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, height, radius, params->corners & (CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMLEFT));
cairo_clip (cr);
cairo_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, 3);
-
+
pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+1, yoffset+4);
cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58);
cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
cairo_rectangle (cr, xoffset+1, yoffset+1, 3, height-(yoffset*2)-2);
-
+
pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+4, yoffset+1);
cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58);
cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0);
cairo_restore (cr);
}
-
+
/* Default button highlight */
if (params->is_default && !params->active && !params->disabled)
{
const CairoColor *glow = &colors->spot[0];
double hh = (height-5)/2.0 + 1;
-
+
cairo_rectangle (cr, 3.5, 3.5, width-7, height-7);
ge_cairo_set_color (cr, glow);
cairo_stroke (cr);
cairo_rel_line_to (cr, width-5, 0); cairo_rel_line_to (cr, 0, hh);
ge_cairo_set_color (cr, glow);
cairo_stroke (cr);
-
+
hh--;
glow = &colors->spot[1];
ge_cairo_set_color (cr, glow);
cairo_stroke (cr);
}
-
+
/* Border */
if (params->is_default || (params->prelight && params->enable_glow))
border_normal = colors->spot[2];
CairoColor shadow;
cairo_pattern_t *pattern;
double radius = MIN (params->radius, MIN ((height-2.0) / 2.0, (width-2.0) / 2.0));
-
+
cairo_save (cr);
cairo_set_line_width (cr, 1.0);
-
+
/* Fill with bg color */
ge_cairo_set_color (cr, &colors->bg[params->state_type]);
-
+
cairo_rectangle (cr, x, y, width, height);
cairo_fill (cr);
stroke_width = height*2;
x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */
-
+
cairo_translate (cr, x, y);
cairo_save (cr);
cairo_line_to (cr, stroke_width-x_step, 0);
cairo_line_to (cr, stroke_width/2-x_step, height);
cairo_line_to (cr, -x_step, height);
-
+
cairo_translate (cr, stroke_width, 0);
tile_pos += stroke_width;
}
-
+
cairo_set_source_rgba (cr, colors->spot[2].r,
colors->spot[2].g,
colors->spot[2].b,
0.15);
-
+
cairo_fill (cr);
cairo_restore (cr); /* rounded clip region */
ge_cairo_set_color (cr, &shadow);
cairo_stroke (cr);
}
-
+
cairo_restore (cr);
cairo_restore (cr); /* rotation, mirroring */
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
clearlooks_set_mixed_color (cr, c3, c1, 0.3);
ge_cairo_stroke_rectangle (cr, x, y, width, height);
}
{
trough_width = width-3;
trough_height = TROUGH_SIZE-2;
-
+
translate_x = x + 0.5;
translate_y = y + 0.5 + (height/2) - (TROUGH_SIZE/2);
}
{
trough_width = TROUGH_SIZE-2;
trough_height = height-3;
-
+
translate_x = x + 0.5 + (width/2) - (TROUGH_SIZE/2);
translate_y = y + 0.5;
}
if (!slider->fill_level)
params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, trough_width+2, trough_height+2, 0, 0);
-
+
cairo_translate (cr, 1, 1);
-
+
if (!slider->lower && !slider->fill_level)
clearlooks_glossy_scale_draw_gradient (cr, &colors->shade[3], /* top */
&colors->shade[2], /* bottom */
CairoColor hilight;
cairo_pattern_t *pattern;
-
+
double radius;
radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM)
{
height += 3.0;
-
+
if (tab->gap_side == CL_GAP_TOP)
cairo_translate (cr, 0.0, -3.0); /* gap at the other side */
}
else
{
width += 3.0;
-
+
if (tab->gap_side == CL_GAP_LEFT)
cairo_translate (cr, -3.0, 0.0); /* gap at the other side */
}
-
+
/* Set the fill color */
fill = &colors->bg[params->state_type];
/* Set tab shape */
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1,
radius, params->corners);
-
+
/* Draw fill */
ge_cairo_set_color (cr, fill);
cairo_fill (cr);
if (!params->active)
{
ShadowParameters shadow;
-
+
shadow.shadow = CL_SHADOW_OUT;
shadow.corners = params->corners;
-
+
clearlooks_glossy_draw_highlight_and_shade (cr, &colors->bg[0], &shadow,
width,
height, radius);
tab->gap_side == CL_GAP_BOTTOM ? height : 0);
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
ge_shade_color (fill, 1.06, &shadow);
ge_shade_color (fill, 1.18, &hilight);
ge_shade_color (fill, 1.12, &f1);
tab->gap_side == CL_GAP_TOP ? height-2 : 0,
tab->gap_side == CL_GAP_RIGHT ? width : 0,
tab->gap_side == CL_GAP_BOTTOM ? height : 0);
-
+
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
cairo_pattern_add_color_stop_rgba (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b, 0.5);
cairo_pattern_add_color_stop_rgba (pattern, 0.8, fill->r, fill->g, fill->b, 0.0);
}
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
if (params->active)
{
ge_cairo_set_color (cr, border);
tab->gap_side == CL_GAP_TOP ? height-2 : 2,
tab->gap_side == CL_GAP_RIGHT ? width : 2,
tab->gap_side == CL_GAP_BOTTOM ? height : 2);
-
+
cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b);
cairo_pattern_add_color_stop_rgb (pattern, 0.8, border->r, border->g, border->b);
cairo_set_source (cr, pattern);
CairoColor a, b, c, d;
cairo_pattern_t *pattern;
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
cairo_translate (cr, -0.5, -0.5);
pattern = cairo_pattern_create_linear (1, 1, 1, height-2);
cairo_pattern_add_color_stop_rgb (pattern, 0, a.r, a.g, a.b);
cairo_pattern_add_color_stop_rgb (pattern, 0.5, b.r, b.g, b.b);
- cairo_pattern_add_color_stop_rgb (pattern, 0.5, c.r, c.g, c.b);
+ cairo_pattern_add_color_stop_rgb (pattern, 0.5, c.r, c.g, c.b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, d.r, d.g, d.b);
cairo_rectangle (cr, 1, 1, width-2, height-2);
cairo_set_source (cr, pattern);
double radius = MIN (params->radius, MIN ((width - 1.0) / 2.0, (height - 1.0) / 2.0));
cairo_set_line_width (cr, 1.0);
-
+
if (!slider->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
cairo_translate (cr, x+0.5, y+0.5);
-
+
params->style_functions->draw_shadow (cr, colors, radius, width-1, height-1);
params->style_functions->draw_slider (cr, colors, params, 1, 1, width-2, height-2);
}
CairoColor fill, s1, s2, s4;
cairo_pattern_t *pattern;
double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
-
+
if (scrollbar->horizontal)
{
if (stepper->stepper == CL_STEPPER_A)
else if (stepper->stepper == CL_STEPPER_D)
corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT;
}
-
+
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1);
-
+
ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners);
-
+
if (scrollbar->horizontal)
pattern = cairo_pattern_create_linear (0, 0, 0, height);
else
pattern = cairo_pattern_create_linear (0, 0, width, 0);
-
+
fill = colors->bg[widget->state_type];
ge_shade_color(&fill, 1.16, &s1);
ge_shade_color(&fill, 1.08, &s2);
ge_shade_color(&fill, 1.08, &s4);
-
+
cairo_pattern_add_color_stop_rgb(pattern, 0, s1.r, s1.g, s1.b);
cairo_pattern_add_color_stop_rgb(pattern, 0.5, s2.r, s2.g, s2.b);
cairo_pattern_add_color_stop_rgb(pattern, 0.5, fill.r, fill.g, fill.b);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
cairo_translate (cr, 0.5, 0.5);
cairo_translate (cr, -0.5, -0.5);
-
+
ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners);
clearlooks_set_mixed_color (cr, border, &fill, 0.2);
if (widget->prelight)
ge_cairo_set_color (cr, &colors->spot[2]);
cairo_stroke (cr);
-
+
cairo_translate (cr, 0.5, 0.5);
}
else
height += 1;
}
-
+
if (!scrollbar->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
if (widget->prelight)
ge_shade_color (&fill, 1.1, &fill);
-
+
cairo_set_line_width (cr, 1);
-
+
ge_shade_color (&fill, 1.25, &hilight);
ge_shade_color (&fill, 1.16, &shade1);
ge_shade_color (&fill, 1.08, &shade2);
ge_shade_color (&fill, 1.08, &shade3);
-
+
pattern = cairo_pattern_create_linear (1, 1, 1, height-2);
cairo_pattern_add_color_stop_rgb (pattern, 0, shade1.r, shade1.g, shade1.b);
cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
if (scrollbar->has_color)
{
cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
/* Draw highlight */
if (header->order == CL_ORDER_FIRST)
{
}
else
cairo_move_to (cr, 0.0, 0.5);
-
+
cairo_line_to (cr, width, 0.5);
-
+
cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5);
cairo_stroke (cr);
-
+
/* Draw resize grip */
if ((params->ltr && header->order != CL_ORDER_LAST) ||
(!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable)
{
SeparatorParameters separator;
separator.horizontal = FALSE;
-
+
if (params->ltr)
params->style_functions->draw_separator (cr, colors, params, &separator,
width-1.5, 4.0, 2, height-8.0);
{
CairoColor light;
const CairoColor *dark;
-
+
const CairoColor *fill = &colors->bg[GTK_STATE_NORMAL];
dark = &colors->shade[3];
(void) height;
ge_shade_color (fill, 1.1, &light);
-
+
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
-
+
if (toolbar->style == 1) /* Enable Extra features */
{
cairo_pattern_t *pattern;
CairoColor shade1, shade2, shade3;
-
+
ge_shade_color (fill, 1.08, &shade1);
ge_shade_color (fill, 1.04, &shade2);
ge_shade_color (fill, 1.04, &shade3);
cairo_line_to (cr, width-1, 0.5);
ge_cairo_set_color (cr, &light);
cairo_stroke (cr);
- }
+ }
}
/* Draw shadow */
cairo_pattern_add_color_stop_rgba (pt, 0.5, shadow.r, shadow.b, shadow.g, 0.5);
cairo_pattern_add_color_stop_rgba (pt, 0.5, highlight.r, highlight.g, highlight.b, 0.5);
cairo_pattern_add_color_stop_rgb (pt, 1.0, highlight.r, highlight.g, highlight.b);
-
+
cairo_translate (cr, x, y);
-
+
cairo_set_line_width (cr, 2);
cairo_arc (cr, 7, 7, 6, 0, G_PI*2);
cairo_set_source (cr, pt);
cairo_set_line_width (cr, 1);
cairo_arc (cr, 7, 7, 5.5, 0, G_PI*2);
-
+
if (!widget->disabled)
{
if (widget->prelight)
clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5);
- else
+ else
ge_cairo_set_color (cr, &colors->base[0]);
cairo_fill_preserve (cr);
}
-
+
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
-
+
if (draw_bullet)
{
if (inconsistent)
cairo_arc (cr, 7, 7, 3, 0, G_PI*2);
ge_cairo_set_color (cr, dot);
cairo_fill (cr);
-
+
cairo_arc (cr, 6, 6, 1, 0, G_PI*2);
cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
cairo_fill (cr);
inconsistent = (checkbox->shadow_type == GTK_SHADOW_ETCHED_IN);
draw_bullet |= inconsistent;
-
+
if (widget->disabled)
{
border = &colors->shade[5];
{
if (widget->prelight)
border = &colors->spot[2];
- else
+ else
border = &colors->shade[6];
dot = &colors->text[GTK_STATE_NORMAL];
}
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1);
-
+
if (widget->xthickness > 2 && widget->ythickness > 2)
{
widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5,
width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
-
+
/* Draw the rectangle for the checkbox itself */
ge_cairo_rounded_rectangle (cr, 1.5, 1.5,
width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
ge_cairo_rounded_rectangle (cr, 0.5, 0.5,
width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
}
-
+
if (!widget->disabled)
{
if (widget->prelight)
ge_cairo_set_color (cr, &colors->base[0]);
cairo_fill_preserve (cr);
}
-
+
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
cairo_set_line_width (cr, 1.7);
cairo_move_to (cr, 0.5 + (width*0.2), (height*0.5));
cairo_line_to (cr, 0.5 + (width*0.4), (height*0.7));
-
+
cairo_curve_to (cr, 0.5 + (width*0.4), (height*0.7),
0.5 + (width*0.5), (height*0.4),
0.5 + (width*0.70), (height*0.25));
}
-
+
ge_cairo_set_color (cr, dot);
cairo_stroke (cr);
}
cairo_set_source_rgba (cr, highlight.r, highlight.g, highlight.b, 0.5);
else
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.5);
-
+
cairo_stroke (cr);
/* Bottom/Right highlight -- this includes the corners */
cairo_line_to (cr, stroke_width-x_step, 0);
cairo_line_to (cr, stroke_width/2-x_step, height);
cairo_line_to (cr, -x_step, height);
-
+
cairo_translate (cr, stroke_width, 0);
tile_pos += stroke_width;
}
int bar_x, i;
int shift_x;
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
cairo_translate (cr, -0.5, -0.5);
{
if (widget->prelight)
border = &colors->spot[2];
- else
+ else
border = &colors->shade[6];
dot = &colors->text[GTK_STATE_NORMAL];
}
{
widget->style_functions->draw_inset (cr, &widget->parentbg, 0.5, 0.5,
width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
-
+
/* Draw the rectangle for the checkbox itself */
ge_cairo_rounded_rectangle (cr, 1.5, 1.5,
width-3, height-3, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
ge_cairo_rounded_rectangle (cr, 0.5, 0.5,
width-1, height-1, (widget->radius > 0)? 1 : 0, CR_CORNER_ALL);
}
-
+
if (!widget->disabled)
- {
+ {
if (widget->prelight)
clearlooks_set_mixed_color (cr, &colors->base[0], &colors->spot[1], 0.5);
- else
+ else
ge_cairo_set_color (cr, &colors->base[0]);
cairo_fill_preserve (cr);
}
pattern = cairo_pattern_create_linear (0, 0, width, height);
cairo_pattern_add_color_stop_rgb (pattern, 0, color->r, color->g, color->b);
cairo_pattern_add_color_stop_rgb (pattern, 1, bottom_shade.r, bottom_shade.g, bottom_shade.b);
-
+
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
}
{
double xoffset = 0, yoffset = 0;
double radius = params->radius;
- const CairoColor *fill = &colors->bg[params->state_type];
+ const CairoColor *fill = &colors->bg[params->state_type];
const CairoColor *border_disabled = &colors->shade[4];
CairoColor border_normal;
CairoColor shadow;
ge_shade_color(&colors->shade[6], 1.05, &border_normal);
ge_shade_color (&border_normal, 0.925, &shadow);
-
+
cairo_save (cr);
-
+
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, 0.5, 0.5);
params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width-1, height-1, radius+1, params->corners);
cairo_translate (cr, -0.5, -0.5);
- }
-
+ }
+
ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1,
width-(xoffset*2)-2,
height-(yoffset*2)-2,
radius, params->corners);
-
+
if (!params->active)
{
cairo_pattern_t *pattern;
CairoColor top_shade, bottom_shade;
- ge_shade_color (fill, 0.95, &top_shade);
+ ge_shade_color (fill, 0.95, &top_shade);
ge_shade_color (fill, 1.05, &bottom_shade);
-
+
pattern = cairo_pattern_create_linear (0, 0, 0, height);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, top_shade.r, top_shade.g, top_shade.b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, bottom_shade.r, bottom_shade.g, bottom_shade.b);
else
{
cairo_pattern_t *pattern;
-
+
ge_cairo_set_color (cr, fill);
cairo_fill_preserve (cr);
ge_cairo_set_color (cr, d);
ge_cairo_stroke_rectangle (cr, 3.5, 3.5, width-7, height-7);
}
-
+
if (params->disabled)
ge_cairo_set_color (cr, border_disabled);
else
clearlooks_set_border_gradient (cr, &border_normal, 1.32, 0, height);
else
ge_cairo_set_color (cr, &border_normal);
-
+
ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5,
width-(xoffset*2)-1, height-(yoffset*2)-1,
radius, params->corners);
cairo_stroke (cr);
-
+
/* Draw the "shadow" */
if (!params->active)
{
cairo_line_to (cr, width-params->xthickness, height - params->ythickness - 1);
cairo_set_source_rgba (cr, shadow.r, shadow.g, shadow.b, 0.1);
cairo_stroke (cr);
-
+
/* Draw topleft shadow */
clearlooks_draw_top_left_highlight (cr, fill, params, width, height, radius);
}
stroke_width = height*2;
x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */
-
+
cairo_translate (cr, x, y);
cairo_save (cr);
ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT);
cairo_clip (cr);
-
+
ge_shade_color (&colors->spot[1], 1.05, &top_shade);
/* Draw the background gradient */
cairo_line_to (cr, stroke_width-x_step, 0);
cairo_line_to (cr, stroke_width/2-x_step, height);
cairo_line_to (cr, -x_step, height);
-
+
cairo_translate (cr, stroke_width, 0);
tile_pos += stroke_width;
}
-
+
cairo_set_source_rgba (cr, colors->spot[2].r,
colors->spot[2].g,
colors->spot[2].b,
0.15);
-
+
cairo_fill (cr);
cairo_restore (cr); /* rounded clip region */
ge_cairo_set_color (cr, &shadow);
cairo_stroke (cr);
}
-
+
cairo_restore (cr);
cairo_restore (cr); /* rotation, mirroring */
CairoColor fill_shade;
CairoColor border = colors->spot[2];
cairo_pattern_t *pattern;
-
+
ge_shade_color (&border, 1.05, &border);
ge_shade_color (fill, 0.85, &fill_shade);
-
+
cairo_set_line_width (cr, 1.0);
ge_cairo_rounded_rectangle (cr, x + 0.5, y + 0.5, width - 1, height, widget->radius, widget->corners);
CairoColor shadow;
cairo_pattern_t *pattern;
-
+
double radius;
double strip_size;
cairo_clip (cr);
cairo_new_path (cr);
- /* Translate and set line width */
+ /* Translate and set line width */
cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x+0.5, y+0.5);
{
height += 3.0;
strip_size = 2.0/height; /* 2 pixel high strip */
-
+
if (tab->gap_side == CL_GAP_TOP)
cairo_translate (cr, 0.0, -3.0); /* gap at the other side */
}
{
width += 3.0;
strip_size = 2.0/width;
-
+
if (tab->gap_side == CL_GAP_LEFT)
cairo_translate (cr, -3.0, 0.0); /* gap at the other side */
}
-
+
/* Set the fill color */
fill = &colors->bg[params->state_type];
/* Set tab shape */
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1,
radius, params->corners);
-
+
/* Draw fill */
ge_cairo_set_color (cr, fill);
cairo_fill (cr);
tab->gap_side == CL_GAP_BOTTOM ? height : 0 );
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
ge_shade_color (fill, 0.92, &shadow);
cairo_pattern_add_color_stop_rgba (pattern, 0.0, hilight.r, hilight.g, hilight.b, 0.4);
tab->gap_side == CL_GAP_TOP ? height-2 : 0,
tab->gap_side == CL_GAP_RIGHT ? width : 0,
tab->gap_side == CL_GAP_BOTTOM ? height : 0 );
-
+
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_fill->r, stripe_fill->g, stripe_fill->b);
}
ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners);
-
+
if (params->active)
{
- ge_cairo_set_color (cr, border2);
+ ge_cairo_set_color (cr, border2);
cairo_stroke (cr);
}
else
tab->gap_side == CL_GAP_TOP ? height-2 : 2,
tab->gap_side == CL_GAP_RIGHT ? width : 2,
tab->gap_side == CL_GAP_BOTTOM ? height : 2 );
-
+
cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, stripe_border->r, stripe_border->g, stripe_border->b);
cairo_pattern_add_color_stop_rgb (pattern, strip_size, border1->r, border1->g, border1->b);
cairo_pattern_t *pattern;
- cairo_set_line_width (cr, 1.0);
+ cairo_set_line_width (cr, 1.0);
cairo_translate (cr, x, y);
if (params->disabled)
{
cairo_move_to (cr, 6, 0.5);
cairo_line_to (cr, 6, height-1);
-
+
cairo_move_to (cr, width-7, 0.5);
cairo_line_to (cr, width-7, height-1);
-
+
cairo_set_line_width (cr, 1.0);
cairo_set_source_rgba (cr, border->r,
border->g,
{
double radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
cairo_set_line_width (cr, 1.0);
-
+
if (!slider->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
cairo_translate (cr, x+0.5, y+0.5);
CairoColor shadow;
ge_shade_color (border, 1.5, &hilight);
- ge_shade_color (fill, 1.05, &hilight_header);
- ge_shade_color (fill, 0.95, &shadow);
+ ge_shade_color (fill, 1.05, &hilight_header);
+ ge_shade_color (fill, 0.95, &shadow);
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1.0);
-
+
/* Draw highlight */
if (header->order == CL_ORDER_FIRST)
{
}
else
cairo_move_to (cr, 0.0, 0.5);
-
+
cairo_line_to (cr, width, 0.5);
-
+
ge_cairo_set_color (cr, &hilight);
cairo_stroke (cr);
-
+
/* Draw bottom border */
cairo_move_to (cr, 0.0, height-0.5);
cairo_line_to (cr, width, height-0.5);
ge_cairo_set_color (cr, border);
cairo_stroke (cr);
- /* Draw bottom shade */
+ /* Draw bottom shade */
pattern = cairo_pattern_create_linear (0.0, 0, 0.0, height-1.0);
cairo_pattern_add_color_stop_rgb (pattern, 0.0, shadow.r, shadow.g, shadow.b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, hilight_header.r, hilight_header.g, hilight_header.b);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
/* Draw resize grip */
if ((params->ltr && header->order != CL_ORDER_LAST) ||
(!params->ltr && header->order != CL_ORDER_FIRST) || header->resizable)
{
SeparatorParameters separator;
separator.horizontal = FALSE;
-
+
if (params->ltr)
params->style_functions->draw_separator (cr, colors, params, &separator,
width-1.5, 4.0, 2, height-8.0);
CairoColor s1, s2, s3;
cairo_pattern_t *pattern;
double radius = MIN (widget->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0));
-
+
ge_shade_color(&colors->shade[6], 1.05, &border);
if (scrollbar->horizontal)
else if (stepper->stepper == CL_STEPPER_D)
corners = CR_CORNER_BOTTOMLEFT | CR_CORNER_BOTTOMRIGHT;
}
-
+
cairo_translate (cr, x, y);
cairo_set_line_width (cr, 1);
-
+
ge_cairo_rounded_rectangle (cr, 1, 1, width-2, height-2, radius, corners);
-
+
if (scrollbar->horizontal)
pattern = cairo_pattern_create_linear (0, 0, 0, height);
else
pattern = cairo_pattern_create_linear (0, 0, width, 0);
-
+
s1 = colors->bg[widget->state_type];
ge_shade_color(&s1, 0.95, &s2);
ge_shade_color(&s1, 1.05, &s3);
-
+
cairo_pattern_add_color_stop_rgb(pattern, 0, s2.r, s2.g, s2.b);
cairo_pattern_add_color_stop_rgb(pattern, 1.0, s3.r, s3.g, s3.b);
cairo_set_source (cr, pattern);
clearlooks_draw_top_left_highlight (cr, &s1, widget, width, height, radius);
- ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners);
+ ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius, corners);
clearlooks_set_border_gradient (cr, &border, 1.2, (scrollbar->horizontal ? 0 : width), (scrollbar->horizontal ? height: 0));
cairo_stroke (cr);
-
+
cairo_translate (cr, 0.5, 0.5);
}
else
height += 1;
}
-
+
if (!scrollbar->horizontal)
ge_cairo_exchange_axis (cr, &x, &y, &width, &height);
- cairo_translate (cr, x, y);
+ cairo_translate (cr, x, y);
if (scrollbar->has_color)
{
CairoColor hilight;
CairoColor shade1, shade2, shade3;
cairo_pattern_t *pattern;
-
+
if (widget->prelight)
ge_shade_color (&fill, 1.1, &fill);
-
+
cairo_set_line_width (cr, 1);
-
+
ge_shade_color (&fill, 1.3, &hilight);
ge_shade_color (&fill, 1.1, &shade1);
ge_shade_color (&fill, 1.05, &shade2);
ge_shade_color (&fill, 0.98, &shade3);
-
+
pattern = cairo_pattern_create_linear (1, 1, 1, height-2);
cairo_pattern_add_color_stop_rgb (pattern, 0, fill.r, fill.g, fill.b);
cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade3.r, shade3.g, shade3.b);
- cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b);
+ cairo_pattern_add_color_stop_rgb (pattern, 0.5, shade2.r, shade2.g, shade2.b);
cairo_pattern_add_color_stop_rgb (pattern, 1.0, shade1.r, shade1.g, shade1.b);
cairo_rectangle (cr, 1, 1, width-2, height-2);
cairo_set_source (cr, pattern);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
-
+
cairo_set_source_rgba (cr, hilight.r, hilight.g, hilight.b, 0.5);
ge_cairo_stroke_rectangle (cr, 1.5, 1.5, width-3, height-3);
-
+
ge_cairo_set_color (cr, border);
ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
}
CairoColor s1, s2, s3;
cairo_pattern_t *pattern;
int bar_x, i;
-
+
const CairoColor *dark = &colors->shade[4];
- const CairoColor *light = &colors->shade[0];
+ const CairoColor *light = &colors->shade[0];
ge_shade_color(&colors->shade[6], 1.05, &border);
cairo_set_source(cr, pattern);
cairo_fill(cr);
cairo_pattern_destroy(pattern);
-
+
clearlooks_draw_top_left_highlight (cr, &s2, widget, width, height, 0);
clearlooks_set_border_gradient (cr, &border, 1.2, 0, height);
ge_cairo_stroke_rectangle (cr, 0.5, 0.5, width-1, height-1);
-
+
/* draw handles */
cairo_set_line_width (cr, 1);
-
+
bar_x = width/2 - 4;
cairo_translate(cr, 0.5, 0.5);
for (i=0; i<3; i++)
cairo_line_to (cr, bar_x, height-5);
ge_cairo_set_color (cr, dark);
cairo_stroke (cr);
-
+
cairo_move_to (cr, bar_x+1, 4);
cairo_line_to (cr, bar_x+1, height-5);
ge_cairo_set_color (cr, light);
cairo_stroke (cr);
-
+
bar_x += 3;
}
}
CairoColor border;
cairo_pattern_t *pattern;
cairo_save (cr);
-
+
cairo_translate (cr, x, y);
if (params->focus)
cairo_fill (cr);
cairo_pattern_destroy (pattern);
- ge_shade_color(&upper_color, 0.8, &border);
+ ge_shade_color(&upper_color, 0.8, &border);
cairo_move_to (cr, 0, 0.5);
cairo_rel_line_to (cr, width, 0);
functions->draw_menubaritem = clearlooks_inverted_draw_menubaritem;
functions->draw_tab = clearlooks_inverted_draw_tab;
functions->draw_list_view_header = clearlooks_inverted_draw_list_view_header;
- functions->draw_scrollbar_stepper = clearlooks_inverted_draw_scrollbar_stepper;
+ functions->draw_scrollbar_stepper = clearlooks_inverted_draw_scrollbar_stepper;
functions->draw_scrollbar_slider = clearlooks_inverted_draw_scrollbar_slider;
functions->draw_selected_cell = clearlooks_inverted_draw_selected_cell;
}
clearlooks_rc_style_parse (GtkRcStyle *rc_style,
GtkSettings *settings,
GScanner *scanner)
-
+
{
static GQuark scope_id = 0;
ClearlooksRcStyle *clearlooks_style = CLEARLOOKS_RC_STYLE (rc_style);
clearlooks_rc_style_create_style (GtkRcStyle *rc_style)
{
(void) rc_style;
-
+
return GTK_STYLE (g_object_new (CLEARLOOKS_TYPE_STYLE, NULL));
}
params->active = (state_type == GTK_STATE_ACTIVE);
params->prelight = (state_type == GTK_STATE_PRELIGHT);
- params->disabled = (state_type == GTK_STATE_INSENSITIVE);
+ params->disabled = (state_type == GTK_STATE_INSENSITIVE);
params->state_type = (ClearlooksStateType)state_type;
params->corners = CR_CORNER_ALL;
params->ltr = ge_widget_is_ltr ((GtkWidget*)widget);
if (!params->active && widget && GE_IS_TOGGLE_BUTTON (widget))
params->active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-
+
params->xthickness = style->xthickness;
params->ythickness = style->ythickness;
-
+
/* This is used in GtkEntry to fake transparency. The reason to do this
* is that the entry has it's entire background filled with base[STATE].
* This is not a very good solution as it will eg. fail if one changes
static void
clearlooks_style_draw_flat_box (DRAW_ARGS)
{
- if (detail &&
+ if (detail &&
state_type == GTK_STATE_SELECTED && (
!strncmp ("cell_even", detail, 9) ||
!strncmp ("cell_odd", detail, 8)))
(DETAIL ("frame") && ge_is_in_combo_box (widget)))
{
WidgetParameters params;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
/* Override the entries state type, because we are too lame to handle this via
width += style->xthickness;
if (!params.ltr)
x -= style->xthickness;
-
+
if (params.ltr)
params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT;
else
params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT;
}
-
+
STYLE_FUNCTION (draw_entry) (cr, &clearlooks_style->colors, ¶ms,
x, y, width, height);
}
else if (DETAIL ("frame") && widget && GE_IS_STATUSBAR (widget->parent))
{
WidgetParameters params;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
gtk_style_apply_default_background (style, window, TRUE, state_type,
area, x, y, width, height);
-
+
STYLE_FUNCTION (draw_statusbar) (cr, colors, ¶ms,
x, y, width, height);
}
frame.shadow = shadow_type;
frame.gap_x = -1; /* No gap will be drawn */
frame.border = &colors->shade[4];
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_NONE;
-
+
if (widget && !g_str_equal ("XfcePanelWindow", gtk_widget_get_name (gtk_widget_get_toplevel (widget))))
STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame,
x, y, width, height);
frame.border = &colors->shade[5];
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_ALL;
-
+
STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame, x, y, width, height);
}
-
+
cairo_destroy (cr);
}
WidgetParameters params;
FrameParameters frame;
gboolean start, end;
-
+
frame.shadow = shadow_type;
frame.gap_side = gap_side;
frame.gap_x = gap_x;
frame.gap_width = gap_width;
frame.border = &colors->shade[5];
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
clearlooks_get_notebook_tab_position (widget, &start, &end);
ge_cairo_rounded_rectangle (cr, x, y, width, height, params.radius, params.corners);
ge_cairo_set_color (cr, &colors->bg[GTK_STATE_NORMAL]);
cairo_fill (cr);
-
+
STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame,
x, y, width, height);
}
x, y, width, height,
gap_side, gap_x, gap_width);
}
-
- cairo_destroy (cr);
+
+ cairo_destroy (cr);
}
static void
SANITIZE_SIZE
cr = ge_gdk_drawable_to_cairo (window, area);
-
+
if (DETAIL ("tab"))
{
WidgetParameters params;
TabParameters tab;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
tab.gap_side = (ClearlooksGapSide)gap_side;
-
+
switch (gap_side)
{
case CL_GAP_BOTTOM:
case CL_GAP_LEFT:
params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT;
}
-
+
STYLE_FUNCTION(draw_tab) (cr, colors, ¶ms, &tab,
x, y, width, height);
}
gap_side);
}
-
+
cairo_destroy (cr);
}
ClearlooksColors *colors = &clearlooks_style->colors;
cairo_t *cr;
gboolean is_horizontal;
-
+
CHECK_ARGS
SANITIZE_SIZE
-
+
cr = ge_gdk_drawable_to_cairo (window, area);
-
+
/* Evil hack to work around broken orientation for toolbars */
is_horizontal = (width > height);
-
+
if (DETAIL ("handlebox"))
{
WidgetParameters params;
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
handle.type = CL_HANDLE_TOOLBAR;
handle.horizontal = is_horizontal;
-
+
/* Is this ever true? -Daniel */
if (GE_IS_TOOLBAR (widget) && shadow_type != GTK_SHADOW_NONE)
{
STYLE_FUNCTION(draw_toolbar) (cr, colors, ¶ms, &toolbar, x, y, width, height);
cairo_restore (cr);
}
-
+
STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle,
x, y, width, height);
}
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
handle.type = CL_HANDLE_SPLITTER;
handle.horizontal = orientation == GTK_ORIENTATION_HORIZONTAL;
-
+
STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle,
x, y, width, height);
}
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
handle.type = CL_HANDLE_TOOLBAR;
handle.horizontal = is_horizontal;
-
+
/* Is this ever true? -Daniel */
if (GE_IS_TOOLBAR (widget) && shadow_type != GTK_SHADOW_NONE)
{
STYLE_FUNCTION(draw_toolbar) (cr, colors, ¶ms, &toolbar, x, y, width, height);
cairo_restore (cr);
}
-
+
STYLE_FUNCTION(draw_handle) (cr, colors, ¶ms, &handle,
x, y, width, height);
}
{
WidgetParameters params;
MenuBarParameters menubar;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
menubar.style = clearlooks_style->menubarstyle;
{
WidgetParameters params;
ListViewHeaderParameters header;
-
+
gint columns, column_index;
gboolean resizable = TRUE;
-
+
/* XXX: This makes unknown treeview header CL_ORDER_MIDDLE, in need for something nicer */
columns = 3;
column_index = 1;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
params.corners = CR_CORNER_NONE;
-
+
if (GE_IS_TREE_VIEW (widget->parent))
{
clearlooks_treeview_get_header_index (GTK_TREE_VIEW(widget->parent),
clearlooks_clist_get_header_index (GTK_CLIST(widget->parent),
widget, &column_index, &columns);
}
-
+
header.resizable = resizable;
-
+
if (column_index == 0)
header.order = params.ltr ? CL_ORDER_FIRST : CL_ORDER_LAST;
else if (column_index == columns-1)
header.order = params.ltr ? CL_ORDER_LAST : CL_ORDER_FIRST;
else
header.order = CL_ORDER_MIDDLE;
-
+
gtk_style_apply_default_background (style, window, FALSE, state_type, area, x, y, width, height);
-
+
STYLE_FUNCTION(draw_list_view_header) (cr, colors, ¶ms, &header,
x, y, width, height);
}
if (GE_IS_TOGGLE_BUTTON (widget) &&
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
params.active = TRUE;
-
+
STYLE_FUNCTION(draw_button) (cr, &clearlooks_style->colors, ¶ms,
x, y, width, height);
}
{
WidgetParameters params;
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
if (style->xthickness == 3)
{
width++;
if (params.ltr)
x--;
}
-
+
if (DETAIL ("spinbutton_up"))
{
height+=2;
else
params.corners = CR_CORNER_BOTTOMLEFT;
}
-
+
STYLE_FUNCTION(draw_spinbutton_down) (cr, &clearlooks_style->colors, ¶ms, x, y, width, height);
}
}
else if (DETAIL ("spinbutton"))
{
WidgetParameters params;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
if (params.ltr)
params.corners = CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT;
else
params.corners = CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT;
-
+
if (style->xthickness == 3)
{
if (params.ltr)
x--;
width++;
}
-
+
STYLE_FUNCTION(draw_spinbutton) (cr, &clearlooks_style->colors, ¶ms,
x, y, width, height);
}
{
WidgetParameters params;
SliderParameters slider;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_NONE;
-
+
slider.lower = DETAIL ("trough-lower");
slider.fill_level = DETAIL ("trough-fill-level") || DETAIL ("trough-fill-level-full");
slider.horizontal = (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL);
-
+
STYLE_FUNCTION(draw_scale_trough) (cr, &clearlooks_style->colors,
¶ms, &slider,
x, y, width, height);
else if (DETAIL ("trough") && widget && GE_IS_PROGRESS_BAR (widget))
{
WidgetParameters params;
-
- clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
+ clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
+
STYLE_FUNCTION(draw_progressbar_trough) (cr, colors, ¶ms,
x, y, width, height);
}
{
WidgetParameters params;
ScrollBarParameters scrollbar;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_NONE;
-
+
scrollbar.horizontal = TRUE;
scrollbar.junction = clearlooks_scrollbar_get_junction (widget);
-
+
if (GE_IS_RANGE (widget))
scrollbar.horizontal = GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL;
-
+
if (scrollbar.horizontal)
{
x += 2;
y += 2;
height -= 4;
}
-
+
STYLE_FUNCTION(draw_scrollbar_trough) (cr, colors, ¶ms, &scrollbar,
x, y, width, height);
}
#ifdef HAVE_ANIMATION
if(clearlooks_style->animation && CL_IS_PROGRESS_BAR (widget))
- {
+ {
gboolean activity_mode = GTK_PROGRESS (widget)->activity_mode;
-
+
if (!activity_mode)
clearlooks_animation_progressbar_add ((gpointer)widget);
}
progressbar.value = 0;
progressbar.pulsing = FALSE;
}
-
+
if (!params.ltr)
{
if (progressbar.orientation == GTK_PROGRESS_LEFT_TO_RIGHT)
tmp.height += 2;
}
}
-
+
cairo_reset_clip (cr);
gdk_cairo_rectangle (cr, &tmp);
cairo_clip (cr);
}
-
+
STYLE_FUNCTION(draw_progressbar_fill) (cr, colors, ¶ms, &progressbar,
x, y, width, height,
10 - (int)(elapsed * 10.0) % 10);
{
WidgetParameters params;
OptionMenuParameters optionmenu;
-
+
GtkRequisition indicator_size;
GtkBorder indicator_spacing;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
params.enable_glow = TRUE;
ge_option_menu_get_props (widget, &indicator_size, &indicator_spacing);
-
+
if (ge_widget_is_ltr (widget))
optionmenu.linepos = width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - 1;
else
optionmenu.linepos = (indicator_size.width + indicator_spacing.left + indicator_spacing.right) + 1;
-
+
STYLE_FUNCTION(draw_optionmenu) (cr, colors, ¶ms, &optionmenu,
- x, y, width, height);
+ x, y, width, height);
}
else if (DETAIL ("menuitem"))
{
WidgetParameters params;
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
if (widget && GE_IS_MENU_BAR (widget->parent))
{
params.corners = CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT;
STYLE_FUNCTION(draw_menubaritem) (cr, colors, ¶ms, x, y, width, height);
}
else
- {
+ {
params.corners = CR_CORNER_ALL;
STYLE_FUNCTION(draw_menuitem) (cr, colors, ¶ms, x, y, width, height);
}
ScrollBarParameters scrollbar;
ScrollBarStepperParameters stepper;
GdkRectangle this_rectangle;
-
+
this_rectangle.x = x;
this_rectangle.y = y;
this_rectangle.width = width;
this_rectangle.height = height;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_NONE;
-
+
scrollbar.has_color = FALSE;
scrollbar.horizontal = TRUE;
scrollbar.junction = clearlooks_scrollbar_get_junction (widget);
}
scrollbar.horizontal = DETAIL ("hscrollbar");
-
+
stepper.stepper = clearlooks_scrollbar_get_stepper (widget, &this_rectangle);
STYLE_FUNCTION(draw_scrollbar_stepper) (cr, colors, ¶ms, &scrollbar, &stepper,
}
else if (DETAIL ("trough"))
{
-
+
}
else if (DETAIL ("menu"))
{
WidgetParameters params;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
STYLE_FUNCTION(draw_menu_frame) (cr, colors, ¶ms, x, y, width, height);
}
else if (DETAIL ("hseparator") || DETAIL ("vseparator"))
clearlooks_parent_class->draw_box (style, window, state_type, shadow_type, area,
widget, detail, x, y, width, height);
}
-
+
cairo_destroy (cr);
}
CHECK_ARGS
SANITIZE_SIZE
-
+
if (DETAIL ("hscale") || DETAIL ("vscale"))
{
WidgetParameters params;
SliderParameters slider;
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
slider.horizontal = (orientation == GTK_ORIENTATION_HORIZONTAL);
slider.lower = FALSE;
slider.fill_level = FALSE;
-
+
if (clearlooks_style->style == CL_STYLE_GLOSSY) /* XXX! */
params.corners = CR_CORNER_ALL;
-
+
STYLE_FUNCTION(draw_slider_button) (cr, &clearlooks_style->colors,
¶ms, &slider,
x, y, width, height);
if ((clearlooks_style->style == CL_STYLE_GLOSSY || clearlooks_style->style == CL_STYLE_GUMMY)
&& !scrollbar.has_color)
scrollbar.color = colors->bg[0];
-
+
STYLE_FUNCTION(draw_scrollbar_slider) (cr, colors, ¶ms, &scrollbar,
x, y, width, height);
}
CheckboxParameters checkbox;
cairo_t *cr;
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
-
+
(void) detail;
CHECK_ARGS
cr = ge_gdk_drawable_to_cairo (window, area);
colors = &clearlooks_style->colors;
-
+
checkbox.shadow_type = shadow_type;
checkbox.in_menu = (widget && GTK_IS_MENU(widget->parent));
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
STYLE_FUNCTION(draw_radiobutton) (cr, colors, ¶ms, &checkbox, x, y, width, height);
cairo_destroy (cr);
SANITIZE_SIZE
cr = ge_gdk_drawable_to_cairo (window, area);
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
-
+
params.corners = CR_CORNER_ALL;
-
+
checkbox.shadow_type = shadow_type;
checkbox.in_cell = DETAIL("cellcheck");
STYLE_FUNCTION(draw_checkbox) (cr, &clearlooks_style->colors, ¶ms, &checkbox,
x, y, width, height);
-
+
cairo_destroy (cr);
}
* (and even if, a normal one should be better on menu bars) */
STYLE_FUNCTION(draw_separator) (cr, colors, NULL, &separator,
x, y1, 2, y2-y1+1);
-
+
cairo_destroy (cr);
}
colors = &clearlooks_style->colors;
cr = ge_gdk_drawable_to_cairo (window, area);
-
+
separator.horizontal = TRUE;
-
+
if (!DETAIL ("menuitem"))
STYLE_FUNCTION(draw_separator) (cr, colors, NULL, &separator,
x1, y, x2-x1+1, 2);
else
STYLE_FUNCTION(draw_menu_item_separator) (cr, colors, NULL, &separator,
x1, y, x2-x1+1, 2);
-
+
cairo_destroy (cr);
}
cr = ge_gdk_drawable_to_cairo (window, area);
colors = &clearlooks_style->colors;
-
+
if (DETAIL ("frame"))
{
WidgetParameters params;
FrameParameters frame;
-
+
frame.shadow = shadow_type;
frame.gap_side = gap_side;
frame.gap_x = gap_x;
frame.gap_width = gap_width;
frame.border = &colors->shade[5];
-
+
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
params.corners = CR_CORNER_ALL;
-
+
STYLE_FUNCTION(draw_frame) (cr, colors, ¶ms, &frame,
x, y, width, height);
}
widget, detail, x, y, width, height,
gap_side, gap_x, gap_width);
}
-
+
cairo_destroy (cr);
}
cr = ge_gdk_drawable_to_cairo (window, area);
- clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
+ clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
STYLE_FUNCTION(draw_resize_grip) (cr, colors, ¶ms, &grip,
x, y, width, height);
{
ClearlooksColors *colors;
WidgetParameters params;
- ArrowParameters arrow;
+ ArrowParameters arrow;
cairo_t *cr;
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
CHECK_ARGS
SANITIZE_SIZE
-
+
cr = ge_gdk_drawable_to_cairo (window, area);
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
arrow.type = CL_ARROW_COMBO;
- arrow.direction = CL_DIRECTION_DOWN;
+ arrow.direction = CL_DIRECTION_DOWN;
STYLE_FUNCTION(draw_arrow) (cr, colors, ¶ms, &arrow, x, y, width, height);
clearlooks_set_widget_parameters (widget, style, state_type, ¶ms);
arrow.type = CL_ARROW_NORMAL;
arrow.direction = (ClearlooksDirection)arrow_type;
-
+
if (ge_is_combo_box (widget, FALSE) && !ge_is_combo_box_entry (widget))
{
arrow.type = CL_ARROW_COMBO;
}
-
+
/* I have no idea why, but the arrow of GtkCombo is larger than in other places.
* Subtracting 3 seems to fix this. */
if (widget && widget->parent && GE_IS_COMBO (widget->parent->parent))
x += 2;
width -= 3;
}
-
+
STYLE_FUNCTION(draw_arrow) (cr, colors, ¶ms, &arrow, x, y, width, height);
-
+
cairo_destroy (cr);
}
GtkRcStyle * rc_style)
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
-
+
clearlooks_parent_class->init_from_rc (style, rc_style);
-
+
g_assert ((CLEARLOOKS_RC_STYLE (rc_style)->style < CL_NUM_STYLES));
clearlooks_style->style = CLEARLOOKS_RC_STYLE (rc_style)->style;
-
+
clearlooks_style->menubarstyle = CLEARLOOKS_RC_STYLE (rc_style)->menubarstyle;
clearlooks_style->toolbarstyle = CLEARLOOKS_RC_STYLE (rc_style)->toolbarstyle;
clearlooks_style->has_scrollbar_color = CLEARLOOKS_RC_STYLE (rc_style)->flags & CL_FLAG_SCROLLBAR_COLOR;
CairoColor bg_normal;
double contrast;
int i;
-
+
clearlooks_parent_class->realize (style);
contrast = CLEARLOOKS_RC_STYLE (style->rc_style)->contrast;
-
+
/* Lighter to darker */
ge_gdk_color_to_cairo (&style->bg[GTK_STATE_NORMAL], &bg_normal);
{
ge_shade_color(&bg_normal, (shades[i]-0.7) * contrast + 0.7, &clearlooks_style->colors.shade[i]);
}
-
+
ge_gdk_color_to_cairo (&style->bg[GTK_STATE_SELECTED], &spot_color);
-
+
ge_shade_color(&spot_color, 1.42, &clearlooks_style->colors.spot[0]);
ge_shade_color(&spot_color, 1.05, &clearlooks_style->colors.spot[1]);
ge_shade_color(&spot_color, 0.65, &clearlooks_style->colors.spot[2]);
-
+
for (i=0; i<5; i++)
{
ge_gdk_color_to_cairo (&style->fg[i], &clearlooks_style->colors.fg[i]);
{
ClearlooksStyle * cl_style = CLEARLOOKS_STYLE (style);
ClearlooksStyle * cl_src = CLEARLOOKS_STYLE (src);
-
+
cl_style->colors = cl_src->colors;
cl_style->menubarstyle = cl_src->menubarstyle;
cl_style->toolbarstyle = cl_src->toolbarstyle;
cl_style->animation = cl_src->animation;
cl_style->radius = cl_src->radius;
cl_style->style = cl_src->style;
-
+
clearlooks_parent_class->copy (style, src);
}
ge_shade_color (¶ms.parentbg, 1.2, &temp);
else
ge_shade_color (&colors->bg[widget->state], 1.2, &temp);
-
+
etched.red = (int) (temp.r * 65535);
etched.green = (int) (temp.g * 65535);
etched.blue = (int) (temp.b * 65535);
* GtkIconSet can be used without a style and if so
* it uses this function.
*/
-
+
base_pixbuf = gtk_icon_source_get_pixbuf (source);
-
+
g_return_val_if_fail (base_pixbuf != NULL, NULL);
-
+
if (widget && gtk_widget_has_screen (widget)) {
screen = gtk_widget_get_screen (widget);
settings = gtk_settings_get_for_screen (screen);
GTK_NOTE (MULTIHEAD,
g_warning ("Using the default screen for gtk_default_render_icon()"));
}
-
+
if (size != (GtkIconSize) -1 && !gtk_icon_size_lookup_for_settings (settings, size, &width, &height)) {
g_warning (G_STRLOC ": invalid icon size '%d'", size);
scaled = scale_or_ref (base_pixbuf, width, height);
else
scaled = g_object_ref (base_pixbuf);
-
+
/* If the state was wildcarded, then generate a state. */
if (gtk_icon_source_get_state_wildcarded (source)) {
if (state == GTK_STATE_INSENSITIVE) {
stated = set_transparency (scaled, 0.3);
gdk_pixbuf_saturate_and_pixelate (stated, stated,
0.1, FALSE);
-
+
g_object_unref (scaled);
} else if (state == GTK_STATE_PRELIGHT) {
stated = gdk_pixbuf_copy (scaled);
-
+
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1.2, FALSE);
-
+
g_object_unref (scaled);
} else {
stated = scaled;
clearlooks_style_class_init (ClearlooksStyleClass * klass)
{
GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
-
+
clearlooks_style_class = CLEARLOOKS_STYLE_CLASS (klass);
clearlooks_parent_class = g_type_class_peek_parent (klass);
ClearlooksColors colors;
ClearlooksStyles style;
-
+
guint8 menubarstyle;
guint8 toolbarstyle;
GdkColor scrollbar_color;
CairoColor bg[5];
CairoColor base[5];
CairoColor text[5];
-
+
CairoColor shade[9];
CairoColor spot[3];
} ClearlooksColors;
boolean enable_glow;
gfloat radius;
-
+
ClearlooksStateType state_type;
-
+
uint8 corners;
uint8 xthickness;
uint8 ythickness;
typedef struct
{
CairoCorners corners;
- ClearlooksShadowType shadow;
+ ClearlooksShadowType shadow;
} ShadowParameters;
typedef struct
const WidgetParameters *widget,
const OptionMenuParameters *optionmenu,
int x, int y, int width, int height);
-
+
void (*draw_inset) (cairo_t *cr,
const CairoColor *bg_color,
double x, double y, double w, double h,
const WidgetParameters *widget,
const ArrowParameters *arrow,
int x, int y, int width, int height);
-
+
void (*draw_checkbox) (cairo_t *cr,
const ClearlooksColors *colors,
const WidgetParameters *widget,
{
int i;
*columns = clist->columns;
-
+
for (i=0; i<*columns; i++)
{
if (clist->column[i].button == button)
GtkStateType state_type;
const GtkWidget *parent;
GdkColor *gcolor;
-
+
if (widget == NULL)
return;
-
+
parent = widget->parent;
-
+
while (parent && GTK_WIDGET_NO_WINDOW (parent) && !((GTK_IS_NOTEBOOK (parent)) || (GTK_IS_TOOLBAR (parent))))
parent = parent->parent;
if (parent == NULL)
return;
-
+
state_type = GTK_WIDGET_STATE (parent);
-
+
gcolor = &parent->style->bg[state_type];
-
+
ge_gdk_color_to_cairo (gcolor, color);
}
check_rectangle.y = widget->allocation.y;
check_rectangle.width = stepper->width;
check_rectangle.height = stepper->height;
-
+
orientation = GTK_RANGE (widget)->orientation;
-
+
if (widget->allocation.x == -1 && widget->allocation.y == -1)
return CL_STEPPER_UNKNOWN;
-
+
if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp))
value = CL_STEPPER_A;
check_rectangle.x = widget->allocation.x + stepper->width;
else
check_rectangle.y = widget->allocation.y + stepper->height;
-
+
if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp))
value = CL_STEPPER_B;
}
check_rectangle.x = widget->allocation.x + widget->allocation.width - (stepper->width * 2);
else
check_rectangle.y = widget->allocation.y + widget->allocation.height - (stepper->height * 2);
-
+
if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp))
value = CL_STEPPER_C;
}
check_rectangle.x = widget->allocation.x + widget->allocation.width - stepper->width;
else
check_rectangle.y = widget->allocation.y + widget->allocation.height - stepper->height;
-
+
if (gdk_rectangle_intersect (stepper, &check_rectangle, &tmp))
value = CL_STEPPER_D;
}
-
+
return value;
}
clearlooks_scrollbar_visible_steppers (GtkWidget *widget)
{
ClearlooksStepper steppers = 0;
-
+
if (!GE_IS_RANGE (widget))
return 0;
-
+
if (GTK_RANGE (widget)->has_stepper_a)
steppers |= CL_STEPPER_A;
-
+
if (GTK_RANGE (widget)->has_stepper_b)
steppers |= CL_STEPPER_B;
ClearlooksJunction
clearlooks_scrollbar_get_junction (GtkWidget *widget)
-{
+{
GtkAdjustment *adj;
ClearlooksJunction junction = CL_JUNCTION_NONE;
-
+
if (!GE_IS_RANGE (widget))
return CL_JUNCTION_NONE;
adj = GTK_RANGE (widget)->adjustment;
-
+
if (adj->value <= adj->lower &&
(GTK_RANGE (widget)->has_stepper_a || GTK_RANGE (widget)->has_stepper_b))
{
junction |= CL_JUNCTION_BEGIN;
}
-
+
if (adj->value >= adj->upper - adj->page_size &&
(GTK_RANGE (widget)->has_stepper_c || GTK_RANGE (widget)->has_stepper_d))
{
junction |= CL_JUNCTION_END;
}
-
+
return junction;
}
GtkWidget *tab_label;
gboolean expand;
GtkPackType pack_type;
-
+
tab_child = gtk_notebook_get_nth_page (notebook, i);
/* Skip invisible tabs */
result = TRUE;
child = NULL;
}
- }
+ }
if (children)
g_list_free(children);
{
GtkBorder default_border = {1, 1, 1, 1};
GtkBorder *tmp_border = NULL;
-
+
if (widget && GE_IS_BUTTON (widget))
gtk_widget_style_get (widget, "default-border", &tmp_border, NULL);
ge_widget_is_ltr (GtkWidget *widget)
{
GtkTextDirection dir = GTK_TEXT_DIR_NONE;
-
+
if (GE_IS_WIDGET (widget))
dir = gtk_widget_get_direction (widget);
static void cl_draw_line (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
int x1, int y1, int x2, int y2, CLBorderType border,
CLRectangle *r);
-
+
static void cl_draw_corner (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
int x, int y, int width, int height,
CLRectangle *r, CLCornerSide corner);
-
+
static void cl_draw_fill (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
int x, int y, int width, int height, CLRectangle *r);
{
cl_draw_fill(window, widget, style, x, y, width, height, r);
}
-
+
if (r->bordergc)
{
cl_draw_borders(window, widget, style, x, y, width, height, r);
- }
+ }
}
r->gradient_type == CL_GRADIENT_VERTICAL && border == CL_BORDER_TOP)
gdk_gc_set_foreground (r->bordergc, r->border_gradient.from);
else
- gdk_gc_set_foreground (r->bordergc, r->border_gradient.to);
+ gdk_gc_set_foreground (r->bordergc, r->border_gradient.to);
gdk_draw_line (window, r->bordergc, x1, y1, x2, y2);
-
+
gdk_gc_set_foreground (r->bordergc, &tmp_color);
}
}
{
color = r->border_gradient.to;
}
-
+
return color;
}
if (r->corners[corner] == CL_CORNER_NONE)
return;
-
+
color = cl_get_gradient_corner_color (r, corner);
gdk_gc_get_values (r->bordergc, &values);
{
x1 = (corner == CL_CORNER_TOPLEFT ||
corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width - 2;
-
+
y1 = (corner == CL_CORNER_TOPLEFT ||
corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height - 2;
-
+
gdk_gc_set_foreground (r->bordergc, color);
gdk_draw_point (window, r->bordergc, x1, y1);
-
+
gdk_gc_set_foreground (r->bordergc, &aacolor);
-
+
x1 = (corner == CL_CORNER_TOPLEFT ||
corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width-2;
y1 = (corner == CL_CORNER_TOPLEFT ||
- corner == CL_CORNER_TOPRIGHT) ? y : y+height-1;
-
+ corner == CL_CORNER_TOPRIGHT) ? y : y+height-1;
+
gdk_draw_point (window, r->bordergc, x1, y1);
x1 = (corner == CL_CORNER_TOPLEFT ||
corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height-2;
gdk_draw_point (window, r->bordergc, x1, y1);
-
+
}
else if (r->corners[corner] == CL_CORNER_NARROW)
{
y1 = (corner == CL_CORNER_TOPLEFT ||
corner == CL_CORNER_TOPRIGHT) ? y : y+height-1;
-
+
gdk_gc_set_foreground (r->bordergc, &aacolor);
gdk_draw_point (window, r->bordergc, x1, y1);
}
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
int my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0;
GdkGC *border_gc = clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type];
-
-
+
+
cl_rectangle_init (r, style->bg_gc[state_type],
clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type],
tl, tr, bl, br);
r->topleft = (state_type != GTK_STATE_ACTIVE) ? style->light_gc[state_type] : clearlooks_style->shade_gc[4];
r->bottomright = (state_type != GTK_STATE_ACTIVE) ? clearlooks_style->shade_gc[1] : NULL;
-
+
shade (&style->bg[state_type], &r->tmp_color, 0.93);
-
+
cl_rectangle_set_gradient (&r->fill_gradient,
&style->bg[state_type],
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
GdkGC *bordergc;
-
+
if (has_focus)
bordergc = clearlooks_style->spot3_gc;
else if (state_type != GTK_STATE_INSENSITIVE)
bordergc = clearlooks_style->border_gc[CL_BORDER_LOWER];
else
- bordergc = clearlooks_style->shade_gc[3];
-
+ bordergc = clearlooks_style->shade_gc[3];
+
cl_rectangle_init (r, style->base_gc[state_type], bordergc,
tl, tr, bl, br);
if (state_type != GTK_STATE_INSENSITIVE )
r->topleft = (has_focus) ? clearlooks_style->spot1_gc
: style->bg_gc[GTK_STATE_NORMAL];
-
+
if (has_focus)
r->bottomright = clearlooks_style->spot1_gc;
else if (state_type == GTK_STATE_INSENSITIVE)
x1 = x+1+(r->corners[CL_CORNER_BOTTOMLEFT]/2);
y1 = y2 = y+height-2;
x2 = x+width - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2);
-
+
gdk_draw_line (window, r->bottomright, x1, y1, x2, y2);
-
+
x1 = x2 = x+width-2;
y1 = y+1+(r->corners[CL_CORNER_TOPRIGHT]/2);
y2 = y+height - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2);
gdk_draw_line (window, r->bottomright, x1, y1, x2, y2);
}
-
+
if (r->topleft != NULL)
{
x1 = x+1+(r->corners[CL_CORNER_TOPLEFT]/2);
y1 = y2 = y+1;
x2 = x+width-1-(1+r->corners[CL_CORNER_TOPRIGHT]/2);
-
+
gdk_draw_line (window, r->topleft, x1, y1, x2, y2);
-
+
x1 = x2 = x+1;
y1 = y+1+(r->corners[CL_CORNER_TOPLEFT]/2);
y2 = y+height-1-(1+r->corners[CL_CORNER_BOTTOMLEFT]/2);
int tl, int tr, int bl, int br)
{
r->gradient_type = CL_GRADIENT_NONE;
-
+
r->border_gradient.from = r->border_gradient.to = NULL;
r->fill_gradient.from = r->fill_gradient.to = NULL;
-
+
r->fillgc = fillgc;
r->bordergc = bordergc;
-
+
r->topleft = NULL;
r->bottomright = NULL;
-
+
r->corners[CL_CORNER_TOPLEFT] = tl;
r->corners[CL_CORNER_TOPRIGHT] = tr;
r->corners[CL_CORNER_BOTTOMLEFT] = bl;
r->corners[CL_CORNER_TOPLEFT] = tl;
r->corners[CL_CORNER_TOPRIGHT] = tr;
r->corners[CL_CORNER_BOTTOMLEFT] = bl;
- r->corners[CL_CORNER_BOTTOMRIGHT] = br;
+ r->corners[CL_CORNER_BOTTOMRIGHT] = br;
}
void cl_set_corner_sharpness (const gchar *detail, GtkWidget *widget, CLRectangle *r)
gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
int cl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
int cr = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND;
-
+
cl_rectangle_set_corners (r, cl, cr, cl, cr);
}
else if (detail && !strcmp (detail, "spinbutton_up"))
{
if (area == NULL)
return;
-
+
if (r->fillgc)
gdk_gc_set_clip_rectangle (r->fillgc, area);
-
+
if (r->bordergc)
- gdk_gc_set_clip_rectangle (r->bordergc, area);
+ gdk_gc_set_clip_rectangle (r->bordergc, area);
if (r->topleft)
- gdk_gc_set_clip_rectangle (r->topleft, area);
+ gdk_gc_set_clip_rectangle (r->topleft, area);
if (r->bottomright)
- gdk_gc_set_clip_rectangle (r->bottomright, area);
+ gdk_gc_set_clip_rectangle (r->bottomright, area);
}
void cl_rectangle_reset_clip_rectangle (CLRectangle *r)
{
if (r->fillgc)
gdk_gc_set_clip_rectangle (r->fillgc, NULL);
-
+
if (r->bordergc)
gdk_gc_set_clip_rectangle (r->bordergc, NULL);
int trans;
int stripe_width = height/2;
- int topright = height + stripe_width;
+ int topright = height + stripe_width;
int topright_div_2 = topright/2;
- double shift;
+ double shift;
GdkPoint points[4];
GtkProgressBarOrientation orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget));
gboolean is_horizontal = (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || orientation == GTK_PROGRESS_RIGHT_TO_LEFT) ? 1 : 0;
-
+
GdkPixmap *tmp = gdk_pixmap_new (widget->window, width, height, -1);
GdkColor tmp_color;
shade (&clearlooks_style->spot2, &tmp_color, 0.90);
-
+
if (is_horizontal)
draw_hgradient (tmp, style->black_gc, style, 0, 0, width, height,
&clearlooks_style->spot2, &tmp_color );
else
draw_vgradient (tmp, style->black_gc, style, 0, 0, width, height,
&tmp_color, &clearlooks_style->spot2); /* TODO: swap for RTL */
-
+
if (orientation == GTK_PROGRESS_RIGHT_TO_LEFT ||
orientation == GTK_PROGRESS_BOTTOM_TO_TOP)
{
offset = -offset;
xdir = -1;
}
-
+
if (get_direction (widget) == GTK_TEXT_DIR_RTL)
offset = -offset;
-
+
if (is_horizontal)
{
points[0] = (GdkPoint){xdir*(topright - stripe_width - topright_div_2), 0}; /* topleft */
points[2] = (GdkPoint){0, xdir*(stripe_width - topright_div_2)}; /* bottomright */
points[3] = (GdkPoint){0, xdir*(-topright_div_2)}; /* bottomleft */
}
-
-
+
+
shift = (stripe_width*2)/(double)10;
cl_progressbar_points_transform (points, 4, (offset*shift), is_horizontal);
-
+
trans = (width/2)-1-(stripe_width*2);
cl_progressbar_points_transform (points, 4, trans, is_horizontal);
gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4);
trans = (width/2)-1+(stripe_width*2);
cl_progressbar_points_transform (points, 4, trans, is_horizontal);
gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4);
-
+
return tmp;
}
ny = y,
nwidth = height,
nheight = width;
-
+
gdk_gc_set_clip_rectangle (gc, area);
-
+
switch (orientation)
{
case GTK_PROGRESS_LEFT_TO_RIGHT:
break;
}
}
-
+
gdk_gc_set_clip_rectangle (gc, NULL);
-
+
g_object_unref (tile);
}
gdk_gc_get_values (gc, &values);
gdk_rgb_find_color (colormap, &tmp_color);
gdk_gc_set_foreground (gc, &tmp_color);
-
+
return values.foreground;
}
GtkStyle *windowstyle = NULL;
GtkWidget *tmpwidget = widget;
GtkStateType windowstate;
-
+
if (widget && GTK_IS_ENTRY (widget))
tmpwidget = tmpwidget->parent;
-
+
while (tmpwidget && GTK_WIDGET_NO_WINDOW (tmpwidget) && !GTK_IS_NOTEBOOK(tmpwidget))
{
tmpwidget = tmpwidget->parent;
{
GtkStyle *style;
GtkStateType state_type;
-
+
cl_get_window_style_state (widget, &style, &state_type);
-
+
return style->bg_gc[state_type];
}
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style);
ClearlooksStyle *clwindowstyle; /* style of the window this widget is on */
- GtkStateType windowstate;
+ GtkStateType windowstate;
CLRectangle r;
cl_rectangle_init (&r, NULL, style->black_gc,
tl, tr, bl, br);
-
+
r.gradient_type = CL_GRADIENT_VERTICAL;
-
+
cl_get_window_style_state(widget, (GtkStyle**)&clwindowstyle, &windowstate);
-
+
g_assert (clwindowstyle != NULL);
-
+
if (GTK_WIDGET_HAS_DEFAULT (widget))
{
r.bordergc = style->mid_gc[GTK_STATE_NORMAL];
GdkGC *bg_gc = NULL;
gboolean is_active = FALSE;
CLRectangle r;
-
+
/* Get the background color of the window we're on */
bg_gc = cl_get_window_bg_gc(widget);
-
+
cl_rectangle_set_button (&r, style, state_type,
GTK_WIDGET_HAS_DEFAULT (widget),
GTK_WIDGET_HAS_FOCUS (widget),
CL_CORNER_ROUND, CL_CORNER_ROUND,
CL_CORNER_ROUND, CL_CORNER_ROUND);
-
+
if (state_type == GTK_STATE_ACTIVE)
is_active = TRUE;
cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->shade[1], &clearlooks_style->shade[1]);
r.topleft = clearlooks_style->shade_gc[3];
r.bottomright = clearlooks_style->shade_gc[1];
-
+
is_active = TRUE;
- }
+ }
if (!is_active)
r.fillgc = NULL;
-
+
if (!GTK_IS_NOTEBOOK (widget->parent))
{
gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
-
+
/* Draw "sunken" look when border thickness is more than 2 pixels. */
if (style->xthickness > 2 && style->ythickness > 2)
cl_draw_inset (style, window, widget, area, x, y, width, height,
CL_CORNER_ROUND, CL_CORNER_ROUND,
CL_CORNER_ROUND, CL_CORNER_ROUND);
}
-
+
/* Draw "sunken" look when border thickness is more than 2 pixels.*/
if (style->xthickness > 2 && style->ythickness > 2)
{
height-=2;
width-=2;
}
-
+
/* Don't draw the normal gradient for normal buttons. */
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
-
-
+
+
if (!is_active)
{
int tmp_height = (float)height*0.25;
-
+
gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2,y+2,width-4,tmp_height,
&clearlooks_style->button_g1[state_type],
&clearlooks_style->button_g2[state_type]);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2, y+2+tmp_height, width-4, height-3-tmp_height*2,
&clearlooks_style->button_g2[state_type],
&clearlooks_style->button_g3[state_type]);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2,y+height-tmp_height-1,width-4,tmp_height,
&clearlooks_style->button_g3[state_type],
&clearlooks_style->button_g4[state_type]);
gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
- }
-
+ }
+
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
}
GdkRectangle new_area;
int tl = CL_CORNER_NONE, tr = CL_CORNER_NONE,
- bl = CL_CORNER_NONE, br = CL_CORNER_NONE;
-
+ bl = CL_CORNER_NONE, br = CL_CORNER_NONE;
+
if (area == NULL)
{
new_area.x = x;
new_area.y = y;
new_area.width = width;
new_area.height = height;
- area = &new_area;
+ area = &new_area;
}
if (!strcmp (detail, "spinbutton")) /* draws the 'back' of the spinbutton */
{
GdkGC *bg_gc = cl_get_window_bg_gc(widget);
-
+
gdk_gc_set_clip_rectangle (bg_gc, area);
gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
gdk_gc_set_clip_rectangle (bg_gc, NULL);
cl_draw_inset (style, window, widget, area, x, y, width, height,
CL_CORNER_NONE, CL_CORNER_ROUND,
CL_CORNER_NONE, CL_CORNER_ROUND);
-
+
return;
}
if (!strcmp (detail, "spinbutton_up"))
{
tr = CL_CORNER_ROUND;
-
+
(style->xthickness > 2 && style->ythickness > 2) ? y++ : height++;
}
-
+
if (!strcmp (detail, "spinbutton_down"))
{
br = CL_CORNER_ROUND;
-
+
if (style->xthickness > 2 && style->ythickness > 2)
height--;
}
-
+
cl_rectangle_set_button (&r, style, state_type,
GTK_WIDGET_HAS_DEFAULT (widget),
GTK_WIDGET_HAS_FOCUS (widget),
tl, tr,
bl, br);
width--;
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
gint x, gint y, gint width, gint height)
{
CLRectangle r;
-
+
gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
gboolean has_focus = GTK_WIDGET_HAS_FOCUS (widget);
-
+
int cl = rtl ? CL_CORNER_NONE : CL_CORNER_ROUND,
cr = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
-
+
GdkGC *bg_gc = cl_get_window_bg_gc(widget);
-
+
if (rtl)
{
if (!has_focus)
width += 2;
if (has_focus) width--; /* this gives us a 2px focus line at the right side. */
}
-
+
cl_rectangle_set_entry (&r, style, state_type,
cl, cr, cl, cr,
has_focus);
width-=2;
height-=2;
}
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
-
+
cl_rectangle_reset_clip_rectangle (&r);
}
GTK_WIDGET_HAS_FOCUS (widget),
CL_CORNER_NONE, CL_CORNER_ROUND,
CL_CORNER_NONE, CL_CORNER_ROUND);
-
+
if (state_type == GTK_STATE_ACTIVE)
is_active = TRUE;
else
r.fillgc = NULL;
-
+
/* Seriously, why can't non-gtk-apps at least try to be decent citizens?
Take this fscking OpenOffice.org 1.9 for example. The morons responsible
for this utter piece of crap give the clip size wrong values! :'( */
-
+
if (area)
{
area->x = x;
x--;
width++;
-
+
/* Draw "sunken" look when border thickness is more than 2 pixels. */
if (GTK_IS_COMBO(widget->parent))
draw_inset = (widget->parent->style->xthickness > 2 &&
widget->parent->style->ythickness > 2);
else
draw_inset = (style->xthickness > 2 && style->ythickness > 2);
-
+
if (draw_inset)
{
cl_draw_inset (style, window, widget, area, x, y, width, height,
CL_CORNER_NONE, CL_CORNER_ROUND,
CL_CORNER_NONE, CL_CORNER_ROUND);
-
+
x++;
y++;
height-=2;
x++;
width--;
}
-
+
if (area)
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
-
+
if (!is_active)
{
int tmp_height = (float)height*0.25;
-
+
gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2,y+2,width-4,tmp_height,
&clearlooks_style->button_g1[state_type],
&clearlooks_style->button_g2[state_type]);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2, y+2+tmp_height, width-4, height-3-tmp_height*2,
&clearlooks_style->button_g2[state_type],
&clearlooks_style->button_g3[state_type]);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x+2,y+height-tmp_height-1,width-4,tmp_height,
&clearlooks_style->button_g3[state_type],
&clearlooks_style->button_g4[state_type]);
gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
- }
-
+ }
+
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
if (area)
CLRectangle r;
gboolean has_focus = GTK_WIDGET_HAS_FOCUS(widget);
GdkGC *bg_gc = cl_get_window_bg_gc(widget);
-
+
gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
gtk_style_apply_default_background (style, window, TRUE, state_type,
area, x+1, y+1, width-2, height-2);
-
+
cl_rectangle_set_entry (&r, style, state_type,
CL_CORNER_ROUND, CL_CORNER_ROUND,
CL_CORNER_ROUND, CL_CORNER_ROUND,
has_focus);
-
+
/* Draw "sunken" look when border thickness is more than 2 pixels. */
if (style->xthickness > 2 && style->ythickness > 2)
{
cl_draw_inset (style, window, widget, area, x, y, width, height,
CL_CORNER_ROUND, CL_CORNER_ROUND,
CL_CORNER_ROUND, CL_CORNER_ROUND);
-
+
x++;
y++;
width-=2;
height-=2;
}
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
int line_pos;
option_menu_get_props (widget, &indicator_size, &indicator_spacing);
-
+
if (get_direction (widget) == GTK_TEXT_DIR_RTL)
line_pos = x + (indicator_size.width + indicator_spacing.left + indicator_spacing.right) + style->xthickness;
else
line_pos = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
cl_draw_button (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
-
+
gdk_draw_line (window, clearlooks_style->shade_gc[3],
line_pos, y + style->ythickness - 1, line_pos,
y + height - style->ythickness);
GdkColor lower_color;
shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.85);
-
+
if (menubar)
{
height++;
{
r->bordergc = clearlooks_style->spot3_gc;
}
-
+
cl_rectangle_set_corners (r, corner, corner, corner, corner);
-
+
cl_rectangle_set_gradient (&r->fill_gradient,
&style->base[GTK_STATE_SELECTED], &lower_color);
r->gradient_type = CL_GRADIENT_VERTICAL;
-
+
r->fillgc = clearlooks_style->spot2_gc;
r->topleft = clearlooks_style->spot1_gc;
-
+
cl_rectangle_set_clip_rectangle (r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, r);
cl_draw_shadow (window, widget, style, x, y, width, height, r);
ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style;
gboolean menubar = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE;
GdkColor tmp;
-
+
cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW,
CL_CORNER_NARROW, CL_CORNER_NARROW);
-
+
tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap,
&style->base[GTK_STATE_PRELIGHT], 0.8);
r->bordergc = style->black_gc;
r->fillgc = style->base_gc[GTK_STATE_PRELIGHT];
-
+
if (menubar) height++;
cl_rectangle_set_clip_rectangle (r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, r);
- cl_rectangle_reset_clip_rectangle (r);
-
+ cl_rectangle_reset_clip_rectangle (r);
+
gdk_gc_set_foreground (style->black_gc, &tmp);
}
gboolean menubar = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE;
GdkColor tmp;
GdkColor lower_color;
-
+
shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.8);
-
+
cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW,
CL_CORNER_NARROW, CL_CORNER_NARROW);
-
+
cl_rectangle_set_gradient (&r->fill_gradient,
&style->base[GTK_STATE_SELECTED], &lower_color);
r->gradient_type = CL_GRADIENT_VERTICAL;
-
+
tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap,
&style->base[GTK_STATE_PRELIGHT], 0.8);
r->bordergc = style->black_gc;
r->fillgc = style->base_gc[GTK_STATE_PRELIGHT];
-
+
if (menubar) height++;
cl_rectangle_set_clip_rectangle (r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, r);
cl_rectangle_reset_clip_rectangle (r);
-
+
gdk_gc_set_foreground (style->black_gc, &tmp);
}
gint columns = 0, column_index = -1, fill_width = width;
gboolean is_etree = strcmp("ETree", G_OBJECT_TYPE_NAME(widget->parent)) == 0;
gboolean resizable = TRUE;
-
+
GdkGC *bottom = clearlooks_style->shade_gc[5];
-
+
if ( width < 2 || height < 2 )
return;
-
+
if (GTK_IS_TREE_VIEW (widget->parent))
{
gtk_treeview_get_header_index (GTK_TREE_VIEW(widget->parent),
gtk_clist_get_header_index (GTK_CLIST(widget->parent),
widget, &column_index, &columns);
}
-
+
if (area)
{
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], area);
- gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
+ gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], area);
}
-
+
if (state_type != GTK_STATE_NORMAL)
fill_width-=2;
-
+
gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, x, y, fill_width, height-(height/3)+1);
-
+
draw_hgradient (window, style->bg_gc[state_type], style,
x, 1+y+height-(height/3), fill_width, height/3,
&style->bg[state_type], &clearlooks_style->inset_dark[state_type]);
gdk_draw_line (window, clearlooks_style->shade_gc[4], x+width-2, y+4, x+width-2, y+height-5);
gdk_draw_line (window, clearlooks_style->shade_gc[0], x+width-1, y+4, x+width-1, y+height-5);
}
-
+
/* left light line */
if (column_index == 0)
gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y+1, x, y+height-2);
-
+
/* top light line */
gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y, x+width-1, y);
-
+
/* bottom dark line */
if (state_type == GTK_STATE_INSENSITIVE)
bottom = clearlooks_style->shade_gc[3];
-
-
+
+
gdk_draw_line (window, bottom, x, y+height-1, x+width-1, y+height-1);
-
+
if (area)
{
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], NULL);
gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], NULL);
- }
+ }
}
{
CLGradient fill_gradient;
CLGradient border_gradient;
-
+
CLGradientType gradient_type;
-
+
GdkGC *bordergc;
GdkGC *fillgc;
guint8 corners[4];
-
+
GdkGC *topleft; /* top + left shadow */
GdkGC *bottomright; /* bottom + right shadow */
-
+
GdkColor tmp_color; /* used for gradient */
} CLRectangle;
CLBorderType tl, CLBorderType tr,
CLBorderType bl, CLBorderType br,
gboolean has_focus);
-
+
void cl_draw_shadow(GdkWindow *window, GtkWidget *widget, GtkStyle *style,
int x, int y, int width, int height, CLRectangle *r);
GdkPixmap* cl_progressbar_tile_new (GdkDrawable *drawable, GtkWidget *widget,
GtkStyle *style, gint height, gint offset);
-
+
void cl_progressbar_fill (GdkDrawable *drawable, GtkWidget *widget,
GtkStyle *style, GdkGC *gc,
gint x, gint y, gint width, gint height,
guint8 offset, GdkRectangle *area);
-
+
GdkColor cl_gc_set_fg_color_shade (GdkGC *gc, GdkColormap *colormap,
GdkColor *from, gfloat s);
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
void cl_draw_button(GtkStyle *style, GdkWindow *window,
GtkStateType state_type, GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
void cl_draw_entry (GtkStyle *style, GdkWindow *window,
GtkStateType state_type, GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
void cl_draw_combobox_entry (GtkStyle *style, GdkWindow *window,
GtkStateType state_type, GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
void cl_draw_combobox_button (GtkStyle *style, GdkWindow *window,
GtkStateType state_type, GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
void cl_draw_menuitem_button (GdkDrawable *window, GtkWidget *widget, GtkStyle *style,
GdkRectangle *area, GtkStateType state_type,
int x, int y, int wiidth, int height, CLRectangle *r);
void cl_draw_menuitem_gradient (GdkDrawable *window, GtkWidget *widget, GtkStyle *style,
GdkRectangle *area, GtkStateType state_type,
int x, int y, int wiidth, int height, CLRectangle *r);
-
+
void cl_draw_treeview_header (GtkStyle *style, GdkWindow *window,
GtkStateType state_type, GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget, const gchar *detail,
gint x, gint y, gint width, gint height);
-
+
#endif /* CLEARLOOKS_DRAW_H */
guint8 *listviewitemstyle)
{
guint token;
-
+
token = g_scanner_get_next_token(scanner);
-
+
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_EQUAL_SIGN)
return G_TOKEN_EQUAL_SIGN;
-
+
token = g_scanner_get_next_token(scanner);
if (token != G_TOKEN_INT)
return G_TOKEN_INT;
-
+
*listviewitemstyle = scanner->value.v_int;
-
+
return G_TOKEN_NONE;
}
clearlooks_rc_style_parse (GtkRcStyle *rc_style,
GtkSettings *settings,
GScanner *scanner)
-
+
{
static GQuark scope_id = 0;
ClearlooksRcStyle *clearlooks_style = CLEARLOOKS_RC_STYLE (rc_style);
GtkRcStyle *src)
{
ClearlooksRcStyle *dest_w, *src_w;
-
+
parent_class->merge (dest, src);
-
+
if (!CLEARLOOKS_IS_RC_STYLE (src))
return;
-
+
src_w = CLEARLOOKS_RC_STYLE (src);
dest_w = CLEARLOOKS_RC_STYLE (dest);
-
+
dest_w->contrast = src_w->contrast;
dest_w->sunkenmenubar = src_w->sunkenmenubar;
dest_w->progressbarstyle = src_w->progressbarstyle;
progressbars = g_list_remove (progressbars, data);
g_object_unref (data);
-
+
if (g_list_first(progressbars) == NULL) {
g_source_remove(timer_id);
timer_id = 0;
return;
fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (data));
-
+
/* update only if not filled */
if (fraction < 1.0)
gtk_widget_queue_resize ((GtkWidget*)data);
-
+
if (fraction >= 1.0 || GTK_PROGRESS (data)->activity_mode)
cl_progressbar_remove (data);
}
g_object_ref (data);
g_signal_connect ((GObject*)data, "unrealize", G_CALLBACK (cl_progressbar_remove), data);
-
+
if (timer_id == 0)
timer_id = g_timeout_add (100, timer_func, NULL);
}
clearlooks_get_spot_color (ClearlooksRcStyle *clearlooks_rc)
{
GtkRcStyle *rc = GTK_RC_STYLE (clearlooks_rc);
-
+
if (clearlooks_rc->has_spot_color)
return &clearlooks_rc->spot_color;
else
GtkRequisition indicator_size;
GtkBorder indicator_spacing;
gint arrow_height;
-
+
option_menu_get_props (widget, &indicator_size, &indicator_spacing);
-
+
indicator_size.width += (indicator_size.width % 2) - 1;
arrow_height = indicator_size.width / 2 + 2;
-
+
x += (width - indicator_size.width) / 2;
y += height/2;
GTK_ARROW_DOWN, 1+x, 1+y+1,
indicator_size.width, arrow_height);
}
-
+
draw_arrow (window, style->fg_gc[state_type], area,
GTK_ARROW_UP, x, y-arrow_height,
indicator_size.width, arrow_height);
-
+
draw_arrow (window, style->fg_gc[state_type], area,
GTK_ARROW_DOWN, x, y+1,
indicator_size.width, arrow_height);
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
gint original_width, original_x;
GdkGC *gc;
-
+
sanitize_size (window, &width, &height);
-
+
if (is_combo_box (widget))
{
width = 7;
GTK_ARROW_DOWN, 1+x, 1+y+1,
width, height);
}
-
+
draw_arrow (window, style->fg_gc[state], area,
GTK_ARROW_UP, x, y-height,
width, height);
-
+
draw_arrow (window, style->fg_gc[state], area,
GTK_ARROW_DOWN, x, y+1,
width, height);
-
+
return;
}
-
+
original_width = width;
original_x = x;
-
+
/* Make spinbutton arrows and arrows in menus
* slightly larger to get the right pixels drawn */
if (DETAIL ("spinbutton"))
height += 1;
-
+
if (DETAIL("menuitem"))
{
width = 6;
height = 7;
}
-
+
/* Compensate arrow position for "sunken" look */
if (DETAIL ("spinbutton") && arrow_type == GTK_ARROW_DOWN &&
style->xthickness > 2 && style->ythickness > 2)
y -= 1;
-
+
if (widget && widget->parent && GTK_IS_COMBO (widget->parent->parent))
{
width -= 2;
height -=2;
x++;
}
-
+
calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
-
+
if (DETAIL ("menuitem"))
x = original_x + original_width - width;
-
+
if (DETAIL ("spinbutton") && (arrow_type == GTK_ARROW_DOWN))
y += 1;
-
+
if (state == GTK_STATE_INSENSITIVE)
draw_arrow (window, style->light_gc[state], area, arrow_type, x + 1, y + 1, width, height);
gc = style->fg_gc[state];
-
+
draw_arrow (window, gc, area, arrow_type, x, y, width, height);
}
sanitize_size (window, &width, &height);
- if (detail &&
+ if (detail &&
clearlooks_style->listviewitemstyle == 1 &&
state_type == GTK_STATE_SELECTED && (
!strncmp ("cell_even", detail, strlen ("cell_even")) ||
gc = style->base_gc[GTK_STATE_ACTIVE];
upper_color = &style->base[GTK_STATE_ACTIVE];
}
-
+
if (GTK_IS_TREE_VIEW (widget) && 0)
{
GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
return;
}
}
-
+
shade (upper_color, &lower_color, 0.8);
if (area)
gdk_gc_set_clip_rectangle (gc, area);
-
+
draw_hgradient (window, gc, style,
x, y, width, height, upper_color, &lower_color);
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
CLRectangle r;
-
+
GdkGC *outer_gc = clearlooks_style->shade_gc[4];
GdkGC *gc1 = NULL;
GdkGC *gc2 = NULL;
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], area);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area);
}
-
+
gdk_draw_line (window, clearlooks_style->shade_gc[3],
x, y, x + width, y);
gdk_draw_line (window, clearlooks_style->shade_gc[0],
x, y + 1, x + width, y + 1);
-
+
if (area)
{
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], NULL);
{
GdkGC *a = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 0 : 3];
GdkGC *b = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 3 : 0];
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r);
cl_rectangle_reset_clip_rectangle (&r);
-
+
r.bordergc = b;
cl_rectangle_set_clip_rectangle (&r, area);
- cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r);
+ cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r);
cl_rectangle_reset_clip_rectangle (&r);
}
else if (shadow_type == GTK_SHADOW_ETCHED_IN)
{
GdkGC *a = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 3 : 0];
GdkGC *b = clearlooks_style->shade_gc[(shadow_type == GTK_SHADOW_ETCHED_IN) ? 0 : 3];
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r);
cl_rectangle_reset_clip_rectangle (&r);
-
+
r.bordergc = b;
cl_rectangle_set_clip_rectangle (&r, area);
- cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r);
+ cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r);
cl_rectangle_reset_clip_rectangle (&r);
- }
+ }
else
parent_class->draw_shadow (style, window, state_type, shadow_type,
area, widget, detail,
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
CLRectangle r;
-
+
GdkRegion *area_region = NULL,
*gap_region = NULL;
GdkRectangle light_rect;
#if DEBUG
printf("draw_box_gap: %s %d %d %d %d\n", detail, x, y, width, height);
#endif
-
+
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
sanitize_size (window, &width, &height);
cl_rectangle_reset (&r, style);
GdkRectangle tmp = { x, y, width, height };
area_region = gdk_region_rectangle (&tmp);
}
-
+
switch (gap_side)
{
case GTK_POS_TOP:
GDK_RECTANGLE_SET (light_rect, x+gap_x+1, y, x+gap_x+1, y+1);
GDK_RECTANGLE_SET (dark_rect, x+gap_x+gap_width-2, y, x+gap_x+gap_width-2, y);
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_ROUND, CL_CORNER_ROUND);
{
GdkRectangle rect = { x+gap_x+1, y+height-2, gap_width-2, 2 };
gap_region = gdk_region_rectangle (&rect);
-
+
GDK_RECTANGLE_SET (light_rect, x+gap_x+1, y+height-2, x+gap_x+1, y+height-1);
GDK_RECTANGLE_SET (dark_rect, x+gap_x+gap_width-2, y+height-2, x+gap_x+gap_width-2, y+height-1);
{
GdkRectangle rect = { x, y+gap_x+1, 2, gap_width-2 };
gap_region = gdk_region_rectangle (&rect);
-
+
GDK_RECTANGLE_SET (light_rect, x, y+gap_x+1, x+1, y+gap_x+1);
GDK_RECTANGLE_SET (dark_rect, x, y+gap_x+gap_width-2, x, y+gap_x+gap_width-2);
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_ROUND,
CL_CORNER_NONE, CL_CORNER_ROUND);
break;
- }
+ }
case GTK_POS_RIGHT:
{
GdkRectangle rect = { x+width-2, y+gap_x+1, 2, gap_width-2 };
gap_region = gdk_region_rectangle (&rect);
-
+
GDK_RECTANGLE_SET (light_rect, x+width-2, y+gap_x+1, x+width-1, y+gap_x+1);
GDK_RECTANGLE_SET (dark_rect, x+width-2, y+gap_x+gap_width-2, x+width-1, y+gap_x+gap_width-2);
cl_rectangle_set_corners (&r, CL_CORNER_ROUND, CL_CORNER_NONE,
CL_CORNER_ROUND, CL_CORNER_NONE);
break;
- }
+ }
}
-
+
gdk_region_subtract (area_region, gap_region);
-
+
gdk_gc_set_clip_region (r.bordergc, area_region);
gdk_gc_set_clip_region (r.topleft, area_region);
gdk_gc_set_clip_region (r.bottomright, area_region);
-
+
gdk_region_destroy (area_region);
gdk_region_destroy (gap_region);
-
+
gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, x, y, width, height);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
gdk_gc_set_clip_region (r.bordergc, NULL);
gdk_gc_set_clip_region (r.topleft, NULL);
gdk_gc_set_clip_region (r.bottomright, NULL);
-
+
/* it's a semi hack */
gdk_draw_line (window, style->light_gc[state_type],
light_rect.x, light_rect.y,
light_rect.width, light_rect.height);
-
+
gdk_draw_line (window, clearlooks_style->shade_gc[1],
dark_rect.x, dark_rect.y,
dark_rect.width, dark_rect.height);
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
sanitize_size (window, &width, &height);
-
+
if (DETAIL ("tab"))
{
GdkRectangle new_area;
cl_rectangle_set_button (&r, style, state_type, FALSE, FALSE,
CL_CORNER_ROUND, CL_CORNER_ROUND,
CL_CORNER_ROUND, CL_CORNER_ROUND);
-
+
if (state_type == GTK_STATE_ACTIVE)
shade (&style->bg[state_type], &tmp_color, 1.08);
else
shade (&style->bg[state_type], &tmp_color, 1.05);
-
+
if (area)
{
new_area = *area;
new_area.width = width;
new_area.height = height;
}
-
+
switch (gap_side)
{
case GTK_POS_BOTTOM:
&clearlooks_style->border[CL_BORDER_LOWER+my_state_type]);
break;
}
-
- r.topleft = style->light_gc[state_type];
+
+ r.topleft = style->light_gc[state_type];
r.bottomright = (state_type == GTK_STATE_NORMAL) ? clearlooks_style->shade_gc[1] : NULL;
cl_rectangle_set_clip_rectangle (&r, &new_area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
-
+
/* draw the selection stripe */
if (state_type != GTK_STATE_ACTIVE) {
cl_rectangle_set_gradient (&r.fill_gradient, NULL, NULL);
r.fillgc = clearlooks_style->spot2_gc;
-
+
switch (gap_side)
{
case GTK_POS_BOTTOM:
CL_CORNER_ROUND, CL_CORNER_NONE);
cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->spot3, &clearlooks_style->spot2);
r.gradient_type = CL_GRADIENT_HORIZONTAL;
-
+
cl_rectangle_set_clip_rectangle (&r, &new_area);
cl_draw_rectangle (window, widget, style, x, y, 3, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
break;
}
}
-
+
}
else
int i;
int n_lines;
int offset;
-
+
#if DEBUG
printf("draw_handle: %s %d %d %d %d\n", detail, x, y, width, height);
#endif
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
sanitize_size (window, &width, &height);
-
+
if (state_type == GTK_STATE_PRELIGHT)
gtk_style_apply_default_background (style, window,
widget && !GTK_WIDGET_NO_WINDOW (widget),
orientation == GTK_ORIENTATION_VERTICAL )
{
/* The line in the toolbar */
-
+
light_gc = style->light_gc[state_type];
dark_gc = clearlooks_style->shade_gc[3];
-
+
if (area)
{
gdk_gc_set_clip_rectangle (light_gc, area);
gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y, x + width, y);
gdk_draw_line (window, clearlooks_style->shade_gc[3], x, y + height - 1, x + width, y + height - 1);
-
+
if (area)
{
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], NULL);
}
}
-
+
light_gc = clearlooks_style->shade_gc[0];
dark_gc = clearlooks_style->shade_gc[4];
rect.y = y + ythick;
rect.width = width - (xthick * 2);
rect.height = height - (ythick * 2);
-
+
if (area)
intersect = gdk_rectangle_intersect (area, &rect, &dest);
else
gdk_gc_set_clip_rectangle (light_gc, &dest);
gdk_gc_set_clip_rectangle (dark_gc, &dest);
-
+
n_lines = (!strcmp (detail, "paned")) ? 21 : 11;
if (orientation == GTK_ORIENTATION_VERTICAL)
- {
+ {
h = width - 2 * xthick;
h = MAX (3, h - 6);
-
+
xx = x + (width - h) / 2;
offset = (height - 2*ythick - 2*n_lines)/2 + 1;
if (offset < 0)
offset = 0;
-
+
for (i = 0, yy = y + ythick + offset; yy <= (y + height - ythick - 1) && i < n_lines; yy += 2, i++)
{
gdk_draw_line (window, dark_gc, xx, yy, xx + h, yy);
{
h = height - 2 * ythick;
h = MAX (3, h - 6);
-
+
yy = y + (height - h) / 2;
offset = (width - 2*xthick - 2*n_lines)/2 + 1;
if (offset < 0)
offset = 0;
-
+
for (i = 0, xx = x + xthick + offset; i < n_lines; xx += 2, i++)
{
gdk_draw_line (window, dark_gc, xx, yy, xx, yy + h);
#ifdef DEBUG
printf("draw_box: %s %d %d %d %d\n", detail, x, y, width, height);
#endif
-
+
g_return_if_fail (style != NULL);
g_return_if_fail (window != NULL);
if (width == -1 || height == -1)
false_size = TRUE;
-
+
if ((width == -1) && (height == -1))
gdk_window_get_size (window, &width, &height);
else if (width == -1)
if (widget == NULL)
return;
-
+
/* listview headers */
if (widget && DETAIL ("button") && widget->parent &&
(GTK_IS_TREE_VIEW(widget->parent) ||
!strcmp (detail, "spinbutton_up") ||
!strcmp (detail, "spinbutton_down") ||
!strcmp (detail, "spinbutton")))
- {
+ {
cl_draw_spinbutton (style, window, state_type, shadow_type, area,
widget, detail, x, y, width, height);
}
r.fill_gradient.to = &clearlooks_style->shade[2];
r.bottomright = clearlooks_style->shade_gc[2];
}
-
+
cl_set_corner_sharpness (detail, widget, &r);
if (!strcmp (detail, "spinbutton_up"))
gtk_style_apply_default_background (style, window, FALSE, state_type,
area, x, y, width, height);
}
-
- cl_rectangle_set_clip_rectangle (&r, area);
+
+ cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x+1, y+1, width-2, height-2, &r);
cl_draw_shadow (window, widget, style, x+1, y+1, width-2, height-2, &r);
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
}
else if (DETAIL ("trough") && GTK_IS_PROGRESS_BAR (widget))
{
GdkPoint points[4] = { {x,y}, {x+width-1,y}, {x,y+height-1}, {x+width-1,y+height-1} };
-
+
gdk_draw_points (window, style->bg_gc[state_type], points, 4);
-
+
r.bordergc = clearlooks_style->shade_gc[5];
r.fillgc = clearlooks_style->shade_gc[2];
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NARROW, CL_CORNER_NARROW,
CL_CORNER_NARROW, CL_CORNER_NARROW);
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
*shadow = clearlooks_style->shade_gc[4];
GdkColor upper_color = *clearlooks_get_spot_color (CLEARLOOKS_RC_STYLE (style->rc_style)),
lower_color;
-
+
GtkAdjustment *adjustment = gtk_range_get_adjustment (GTK_RANGE (widget));
-
+
GtkOrientation orientation = GTK_RANGE (widget)->orientation;
-
+
gint fill_size = (orientation ? height : width) *
(1 / ((adjustment->upper - adjustment->lower) /
(adjustment->value - adjustment->lower)));
x += (width - SCALE_SIZE) / 2;
width = SCALE_SIZE;
}
-
+
if (state_type == GTK_STATE_INSENSITIVE)
{
outer = clearlooks_style->shade_gc[4];
inner = clearlooks_style->shade_gc[2];
shadow = clearlooks_style->shade_gc[3];
}
-
+
cl_rectangle_init (&r, inner, outer, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE );
-
+
r.topleft = shadow;
-
- cl_rectangle_set_clip_rectangle (&r, area);
+
+ cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
/* DRAW FILL */
shade (&upper_color, &lower_color, 1.3);
-
+
r.bordergc = clearlooks_style->spot3_gc;
r.fillgc = style->bg_gc[state_type];
-
+
r.gradient_type = (orientation == GTK_ORIENTATION_HORIZONTAL ) ? CL_GRADIENT_VERTICAL
: CL_GRADIENT_HORIZONTAL;
-
+
cl_rectangle_set_gradient (&r.fill_gradient, &upper_color, &lower_color);
-
- cl_rectangle_set_clip_rectangle (&r, area);
+
+ cl_rectangle_set_clip_rectangle (&r, area);
if (orientation == GTK_ORIENTATION_HORIZONTAL && fill_size > 1)
{
if (gtk_range_get_inverted(GTK_RANGE(widget)) != (get_direction(widget) == GTK_TEXT_DIR_RTL))
cl_draw_rectangle (window, widget, style, x+width-fill_size, y, fill_size, height, &r);
else
- cl_draw_rectangle (window, widget, style, x, y, fill_size, height, &r);
+ cl_draw_rectangle (window, widget, style, x, y, fill_size, height, &r);
}
else if (fill_size > 1)
{
if (gtk_range_get_inverted (GTK_RANGE (widget)))
cl_draw_rectangle (window, widget, style, x, y+height-fill_size, width, fill_size, &r);
else
- cl_draw_rectangle (window, widget, style, x, y, width, fill_size, &r);
+ cl_draw_rectangle (window, widget, style, x, y, width, fill_size, &r);
}
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
}
else if (DETAIL ("trough"))
{
GdkGC *inner = clearlooks_style->shade_gc[3],
- *outer = clearlooks_style->shade_gc[5];
-
+ *outer = clearlooks_style->shade_gc[5];
+
cl_rectangle_init (&r, inner, outer, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE );
-
+
if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_VERTICAL)
{
y+=1;
x+=1;
width-=2;
}
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
}
cl_rectangle_set_button (&r, style, state_type, FALSE, FALSE, 0,0,0,0);
-
+
cl_rectangle_set_gradient (&r.fill_gradient, NULL, NULL);
cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->inset_light[state_type],
&clearlooks_style->inset_dark[state_type]);
-
-
+
+
r.gradient_type = horizontal ? CL_GRADIENT_VERTICAL
: CL_GRADIENT_HORIZONTAL;
-
+
r.bottomright = clearlooks_style->shade_gc[1];
r.border_gradient.to = r.border_gradient.from;
-
+
if (button_type == CL_SCROLLBUTTON_OTHER)
{
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_ROUND, CL_CORNER_ROUND);
}
-
- cl_rectangle_set_clip_rectangle (&r, area);
+
+ cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
}
else if (DETAIL ("slider"))
if (DETAIL("slider") && widget && GTK_IS_RANGE (widget))
{
GtkAdjustment *adj = GTK_RANGE (widget)->adjustment;
-
+
if (adj->value <= adj->lower &&
(GTK_RANGE (widget)->has_stepper_a || GTK_RANGE (widget)->has_stepper_b))
{
width+=1;
}
}
-
+
cl_rectangle_set_button (&r, style, state_type, FALSE, GTK_WIDGET_HAS_FOCUS (widget),
CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
-
+
r.gradient_type = GTK_IS_HSCROLLBAR (widget) ? CL_GRADIENT_VERTICAL
: CL_GRADIENT_HORIZONTAL;
r.bottomright = clearlooks_style->shade_gc[1];
r.border_gradient.to = r.border_gradient.from;
-
- cl_rectangle_set_clip_rectangle (&r, area);
+
+ cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
}
else if (detail && !strcmp (detail, "optionmenu")) /* supporting deprecated */
{
if (clearlooks_style->menuitemstyle == 0)
{
cl_draw_menuitem_flat (window, widget, style, area, state_type,
- x, y, width, height, &r);
+ x, y, width, height, &r);
}
else if (clearlooks_style->menuitemstyle == 1)
{
{
GdkGC *dark = clearlooks_style->shade_gc[2];
GdkColor upper_color, lower_color;
-
+
/* don't draw sunken menubar on gnome panel
IT'S A HACK! HORRIBLE HACK! HIDEOUS HACK!
BUT IT WORKS FOR ME(tm)! */
if (widget->parent &&
strcmp(G_OBJECT_TYPE_NAME (widget->parent), "PanelWidget") == 0)
return;
-
+
shade(&style->bg[state_type], &upper_color, 1.0);
shade(&style->bg[state_type], &lower_color, 0.95);
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
-
+
r.fillgc = style->bg_gc[state_type];
r.bordergc = clearlooks_style->shade_gc[2];
r.gradient_type = CL_GRADIENT_VERTICAL;
-
+
cl_rectangle_set_gradient (&r.border_gradient, &clearlooks_style->shade[2],
&clearlooks_style->shade[3]);
cl_rectangle_set_gradient (&r.fill_gradient, &upper_color, &lower_color);
-
+
/* make vertical and top borders invisible for style 2 */
if (clearlooks_style->menubarstyle == 2) {
x--; width+=2;
y--; height+=1;
}
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
}
else if (DETAIL ("menu") && widget->parent &&
GDK_IS_WINDOW (widget->parent->window))
- {
+ {
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
-
+
r.bordergc = clearlooks_style->border_gc[CL_BORDER_UPPER];
r.topleft = style->light_gc[state_type];
r.bottomright = clearlooks_style->shade_gc[1];
-
+
cl_rectangle_set_clip_rectangle (&r, area);
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
- cl_rectangle_reset_clip_rectangle (&r);
+ cl_rectangle_reset_clip_rectangle (&r);
return;
}
lower_color,
prev_foreground;
gboolean activity_mode = GTK_PROGRESS (widget)->activity_mode;
-
+
#ifdef HAVE_ANIMATION
if (!activity_mode && gtk_progress_bar_get_fraction (widget) != 1.0 &&
!cl_progressbar_known((gconstpointer)widget))
{
cl_progressbar_add ((gpointer)widget);
}
-#endif
+#endif
cl_progressbar_fill (window, widget, style, style->black_gc,
x, y, width, height,
#ifdef HAVE_ANIMATION
activity_mode ? 0 : pboffset,
#else
- 0,
+ 0,
#endif
area);
-
+
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
-
+
r.bordergc = clearlooks_style->spot3_gc;
r.topleft = clearlooks_style->spot2_gc;
-
+
prev_foreground = cl_gc_set_fg_color_shade (clearlooks_style->spot2_gc,
style->colormap,
&clearlooks_style->spot2,
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
cl_rectangle_reset_clip_rectangle (&r);
-
+
gdk_gc_set_foreground (clearlooks_style->spot2_gc, &prev_foreground);
}
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area);
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[3], area);
}
-
+
gtk_style_apply_default_background (style, window,
widget && !GTK_WIDGET_NO_WINDOW (widget),
state_type, area, x, y, width, height);
-
+
/* we only want the borders on horizontal toolbars */
if ( DETAIL ("menubar") || height < 2*width ) {
if (!DETAIL ("menubar"))
gdk_draw_line (window, clearlooks_style->shade_gc[0],
x, y, x + width, y); /* top */
-
+
gdk_draw_line (window, clearlooks_style->shade_gc[3],
x, y + height - 1, x + width, y + height - 1); /* bottom */
}
-
+
if (area)
{
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL);
ClearlooksRcStyle *clearlooks_rc = CLEARLOOKS_RC_STYLE (style->rc_style);
GdkPixbuf *check, *base, *inconsistent, *composite;
GdkColor *spot_color = clearlooks_get_spot_color (clearlooks_rc);
-
+
if (clearlooks_style->check_pixmap_nonactive[state] != NULL)
return;
-
+
if (state == GTK_STATE_ACTIVE || state == GTK_STATE_SELECTED) {
check = generate_bit (check_alpha, &style->text[GTK_STATE_NORMAL], 1.0);
inconsistent = generate_bit (check_inconsistent_alpha, &style->text[GTK_STATE_NORMAL], 1.0);
check = generate_bit (check_alpha, &style->text[state], 1.0);
inconsistent = generate_bit (check_inconsistent_alpha, &style->text[state], 1.0);
}
-
+
if (state == GTK_STATE_ACTIVE && !treeview)
base = generate_bit (check_base_alpha, &style->bg[state], 1.0);
else
base = generate_bit (check_base_alpha, &style->base[GTK_STATE_NORMAL], 1.0);
-
+
if (treeview)
composite = generate_bit (NULL, &clearlooks_style->shade[6], 1.0);
else
composite = generate_bit (NULL, &clearlooks_style->shade[5], 1.0);
-
+
gdk_pixbuf_composite (base, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
clearlooks_style->check_pixmap_nonactive[state] =
pixbuf_to_pixmap (style, composite, screen);
-
+
gdk_pixbuf_composite (check, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
y += (height - CHECK_SIZE)/2;
gdk_draw_drawable (window, gc, pixmap, 0, 0, x, y, CHECK_SIZE, CHECK_SIZE);
-
+
if (area)
gdk_gc_set_clip_rectangle (gc, NULL);
}
if ((orientation == GTK_ORIENTATION_VERTICAL && height < 20) ||
(orientation == GTK_ORIENTATION_HORIZONTAL && width < 20))
return;
-
+
if (detail && strcmp ("slider", detail) == 0)
{
if (area)
GdkPixbuf *dot, *circle, *outline, *inconsistent, *composite;
GdkColor *spot_color = clearlooks_get_spot_color (clearlooks_rc);
GdkColor *composite_color;
-
+
if (clearlooks_style->radio_pixmap_nonactive[state] != NULL)
return;
-
+
if (state == GTK_STATE_ACTIVE || state == GTK_STATE_SELECTED) {
dot = colorize_bit (dot_intensity, dot_alpha, &style->text[GTK_STATE_NORMAL]);
inconsistent = generate_bit (inconsistent_alpha, &style->text[GTK_STATE_NORMAL], 1.0);
dot = colorize_bit (dot_intensity, dot_alpha, &style->text[state]);
inconsistent = generate_bit (inconsistent_alpha, &style->text[state], 1.0);
}
-
+
outline = generate_bit (outline_alpha, &clearlooks_style->shade[5], 1.0);
-
+
if (clearlooks_style->radio_pixmap_mask == NULL)
{
gdk_pixbuf_render_pixmap_and_mask (outline,
&clearlooks_style->radio_pixmap_mask,
1);
}
-
+
if (state == GTK_STATE_ACTIVE)
{
composite_color = &style->bg[GTK_STATE_PRELIGHT];
composite_color = &style->bg[state];
circle = generate_bit (circle_alpha, &style->base[GTK_STATE_NORMAL], 1.0);
}
-
+
composite = generate_bit (NULL, composite_color, 1.0);
-
+
gdk_pixbuf_composite (outline, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
-
+
gdk_pixbuf_composite (circle, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
-
+
clearlooks_style->radio_pixmap_nonactive[state] =
pixbuf_to_pixmap (style, composite, screen);
-
+
gdk_pixbuf_composite (dot, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
-
+
clearlooks_style->radio_pixmap_active[state] =
pixbuf_to_pixmap (style, composite, screen);
-
+
g_object_unref (composite);
-
+
composite = generate_bit (NULL, composite_color,1.0);
-
+
gdk_pixbuf_composite (outline, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
gdk_pixbuf_composite (inconsistent, composite,
0, 0, RADIO_SIZE, RADIO_SIZE, 0, 0,
1.0, 1.0, GDK_INTERP_NEAREST, 255);
-
+
clearlooks_style->radio_pixmap_inconsistent[state] =
pixbuf_to_pixmap (style, composite, screen);
-
+
g_object_unref (composite);
g_object_unref (circle);
g_object_unref (dot);
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
GdkGC *gc = style->base_gc[state_type];
GdkPixmap *pixmap;
-
+
if (DETAIL ("option")) /* Menu item */
{
parent_class->draw_option (style, window, state_type, shadow_type,
area, widget, detail, x, y, width, height);
return;
}
-
+
ensure_radio_pixmaps (style, state_type, gtk_widget_get_screen (widget));
-
+
if (area)
gdk_gc_set_clip_rectangle (gc, area);
-
+
if (shadow_type == GTK_SHADOW_IN)
pixmap = clearlooks_style->radio_pixmap_active[state_type];
else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
pixmap = clearlooks_style->radio_pixmap_inconsistent[state_type];
else
pixmap = clearlooks_style->radio_pixmap_nonactive[state_type];
-
+
x += (width - RADIO_SIZE)/2;
y += (height - RADIO_SIZE)/2;
-
+
#ifndef GTKOSX
gdk_gc_set_clip_mask (gc, clearlooks_style->radio_pixmap_mask);
gdk_gc_set_clip_origin (gc, x, y);
#endif
-
+
gdk_draw_drawable (window, gc, pixmap, 0, 0, x, y,
RADIO_SIZE, RADIO_SIZE);
-
+
#ifndef GTKOSX
gdk_gc_set_clip_origin (gc, 0, 0);
gdk_gc_set_clip_mask (gc, NULL);
#endif
-
+
if (area)
gdk_gc_set_clip_rectangle (gc, NULL);
}
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
sanitize_size (window, &width, &height);
cl_rectangle_reset (&r, style);
cl_rectangle_set_corners (&r, CL_CORNER_NONE, CL_CORNER_NONE,
CL_CORNER_NONE, CL_CORNER_NONE);
-
+
if (area)
{
area_region = gdk_region_rectangle (area);
-
+
switch (gap_side)
{
case GTK_POS_TOP:
GdkRectangle rect = { x, y+gap_x, 2, gap_width };
gap_region = gdk_region_rectangle (&rect);
break;
- }
+ }
case GTK_POS_RIGHT:
{
GdkRectangle rect = { x+width-2, y+gap_x, 2, gap_width };
gap_region = gdk_region_rectangle (&rect);
break;
- }
+ }
}
-
+
gdk_region_subtract (area_region, gap_region);
}
-
+
if (shadow_type == GTK_SHADOW_ETCHED_IN ||
shadow_type == GTK_SHADOW_ETCHED_OUT)
{
a = clearlooks_style->shade_gc[3];
b = style->light_gc[state_type];
}
-
- gdk_gc_set_clip_region (a, area_region);
- gdk_gc_set_clip_region (b, area_region);
+
+ gdk_gc_set_clip_region (a, area_region);
+ gdk_gc_set_clip_region (b, area_region);
r.bordergc = a;
cl_draw_rectangle (window, widget, style, x+1, y+1, width-1, height-1, &r);
r.bordergc = b;
cl_draw_rectangle (window, widget, style, x, y, width-1, height-1, &r);
- gdk_gc_set_clip_region (a, NULL);
- gdk_gc_set_clip_region (b, NULL);
+ gdk_gc_set_clip_region (a, NULL);
+ gdk_gc_set_clip_region (b, NULL);
}
else if (shadow_type == GTK_SHADOW_IN || shadow_type == GTK_SHADOW_OUT)
{
r.topleft = (shadow_type == GTK_SHADOW_OUT) ? style->light_gc[state_type] : clearlooks_style->shade_gc[1];
r.bottomright = (shadow_type == GTK_SHADOW_OUT) ? clearlooks_style->shade_gc[1] : style->light_gc[state_type];
r.bordergc = clearlooks_style->shade_gc[5];
-
- gdk_gc_set_clip_region (r.bordergc, area_region);
- gdk_gc_set_clip_region (r.topleft, area_region);
- gdk_gc_set_clip_region (r.bottomright, area_region);
-
+
+ gdk_gc_set_clip_region (r.bordergc, area_region);
+ gdk_gc_set_clip_region (r.topleft, area_region);
+ gdk_gc_set_clip_region (r.bottomright, area_region);
+
cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
-
+
cl_draw_shadow (window, widget, style, x, y, width, height, &r);
gdk_gc_set_clip_region (r.bordergc, NULL);
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
if (area)
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], area);
-
+
if (detail && !strcmp (detail, "label"))
{
if (state_type == GTK_STATE_INSENSITIVE)
gdk_draw_line (window, style->light_gc[state_type], x1 + 1, y + 1, x2 + 1, y + 1);
-
+
gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y);
}
else
{
gdk_draw_line (window, clearlooks_style->shade_gc[2], x1, y, x2, y);
-
+
/* if (DETAIL ("menuitem")) */
gdk_draw_line (window, clearlooks_style->shade_gc[0], x1, y+1, x2, y+1);
}
-
+
if (area)
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], NULL);
}
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (window != NULL);
-
+
thickness_light = style->xthickness / 2;
thickness_dark = style->xthickness - thickness_light;
-
+
if (area)
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], area);
-
+
gdk_draw_line (window, clearlooks_style->shade_gc[2], x, y1, x, y2 - 1);
gdk_draw_line (window, clearlooks_style->shade_gc[0], x+1, y1, x+1, y2 - 1);
-
+
if (area)
gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[2], NULL);
}
#if DEBUG
printf("draw_focus: %s %d %d %d %d\n", detail, x, y, width, height);
#endif
-
+
gc = clearlooks_style->shade_gc[6];
-
+
if (widget)
{
gtk_widget_style_get (widget,
"focus-line-width", &line_width,
"focus-line-pattern", (gchar *)&dash_list,
NULL);
-
+
free_dash_list = TRUE;
}
-
+
sanitize_size (window, &width, &height);
-
+
if (area)
gdk_gc_set_clip_rectangle (gc, area);
-
+
gdk_gc_set_line_attributes (gc, line_width,
dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
GDK_CAP_BUTT, GDK_JOIN_MITER);
-
-
+
+
if (detail && !strcmp (detail, "add-mode"))
{
if (free_dash_list)
g_free (dash_list);
-
+
dash_list = "\4\4";
free_dash_list = FALSE;
}
-
+
points[0].x = x + line_width / 2;
points[0].y = y + line_width / 2;
points[1].x = x + width - line_width + line_width / 2;
points[3].x = x + line_width / 2;
points[3].y = y + height - line_width + line_width / 2;
points[4] = points[0];
-
+
if (!dash_list[0])
{
gdk_draw_lines (window, gc, points, 5);
else
{
dash_len = strlen (dash_list);
-
+
if (dash_list[0])
gdk_gc_set_dashes (gc, 0, dash_list, dash_len);
-
+
gdk_draw_lines (window, gc, points, 3);
-
+
points[2].x += 1;
-
+
if (dash_list[0])
{
gint dash_pixels = 0;
gint i;
-
+
/* Adjust the dash offset for the bottom and left so we
* match up at the upper left.
*/
for (i = 0; i < dash_len; i++)
dash_pixels += dash_list[i];
-
+
if (dash_len % 2 == 1)
dash_pixels *= 2;
-
+
gdk_gc_set_dashes (gc,
dash_pixels - (width + height - 2 * line_width) % dash_pixels,
dash_list, dash_len);
}
-
+
gdk_draw_lines (window, gc, points + 2, 3);
}
-
+
gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
-
+
if (area)
gdk_gc_set_clip_rectangle (gc, NULL);
-
+
if (free_dash_list)
g_free (dash_list);
}
const gchar * detail, gint x, gint y, PangoLayout * layout)
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
-
+
g_return_if_fail(GTK_IS_STYLE (style));
g_return_if_fail(window != NULL);
parent_class->draw_layout(style, window, state_type, use_text,
area, widget, detail, x, y, layout);
-
+
}
/**************************************************************************/
xi -= 3;
yi -= 3;
-
+
}
}
break;
xi -= 3;
yi += 3;
-
+
}
}
break;
double shades[] = {1.065, 0.93, 0.896, 0.85, 0.768, 0.665, 0.4, 0.205};
int i;
double contrast;
-
+
parent_class->init_from_rc (style, rc_style);
-
+
contrast = CLEARLOOKS_RC_STYLE (rc_style)->contrast;
-
+
clearlooks_style->sunkenmenubar = CLEARLOOKS_RC_STYLE (rc_style)->sunkenmenubar;
clearlooks_style->progressbarstyle = CLEARLOOKS_RC_STYLE (rc_style)->progressbarstyle;
clearlooks_style->menubarstyle = CLEARLOOKS_RC_STYLE (rc_style)->menubarstyle;
clearlooks_style->menuitemstyle = CLEARLOOKS_RC_STYLE (rc_style)->menuitemstyle;
clearlooks_style->listviewitemstyle = CLEARLOOKS_RC_STYLE (rc_style)->listviewitemstyle;
-
+
/* Lighter to darker */
for (i = 0; i < 8; i++)
{
shade (&style->bg[GTK_STATE_NORMAL], &clearlooks_style->shade[i],
(shades[i]-0.7) * contrast + 0.7);
}
-
+
spot_color = clearlooks_get_spot_color (CLEARLOOKS_RC_STYLE (rc_style));
-
+
clearlooks_style->spot_color = *spot_color;
shade (&clearlooks_style->spot_color, &clearlooks_style->spot1, 1.42);
shade (&clearlooks_style->spot_color, &clearlooks_style->spot2, 1.05);
GdkColor * color)
{
GdkGCValues gc_values;
-
+
gdk_colormap_alloc_color (style->colormap, color, FALSE, TRUE);
-
+
gc_values.foreground = *color;
-
+
return gtk_gc_get (style->depth, style->colormap, &gc_values, GDK_GC_FOREGROUND);
}
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
int i;
-
+
parent_class->realize (style);
-
+
for (i = 0; i < 8; i++)
clearlooks_style->shade_gc[i] = realize_color (style, &clearlooks_style->shade[i]);
for (i=0; i < CL_BORDER_COUNT; i++)
clearlooks_style->border_gc[i] = realize_color (style, &clearlooks_style->border[i]);
-
+
clearlooks_style->spot1_gc = realize_color (style, &clearlooks_style->spot1);
clearlooks_style->spot2_gc = realize_color (style, &clearlooks_style->spot2);
clearlooks_style->spot3_gc = realize_color (style, &clearlooks_style->spot3);
shade (&style->bg[i], &clearlooks_style->listview_bg[i], 1.015);
gdk_rgb_find_color (style->colormap, &clearlooks_style->listview_bg[i]);
- /* CREATE GRADIENT FOR BUTTONS */
+ /* CREATE GRADIENT FOR BUTTONS */
shade (&style->bg[i], &clearlooks_style->button_g1[i], 1.055);
gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g1[i]);
-
+
shade (&style->bg[i], &clearlooks_style->button_g2[i], 1.005);
gdk_rgb_find_color (style->colormap, &clearlooks_style->button_g2[i]);
{
ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
int i;
-
+
/* We don't free the colors, because we don't know if
* gtk_gc_release() actually freed the GC. FIXME - need
* a way of ref'ing colors explicitely so GtkGC can
*/
for (i=0; i < 8; i++)
gtk_gc_release (clearlooks_style->shade_gc[i]);
-
+
gtk_gc_release (clearlooks_style->spot1_gc);
gtk_gc_release (clearlooks_style->spot2_gc);
gtk_gc_release (clearlooks_style->spot3_gc);
-
+
for (i = 0; i < 5; i++)
{
if (clearlooks_style->radio_pixmap_nonactive[i] != NULL)
g_object_unref (clearlooks_style->radio_pixmap_inconsistent[i]);
clearlooks_style->radio_pixmap_inconsistent[i] = NULL;
}
-
+
if (clearlooks_style->check_pixmap_nonactive[i] != NULL)
{
g_object_unref (clearlooks_style->check_pixmap_nonactive[i]);
clearlooks_style->check_pixmap_inconsistent[i] = NULL;
}
}
-
+
if (clearlooks_style->radio_pixmap_mask != NULL)
g_object_unref (clearlooks_style->radio_pixmap_mask);
-
+
clearlooks_style->radio_pixmap_mask = NULL;
while (progressbars = g_list_first (progressbars))
cl_progressbar_remove (progressbars->data);
-
+
if (timer_id != 0)
{
g_source_remove(timer_id);
- timer_id = 0;
+ timer_id = 0;
}
-
+
parent_class->unrealize (style);
}
GdkPixbuf *base_pixbuf;
GdkScreen *screen;
GtkSettings *settings;
-
+
/* Oddly, style can be NULL in this function, because
* GtkIconSet can be used without a style and if so
* it uses this function.
*/
-
+
base_pixbuf = gtk_icon_source_get_pixbuf (source);
-
+
g_return_val_if_fail (base_pixbuf != NULL, NULL);
-
+
if (widget && gtk_widget_has_screen (widget)) {
screen = gtk_widget_get_screen (widget);
settings = gtk_settings_get_for_screen (screen);
GTK_NOTE (MULTIHEAD,
g_warning ("Using the default screen for gtk_default_render_icon()"));
}
-
+
if (size != (GtkIconSize) -1 && !gtk_icon_size_lookup_for_settings (settings, size, &width, &height)) {
g_warning (G_STRLOC ": invalid icon size '%d'", size);
scaled = scale_or_ref (base_pixbuf, width, height);
else
scaled = g_object_ref (base_pixbuf);
-
+
/* If the state was wildcarded, then generate a state. */
if (gtk_icon_source_get_state_wildcarded (source)) {
if (state == GTK_STATE_INSENSITIVE) {
#endif
gdk_pixbuf_saturate_and_pixelate (stated, stated,
0.1, FALSE);
-
+
g_object_unref (scaled);
} else if (state == GTK_STATE_PRELIGHT) {
stated = gdk_pixbuf_copy (scaled);
-
+
gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1.2, FALSE);
-
+
g_object_unref (scaled);
} else {
stated = scaled;
clearlooks_style_class_init (ClearlooksStyleClass * klass)
{
GtkStyleClass *style_class = GTK_STYLE_CLASS (klass);
-
+
parent_class = g_type_class_peek_parent (klass);
style_class->realize = clearlooks_style_realize;
style_class->draw_box_gap = draw_box_gap;
style_class->draw_extension = draw_extension;
style_class->draw_option = draw_option;
- style_class->draw_layout = draw_layout;
+ style_class->draw_layout = draw_layout;
style_class->render_icon = render_icon;
style_class->draw_flat_box = draw_flat_box;
}
struct _ClearlooksStyle
{
GtkStyle parent_instance;
-
+
GdkColor shade[9];
-
+
GdkColor spot_color;
GdkColor spot1;
GdkColor spot2;
GdkColor spot3;
-
+
GdkColor border[CL_BORDER_COUNT];
-
+
/* from light to dark */
GdkGC *shade_gc[9];
GdkGC *border_gc[CL_BORDER_COUNT];
-
+
GdkGC *spot1_gc;
GdkGC *spot2_gc;
GdkGC *spot3_gc;
-
+
GdkColor inset_light[5];
GdkColor inset_dark[5];
-
+
GdkColor button_g1[5];
GdkColor button_g2[5];
GdkColor button_g3[5];
GdkColor button_g4[5];
-
+
GdkColor listview_bg[5];
GdkPixmap *radio_pixmap_nonactive[5];
GdkPixmap *radio_pixmap_active[5];
GdkPixmap *radio_pixmap_inconsistent[5];
GdkBitmap *radio_pixmap_mask; /* All masks are the same */
-
+
GdkPixmap *check_pixmap_nonactive[5];
GdkPixmap *check_pixmap_active[5];
GdkPixmap *check_pixmap_inconsistent[5];
-
+
gboolean sunkenmenubar:1;
guint8 progressbarstyle;
get_direction (GtkWidget *widget)
{
GtkTextDirection dir;
-
+
if (widget)
dir = gtk_widget_get_direction (widget);
else
dir = GTK_TEXT_DIR_LTR;
-
+
return dir;
}
unsigned char *pixels;
int w, h, rs;
int x, y;
-
+
r = (color->red >> 8) * mult;
r = MIN(r, 255);
g = (color->green >> 8) * mult;
g = MIN(g, 255);
b = (color->blue >> 8) * mult;
b = MIN(b, 255);
-
+
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, RADIO_SIZE, RADIO_SIZE);
-
+
w = gdk_pixbuf_get_width (pixbuf);
h = gdk_pixbuf_get_height (pixbuf);
rs = gdk_pixbuf_get_rowstride (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
-
-
+
+
for (y=0; y < h; y++)
{
for (x=0; x < w; x++)
pixels[y*rs + x*4 + 3] = 255;
}
}
-
+
return pixbuf;
}
int dest_rowstride;
int width, height;
guchar *dest_pixels;
-
+
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, RADIO_SIZE, RADIO_SIZE);
-
+
if (pixbuf == NULL)
return NULL;
-
+
dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
dest_pixels = gdk_pixbuf_get_pixels (pixbuf);
-
+
for (y = 0; y < RADIO_SIZE; y++)
{
src = bit + y * RADIO_SIZE;
asrc = alpha + y * RADIO_SIZE;
dest = dest_pixels + y * dest_rowstride;
-
+
for (x = 0; x < RADIO_SIZE; x++)
{
double dr, dg, db;
-
+
intensity = (src[x] + 0 )/ 255.0;
-
+
if (intensity <= 0.5)
{
/* Go from black at intensity = 0.0 to new_color at intensity = 0.5 */
dg = (new_color->green + (65535 - new_color->green) * (intensity - 0.5) * 2.0) / 65535.0;
db = (new_color->blue + (65535 - new_color->blue) * (intensity - 0.5) * 2.0) / 65535.0;
}
-
+
dest[0] = CLAMP_UCHAR (255 * dr);
dest[1] = CLAMP_UCHAR (255 * dg);
dest[2] = CLAMP_UCHAR (255 * db);
-
+
dest[3] = asrc[x];
dest += 4;
}
}
-
+
return pixbuf;
}
{
GdkGC *tmp_gc;
GdkPixmap *pixmap;
-
+
pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
style->depth);
-
+
gdk_drawable_set_colormap (pixmap, style->colormap);
-
+
tmp_gc = gdk_gc_new (pixmap);
-
+
gdk_pixbuf_render_to_drawable (pixbuf, pixmap, tmp_gc, 0, 0, 0, 0,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
GDK_RGB_DITHER_NORMAL, 0, 0);
-
+
gdk_gc_unref (tmp_gc);
-
+
return pixmap;
}
gdouble blue;
gdouble h, l, s;
gdouble delta;
-
+
red = *r;
green = *g;
blue = *b;
max = red;
else
max = blue;
-
+
if (green < blue)
min = green;
else
max = green;
else
max = blue;
-
+
if (red < blue)
min = red;
else
s = (max - min) / (max + min);
else
s = (max - min) / (2 - max - min);
-
+
delta = max -min;
if (red == max)
h = (green - blue) / delta;
h = 2 + (blue - red) / delta;
else if (blue == max)
h = 4 + (red - green) / delta;
-
+
h *= 60;
if (h < 0.0)
h += 360;
gdouble saturation;
gdouble m1, m2;
gdouble r, g, b;
-
+
lightness = *l;
saturation = *s;
m2 = lightness * (1 + saturation);
else
m2 = lightness + saturation - lightness * saturation;
-
+
m1 = 2 * lightness - m2;
if (saturation == 0)
hue -= 360;
while (hue < 0)
hue += 360;
-
+
if (hue < 60)
r = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
r = m1 + (m2 - m1) * (240 - hue) / 60;
else
r = m1;
-
+
hue = *h;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
-
+
if (hue < 60)
g = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
g = m1 + (m2 - m1) * (240 - hue) / 60;
else
g = m1;
-
+
hue = *h - 120;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
-
+
if (hue < 60)
b = m1 + (m2 - m1) * hue / 60;
else if (hue < 180)
b = m1 + (m2 - m1) * (240 - hue) / 60;
else
b = m1;
-
+
*h = r;
*l = g;
*s = b;
gdouble red;
gdouble green;
gdouble blue;
-
+
red = (gdouble) a->red / 65535.0;
green = (gdouble) a->green / 65535.0;
blue = (gdouble) a->blue / 65535.0;
-
+
rgb_to_hls (&red, &green, &blue);
-
+
green *= k;
if (green > 1.0)
green = 1.0;
else if (green < 0.0)
green = 0.0;
-
+
blue *= k;
if (blue > 1.0)
blue = 1.0;
else if (blue < 0.0)
blue = 0.0;
-
+
hls_to_rgb (&red, &green, &blue);
-
+
b->red = red * 65535.0;
b->green = green * 65535.0;
b->blue = blue * 65535.0;
case GTK_ARROW_DOWN:
w += (w % 2) - 1;
h = (w / 2 + 1) + 1;
-
+
if (h > *height)
{
h = *height;
w = 2 * (h - 1) - 1;
}
-
+
if (arrow_type == GTK_ARROW_DOWN)
{
if (*height % 2 == 1 || h % 2 == 0)
*height -= 1;
}
break;
-
+
case GTK_ARROW_RIGHT:
case GTK_ARROW_LEFT:
h += (h % 2) - 1;
w = (h / 2 + 1) + 1;
-
+
if (w > *width)
{
w = *width;
h = 2 * (w - 1) - 1;
}
-
+
if (arrow_type == GTK_ARROW_RIGHT)
{
if (*width % 2 == 1 || w % 2 == 0)
*width -= 1;
}
break;
-
+
default:
/* should not be reached */
break;
{
*columns = clist->columns;
int i;
-
+
for (i=0; i<*columns; i++)
{
if (clist->column[i].button == button)
gint *height)
{
gboolean set_bg = FALSE;
-
+
if ((*width == -1) && (*height == -1))
{
set_bg = GDK_IS_WINDOW (window);
gdk_window_get_size (window, width, NULL);
else if (*height == -1)
gdk_window_get_size (window, NULL, height);
-
+
return set_bg;
}
{
GtkRequisition *tmp_size = NULL;
GtkBorder *tmp_spacing = NULL;
-
+
if (widget)
gtk_widget_style_get (widget, "indicator_size", &tmp_size,
"indicator_spacing", &tmp_spacing, NULL);
-
+
if (tmp_size)
{
*indicator_size = *tmp_size;
}
else
*indicator_size = default_option_indicator_size;
-
+
if (tmp_spacing)
{
*indicator_spacing = *tmp_spacing;
*red = (guchar) (color->red / 256.0);
*green = (guchar) (color->green / 256.0);
*blue = (guchar) (color->blue / 256.0);
-}
+}
static GdkPixbuf*
internal_create_horizontal_gradient_image_buffer (gint width, gint height,
gint i, j, max_block, last_block;
long r, g, b, dr, dg, db;
GdkPixbuf *buffer;
-
+
guchar *ptr;
guchar point[4];
ptr[0] = r>>16;
ptr[1] = g>>16;
ptr[2] = b>>16;
-
+
if (width > 1)
{
last_block = 0;
g += dg;
b += db;
}
-
+
return buffer;
}
#endif
{
GdkPixbuf *image_buffer = NULL;
-
+
image_buffer = internal_create_horizontal_gradient_image_buffer (width, height, left_color, right_color);
-
+
if (image_buffer)
{
gdk_draw_pixbuf(drawable, gc, image_buffer, 0, 0, x, y, width, height, GDK_RGB_DITHER_MAX, 0, 0);
g_object_unref(image_buffer);
- }
+ }
}
#ifndef ALWAYS_DITHER_GRADIENTS
else
GdkGCValues old_values;
gdk_gc_get_values (gc, &old_values);
-
+
if (left_color == right_color )
{
col = *left_color;
gdk_gc_set_foreground (gc, &old_values.foreground);
return;
}
-
+
col = *left_color;
dr = (right_color->red - left_color->red) / width;
dg = (right_color->green - left_color->green) / width;
for (i = 0; i < width; i++)
{
gdk_rgb_find_color (style->colormap, &col);
-
+
gdk_gc_set_foreground (gc, &col);
gdk_draw_line (drawable, gc, x + i, y, x + i, y + height - 1);
-
+
col.red += dr;
col.green += dg;
col.blue += db;
draw_hgradient (GdkDrawable *drawable, GdkGC *gc, GtkStyle *style,
int x, int y, int width, int height,
GdkColor *top_color, GdkColor *bottom_color)
-{
+{
#ifndef ALWAYS_DITHER_GRADIENTS
gboolean dither = ((style->depth > 0) && (style->depth <= 16));
#endif
-
+
if ((width <= 0) || (height <= 0))
return;
#endif
{
GdkPixbuf *image_buffer = NULL;
-
+
image_buffer = internal_create_vertical_gradient_image_buffer (width, height, top_color, bottom_color);
-
+
if (image_buffer)
{
gdk_draw_pixbuf(drawable, gc, image_buffer, 0, 0, x, y, width, height, GDK_RGB_DITHER_MAX, 0, 0);
g_object_unref(image_buffer);
- }
+ }
}
#ifndef ALWAYS_DITHER_GRADIENTS
else
GdkColor col;
int dr, dg, db;
GdkGCValues old_values;
-
+
gdk_gc_get_values (gc, &old_values);
if (top_color == bottom_color )
dr = (bottom_color->red - top_color->red) / height;
dg = (bottom_color->green - top_color->green) / height;
db = (bottom_color->blue - top_color->blue) / height;
-
+
for (i = 0; i < height; i++)
{
gdk_rgb_find_color (style->colormap, &col);
-
+
gdk_gc_set_foreground (gc, &col);
gdk_draw_line (drawable, gc, x, y + i, x + width - 1, y + i);
-
+
col.red += dr;
col.green += dg;
col.blue += db;
c->red = (a->red * alpha + b->red * inAlpha) / 100;
c->green = (a->green * alpha + b->green * inAlpha) / 100;
c->blue = (a->blue * alpha + b->blue * inAlpha) / 100;
-
+
gdk_rgb_find_color (colormap, c);
}
find_combo_box_widget (GtkWidget * widget)
{
GtkWidget *result = NULL;
-
+
if (widget && !GTK_IS_COMBO_BOX_ENTRY (widget))
{
if (GTK_IS_COMBO_BOX (widget))
else
result = find_combo_box_widget(widget->parent);
}
-
+
return result;
}
gint *y,
gint *width,
gint *height);
-
+
GtkWidget *special_get_ancestor(GtkWidget * widget,
GType widget_type);
-
+
void blend (GdkColormap *colormap,
GdkColor *a, GdkColor *b, GdkColor *c, int alpha);
-
+
GtkWidget *get_parent_window (GtkWidget *widget);
GdkColor *get_parent_bgcolor (GtkWidget *widget);
void set_descriptor(const ParameterDescriptor& d) { _desc = d; }
EventList::size_type size() const { return _events.size(); }
- double length() const {
+ double length() const {
Glib::Threads::RWLock::ReaderLock lm (_lock);
return _events.empty() ? 0.0 : _events.back()->when;
}
virtual void add (double when, double value, bool with_guards=true, bool with_initial=true);
virtual void editor_add (double when, double value, bool with_guard);
-
+
void fast_simple_add (double when, double value);
void erase_range (double start, double end);
Controls _controls;
PBD::ScopedConnectionList _list_connections;
-
+
private:
PBD::ScopedConnectionList _control_connections;
bool empty() const { return from == to; }
};
-template<typename T>
+template<typename T>
bool operator== (Range<T> a, Range<T> b) {
return a.from == b.from && a.to == b.to;
}
class /*LIBEVORAL_API*/ RangeList {
public:
RangeList () : _dirty (false) {}
-
+
typedef std::list<Range<T> > List;
List const & get () {
return;
}
- restart:
+ restart:
for (typename List::iterator i = _list.begin(); i != _list.end(); ++i) {
for (typename List::iterator j = _list.begin(); j != _list.end(); ++j) {
}
private:
-
+
List _list;
bool _dirty;
};
/* The basic idea here is to keep a list of the result ranges, and subtract
the bits of `sub' from them one by one.
*/
-
+
for (typename RangeList<T>::List::const_iterator i = s.begin(); i != s.end(); ++i) {
/* Here's where we'll put the new current result after subtracting *i from it */
B origin_b () const {
return _origin_b;
}
-
+
void set_origin_b (B o) {
_origin_b = o;
}
class LIBEVORAL_TEMPLATE_API IdentityConverter : public TimeConverter<A,B> {
public:
IdentityConverter() {}
-
+
B to(A a) const;
A from(B b) const;
};
// see http://www.midi.org/techspecs/midimessages.php
if (status == MIDI_CMD_COMMON_SYSEX) {
int end;
-
+
for (end = 1; buffer[end] != MIDI_CMD_COMMON_SYSEX_END; end++) {
if ((buffer[end] & 0x80) != 0) {
return -1;
Control::set_double (double value, double frame, bool to_list)
{
_user_value = value;
-
+
/* if we're in a write pass, the automation watcher will determine the
values and add them to the list, so we we don't need to bother.
*/
Control::set_list(boost::shared_ptr<ControlList> list)
{
_list_marked_dirty_connection.disconnect ();
-
+
_list = list;
if (_list) {
_interpolation = other._interpolation;
_default_value = other._default_value;
-
+
copy_events (other);
}
{
Glib::Threads::RWLock::WriterLock lm (_lock);
-
+
ControlEvent* prevprev = 0;
ControlEvent* cur = 0;
ControlEvent* prev = 0;
iterator pprev;
int counter = 0;
-
+
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 thin from %2 events\n", this, _events.size()));
-
+
for (iterator i = _events.begin(); i != _events.end(); ++i) {
-
+
cur = *i;
counter++;
-
+
if (counter > 2) {
-
+
/* compute the area of the triangle formed by 3 points
*/
-
+
double area = fabs ((prevprev->when * (prev->value - cur->value)) +
(prev->when * (cur->value - prevprev->value)) +
(cur->when * (prevprev->value - prev->value)));
-
+
if (area < thinning_factor) {
iterator tmp = pprev;
-
+
/* pprev will change to current
i is incremented to the next event
as we loop.
*/
-
+
pprev = i;
_events.erase (tmp);
changed = true;
continue;
}
}
-
+
prevprev = prev;
prev = cur;
pprev = i;
}
-
+
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 thin => %2 events\n", this, _events.size()));
if (changed) {
new_write_pass = true;
did_write_during_pass = false;
insert_position = when;
-
+
/* leave the insert iterator invalid, so that we will do the lookup
of where it should be in a "lazy" way - deferring it until
we actually add the first point (which may never happen).
*/
-
+
unlocked_invalidate_insert_iterator ();
}
void
ControlList::set_in_write_pass (bool yn, bool add_point, double when)
-{
+{
DEBUG_TRACE (DEBUG::ControlList, string_compose ("now in write pass @ %1, add point ? %2\n", when, add_point));
-
+
_in_write_pass = yn;
if (yn && add_point) {
double eval_value = unlocked_eval (insert_position);
if (most_recent_insert_iterator == _events.end()) {
-
+
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert iterator at end, adding eval-value there %2\n", this, eval_value));
_events.push_back (new ControlEvent (when, eval_value));
/* leave insert iterator at the end */
-
+
} else if ((*most_recent_insert_iterator)->when == when) {
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert iterator at existing point, setting eval-value there %2\n", this, eval_value));
-
+
/* most_recent_insert_iterator points to a control event
already at the insert position, so there is
nothing to do.
-
+
... except ...
advance most_recent_insert_iterator so that the "real"
/* insert a new control event at the right spot
*/
-
+
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert eval-value %2 just before iterator @ %3\n",
this, eval_value, (*most_recent_insert_iterator)->when));
-
+
most_recent_insert_iterator = _events.insert (most_recent_insert_iterator, new ControlEvent (when, eval_value));
/* advance most_recent_insert_iterator so that the "real"
* insert occurs in the right place, since it
* points to the control event just inserted.
*/
-
+
++most_recent_insert_iterator;
}
-
+
/* don't do this again till the next write pass */
-
+
new_write_pass = false;
}
*/
if (_events.empty()) {
-
+
/* as long as the point we're adding is not at zero,
* add an "anchor" point there.
*/
iterator insertion_point;
if (_events.empty() && with_initial) {
-
+
/* empty: add an "anchor" point if the point we're adding past time 0 */
if (when >= 1) {
}
} else if (!_in_write_pass) {
-
+
/* not in a write pass: figure out the iterator we should insert in front of */
DEBUG_TRACE (DEBUG::ControlList, string_compose ("compute(b) MRI for position %1\n", when));
if (most_recent_insert_iterator == _events.end()) {
DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 appending new point at end\n", this));
-
+
const bool done = maybe_insert_straight_line (when, value);
if (!done) {
_events.push_back (new ControlEvent (when, value));
_events.back()->when = last_coordinate;
_events.back()->value = last_val;
}
-
+
unlocked_invalidate_insert_iterator ();
mark_dirty();
}
if (i != _events.end ()) {
return true;
}
-
+
return (
_parameter != other._parameter ||
_interpolation != other._interpolation ||
min_x = _list.events().front()->when;
if (x0 > max_x) {
- /* totally past the end - just fill the entire array with the final value */
+ /* totally past the end - just fill the entire array with the final value */
for (int32_t i = 0; i < veclen; ++i) {
vec[i] = _list.events().back()->value;
}
{
_original_time = t;
}
-
+
#endif // EVORAL_EVENT_ALLOC
template class Event<Evoral::Beats>;
_off_event.buffer = _off_event_buffer;
memcpy(_off_event_buffer, copy._off_event_buffer, 3);
*/
-
+
assert(time() == copy.time());
assert(end_time() == copy.end_time());
assert(length() == copy.length());
*/
typename Sequence<Time>::Notes::iterator i;
-
+
for (i = note_lower_bound(note->time()); i != _notes.end() && (*i)->time() == note->time(); ++i) {
if (*i == note) {
* in this scenario, we have no choice other than to linear
* search the list of notes and find the note by ID.
*/
-
+
for (i = _notes.begin(); i != _notes.end(); ++i) {
if ((*i)->id() == note->id()) {
-
+
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\tID-based pass, erasing note #%2 %3 @ %4\n", this, (*i)->id(), (int)(*i)->note(), (*i)->time()));
_notes.erase (i);
-
+
if (note->note() == _lowest_note || note->note() == _highest_note) {
-
+
_lowest_note = 127;
_highest_note = 0;
-
+
for (typename Sequence<Time>::Notes::iterator ii = _notes.begin(); ii != _notes.end(); ++ii) {
if ((*ii)->note() < _lowest_note)
_lowest_note = (*ii)->note();
_highest_note = (*ii)->note();
}
}
-
+
erased = true;
id_matched = true;
break;
}
}
}
-
+
if (erased) {
Pitches& p (pitches (note->channel()));
-
+
typename Pitches::iterator j;
/* if we had to ID-match above, we can't expect to find it in
* notes by channel+time. We care only about its note number
* so the search_note has all other properties unset.
*/
-
+
NotePtr search_note (new Note<Time>(0, Time(), Time(), note->note(), 0));
for (j = p.lower_bound (search_note); j != p.end() && (*j)->note() == note->note(); ++j) {
-
+
if ((*j) == note) {
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\terasing pitch %2 @ %3\n", this, (int)(*j)->note(), (*j)->time()));
p.erase (j);
}
_edited = true;
-
+
} else {
cerr << "Unable to find note to erase matching " << *note.get() << endmsg;
}
#else
smf_set_format(smf, 1);
#endif
-
+
}
}
{
assert(event->midi_buffer);
assert(event->midi_buffer_length > 0);
-
+
if (event->midi_buffer[0] == 0xFF)
return (1);
if (smf_event_is_metadata(event))
return (0);
-
+
if (event->midi_buffer[0] >= 0xF8)
return (1);
{
assert(event->midi_buffer);
assert(event->midi_buffer_length > 0);
-
+
if (event->midi_buffer[0] == 0xF0)
return (1);
if (!chunk_signature_matches(tmp_mthd, "MThd")) {
g_critical("SMF error: MThd signature not found, is that a MIDI file?");
-
+
return (-2);
}
g_critical("SMF file uses FPS timing instead of PPQN, no support for that yet.");
return (-4);
}
-
+
return (0);
}
case 0xA0: /* AfterTouch. */
case 0xB0: /* Control Change. */
case 0xE0: /* Pitch Wheel. */
- return (3);
+ return (3);
case 0xC0: /* Program Change. */
case 0xD0: /* Channel Pressure. */
extract_sysex_event(const unsigned char *buf, const size_t buffer_length, smf_event_t *event, uint32_t *len, int last_status)
{
(void) last_status;
-
+
int status;
int32_t vlq_length, message_length;
const unsigned char *c = buf;
extract_escaped_event(const unsigned char *buf, const size_t buffer_length, smf_event_t *event, uint32_t *len, int last_status)
{
(void) last_status;
-
+
int status;
int32_t message_length = 0;
int32_t vlq_length = 0;
if (!chunk_signature_matches(mtrk, "MTrk")) {
g_warning("SMF warning: Expected MTrk signature, got %c%c%c%c instead; ignoring this chunk.",
mtrk->id[0], mtrk->id[1], mtrk->id[2], mtrk->id[3]);
-
+
return (-2);
}
{
assert(event);
assert(event->midi_buffer);
-
+
int32_t expected;
if (event->midi_buffer_length < 1)
*file_buffer = malloc(*file_buffer_length);
if (*file_buffer == NULL) {
g_critical("malloc(3) failed: %s", strerror(errno));
-
+
return (-5);
}
*file_buffer = NULL;
return (-6);
}
-
+
return (0);
}
return (-6);
}
}
-
+
}
return (0);
for (;;) {
event = smf_get_next_event(smf);
-
+
if (event == NULL)
return;
return (smf_get_tempo_by_number(smf, 0));
assert(smf->tempo_array != NULL);
-
+
for (i = smf->tempo_array->len; i > 0; i--) {
tempo = smf_get_tempo_by_number(smf, i - 1);
return (smf_get_tempo_by_number(smf, 0));
assert(smf->tempo_array != NULL);
-
+
for (i = smf->tempo_array->len; i > 0; i--) {
tempo = smf_get_tempo_by_number(smf, i - 1);
g_message("Pulses Per Quarter Note changed to %d.", smf->ppqn);
}
-
+
return (0);
}
g_message("Forma changed to %d.", smf->format);
}
-
+
return (0);
}
type = "Metadata";
else
type = "Event";
-
+
decoded = smf_event_decode(event);
if (decoded == NULL) {
f"2(x2) = 2*(2*f'2(x2) + f'2(x1))/(x2 – x1) - 6*(y2 – y1)/ (x2 – x1)^2
= 2*(2*0 + 1.8181)/(30 – 10) – 6*(150 – 130)/(30 – 10)^2
= -0.11818
-
+
d2 = 1/6 * (f"2(x2) - f"2(x1))/(x2 – x1)
= 1/6 * (-0.11818 + 0.063636)/(30 – 10)
= -0.0004545
void coverageTest ();
};
-
+
for (acts = gtk_action_group_list_actions (group); acts; acts = g_list_next (acts)) {
ui_string += "<accelerator action=\"";
-
+
/* OK, this is pretty stupid ... there is the full
* accel path returned by gtk_action_get_accel_path ()
* but of course the UIManager doesn't use that, but
}
// save all action's states to action_states_to_restore
save_action_states ();
-
+
// set all action's states disabled
for (ActionStates::iterator i = action_states_to_restore.begin(); i != action_states_to_restore.end(); ++i) {
if ((*i).sensitive) {
*slash = '\0';
return get_action (©[0], ++slash);
-
+
}
RefPtr<Action>
ActionManager::set_toggleaction_state (string n, bool s)
{
char const * name = n.c_str ();
-
+
const char *last_slash = strrchr (name, '/');
if (last_slash == 0) {
ActionManager::get_key_representation (const string& accel_path, AccelKey& key)
{
bool known = lookup_entry (accel_path, key);
-
+
if (known) {
uint32_t k = possibly_translate_legal_accelerator_to_real_key (key.get_key());
key = AccelKey (k, Gdk::ModifierType (key.get_mod()));
return ui_manager->get_accel_group()->get_label (key.get_key(), Gdk::ModifierType (key.get_mod()));
}
-
+
return unbound_string;
}
BindingProxy::BindingProxy (boost::shared_ptr<Controllable> c)
: prompter (0),
controllable (c)
-{
+{
}
BindingProxy::BindingProxy ()
: prompter (0)
-{
+{
}
BindingProxy::~BindingProxy ()
}
return true;
}
-
+
return false;
}
int x, y;
Gtk::Widget* window_parent;
Glib::RefPtr<Gdk::Window> win = Gtkmm2ext::window_to_draw_on (w, &window_parent);
-
+
if (win) {
-
+
Cairo::RefPtr<Cairo::Context> context = win->create_cairo_context();
w.translate_coordinates (*window_parent, 0, 0, x, y);
float r = col.get_red_p ();
float g = col.get_green_p ();
float b = col.get_blue_p ();
-
+
cairo_set_source_rgba(cr, r, g, b, a);
}
cairo_context->paint ();
}
#endif
-
+
Gtk::Widget* child = get_child ();
-
+
if (child) {
propagate_expose (*child, ev);
}
/* paint expose area the color of the parent window bg
*/
-
+
Gdk::Color bg (get_parent_bg());
-
+
cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p());
cr->fill ();
#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
}
#endif
-
+
return true;
}
for (n = 0; n < lim; ++n) {
buf[n] = '0' + digit;
}
-
+
context->get_text_extents (&buf[0], ext);
-
+
max_width = max (ext.width + ext.x_bearing, max_width);
max_height = max (ext.height, max_height);
bsum += ext.x_bearing;
Cairo::TextExtents ext;
_font->apply (context);
-
+
{
const char* buf = "8";
context->get_text_extents (buf, ext);
CairoEditableText::add_cell (CairoCell* cell)
{
cells.push_back (cell);
-
+
CairoTextCell* tc = dynamic_cast<CairoTextCell*>(cell);
if (tc) {
Gtk::Allocation alloc = get_allocation ();
double width = alloc.get_width();
double height = alloc.get_height ();
-
+
if (_draw_bg) {
context->set_source_rgba (bg_r, bg_g, bg_b, bg_a);
if (_corner_radius) {
}
context->fill ();
}
-
+
for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i) {
CairoCell* cell = (*i);
/* is cell inside the expose area?
*/
-
+
if (cell->intersects (ev->area)) {
if (cell == editing_cell) {
context->set_source_rgba (edit_r, edit_b, edit_g, edit_a);
if (!win) {
return;
}
-
+
Cairo::RefPtr<Cairo::Context> context = win->create_cairo_context();
-
+
if (!context) {
return;
}
max_cell_width = 0;
max_cell_height = 0;
-
+
for (CellMap::iterator i = cells.begin(); i != cells.end(); ++i) {
max_cell_width += (*i)->width();
max_cell_height = std::max ((double) (*i)->height(), max_cell_height);
c.set_red (0);
c.set_green (0);
c.set_blue (0);
-
+
property_color() = c;
}
cairo_t* cr = gdk_cairo_create (window->gobj());
double r, g, b;
Gdk::Color c = _property_color.get_value();
-
+
cairo_rectangle (cr, expose_area.get_x(), expose_area.get_y(), expose_area.get_width(), expose_area.get_height());
cairo_clip (cr);
-
+
r = c.get_red_p();
g = c.get_green_p();
b = c.get_blue_p();
-
+
cairo_rectangle_t drawing_rect;
-
+
drawing_rect.x = cell_area.get_x() + property_xpad();
drawing_rect.y = cell_area.get_y() + property_ypad();
drawing_rect.width = cell_area.get_width() - (2 * property_xpad());
drawing_rect.height = cell_area.get_height() - (2 * property_ypad());
-
+
Gtkmm2ext::rounded_rectangle (cr, drawing_rect.x, drawing_rect.y, drawing_rect.width, drawing_rect.height, 5);
cairo_set_source_rgb (cr, r, g, b);
cairo_fill (cr);
offset_width = cell_area.get_x() + (int)(cell_area.get_width() - pb->get_width())/2;
offset_height = cell_area.get_y() + (int)(cell_area.get_height() - pb->get_height())/2;
-
+
window->draw_pixbuf (RefPtr<GC>(), pb, 0, 0, offset_width, offset_height, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0);
}
{
int offset_width = 0;
int offset_height = 0;
-
+
if(property_active() == true){
offset_width = cell_area.get_x() + (int)(cell_area.get_width() - inactive_pixbuf->get_width())/2;
{
int n;
vector<string>::iterator i;
-
+
if (center) {
set_position (Gtk::WIN_POS_CENTER);
} else {
get_vbox()->set_border_width (12);
get_vbox()->pack_start (*dhbox, true, false);
-
+
set_has_separator (false);
set_resizable (false);
show_all_children ();
Glib::RefPtr<Gdk::GC> fg_gc (style->get_fg_gc (Gtk::STATE_NORMAL));
Glib::RefPtr<Gdk::GC> bg_gc (style->get_bg_gc (Gtk::STATE_NORMAL));
Glib::RefPtr<Gdk::Window> win (get_window());
-
+
GdkRectangle base_rect;
GdkRectangle draw_rect;
gint x, y, width, height, depth;
-
+
win->get_geometry (x, y, width, height, depth);
-
+
base_rect.width = width;
base_rect.height = height;
base_rect.x = 0;
base_rect.y = 0;
-
+
gdk_rectangle_intersect (&ev->area, &base_rect, &draw_rect);
win->draw_rectangle (bg_gc, true, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height);
-
+
if (twidth && theight) {
win->draw_layout (fg_gc, (width - twidth) / 2, (height - theight) / 2, layout);
}
for (list<TargetEntry>::iterator i = targets.begin(); i != targets.end(); ++i) {
draggable.push_back (*i);
}
-
+
enable_model_drag_source (draggable);
enable_model_drag_dest (draggable);
-}
+}
void
DnDTreeViewBase::add_object_drag (int column, string type_name)
int pbheight = _face_pixbuf->get_height ();
int width = get_width ();
int height = get_height ();
-
+
if ((width != pbwidth) || (height != pbheight)) {
x_scale = double (width) / double (pbwidth);
if (x_scale == 0.0) {
void
Fader::render (cairo_t* cr, cairo_rectangle_t*)
{
-
+
double xscale = 1.0;
double yscale = 1.0;
-
+
get_image_scales (xscale, yscale);
-
+
cairo_matrix_t matrix;
cairo_get_matrix (cr, &matrix);
cairo_matrix_scale (&matrix, xscale, yscale);
cairo_set_matrix (cr, &matrix);
-
+
get_handle_position (_last_drawn_x, _last_drawn_y);
if (_underlay_pixbuf != 0) {
double xscale = 1.0;
double yscale = 1.0;
-
+
get_image_scales (xscale, yscale);
-
+
double hw = _handle_pixbuf->get_width() * xscale;
double hh = _handle_pixbuf->get_height() * yscale;
double ev_pos_x;
double ev_pos_y;
-
+
get_closest_point_on_line(_min_pos_x, _min_pos_y,
_max_pos_x, _max_pos_y,
ev->x, ev->y,
ev_pos_x, ev_pos_y );
add_modal_grab ();
-
+
_grab_window = ev->window;
_dragging = true;
-
+
gdk_pointer_grab(ev->window,false,
GdkEventMask (Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK),
NULL,
ev->time);
queue_draw();
-
+
return true;
}
if (_dragging) {
double ev_pos_x;
double ev_pos_y;
-
+
if (ev->window != _grab_window) {
_grab_window = ev->window;
return true;
_max_pos_x, _max_pos_y,
_grab_start_handle_x + (ev->x - _grab_start_mouse_x), _grab_start_handle_y + (ev->y - _grab_start_mouse_y),
ev_pos_x, ev_pos_y );
-
+
double const fract = sqrt((ev_pos_x - _min_pos_x) * (ev_pos_x - _min_pos_x) +
(ev_pos_y - _min_pos_y) * (ev_pos_y - _min_pos_y)) /
sqrt((double)((_max_pos_x - _min_pos_x) * (_max_pos_x - _min_pos_x) +
(_max_pos_y - _min_pos_y) * (_max_pos_y - _min_pos_y)));
-
+
adjustment.set_value (adjustment.get_lower() + (adjustment.get_upper() - adjustment.get_lower()) * fract);
}
return true;
for (uint32_t n = 0; n < nbuttons; ++n) {
Gtk::ToggleButton *button;
-
+
button = manage (new (Gtk::ToggleButton));
-
+
if (n == current_active) {
button->set_active (true);
}
: AbstractUI<UIRequest> (namestr)
, _receiver (*this)
, errors (0)
-
+
{
theMain = new Main (argc, argv);
pthread_set_name ("gui");
-
+
_active = false;
if (!theGtkUI) {
*/
run_loop_thread = Threads::Thread::self();
-
+
/* store "this" as the UI-for-thread of this thread, same argument
as for previous line.
*/
* This does not occur if wiget.get_style is used instead of rc.get_style below,
* except that doesn't actually work...
*/
-
+
static Glib::RefPtr<Style>* fatal_style = 0;
static Glib::RefPtr<Style>* error_style = 0;
static Glib::RefPtr<Style>* warning_style = 0;
}
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
-
+
if (tact->get_active()) {
errors->set_position (WIN_POS_MOUSE);
errors->show ();
LIBGTKMM2EXT_API extern std::string unbound_string; /* the key string returned if an action is not bound */
LIBGTKMM2EXT_API extern Glib::RefPtr<Gtk::UIManager> ui_manager;
-
+
LIBGTKMM2EXT_API extern void set_sensitive (std::vector<Glib::RefPtr<Gtk::Action> >& actions, bool);
LIBGTKMM2EXT_API extern std::string get_key_representation (const std::string& accel_path, Gtk::AccelKey& key);
};
} /* namespace */
-
+
#endif /* __gtkmm2ext_auto_spin_h__ */
}; /* namespace */
-#endif // __gtkmm2ext_bar_controller_h__
+#endif // __gtkmm2ext_bar_controller_h__
BindableToggleButton () {}
virtual ~BindableToggleButton() {}
-
+
bool on_button_press_event (GdkEventButton *ev) {
if (!binding_proxy.button_press_handler (ev)) {
StatefulToggleButton::on_button_press_event (ev);
return true;
}
}
-
+
boost::shared_ptr<PBD::Controllable> get_controllable() { return binding_proxy.get_controllable(); }
void set_controllable (boost::shared_ptr<PBD::Controllable> c);
void watch ();
public:
BindableButton (boost::shared_ptr<PBD::Controllable> c) : binding_proxy (c) {}
~BindableButton() {}
-
+
bool on_button_press_event (GdkEventButton *ev) {
if (!binding_proxy.button_press_handler (ev)) {
StatefulButton::on_button_press_event (ev);
BindingProxy (boost::shared_ptr<PBD::Controllable>);
BindingProxy ();
virtual ~BindingProxy();
-
+
void set_bind_button_state (guint button, guint statemask);
static bool is_bind_action (GdkEventButton *);
protected:
Gtkmm2ext::PopUp* prompter;
boost::shared_ptr<PBD::Controllable> controllable;
-
+
static guint bind_button;
static guint bind_statemask;
-
+
PBD::ScopedConnection learning_connection;
void learning_finished ();
bool prompter_hiding (GdkEventAny *);
Gtkmm2ext::ActiveState active_state() const { return _active_state; }
Gtkmm2ext::VisualState visual_state() const { return _visual_state; }
-
+
/* derived widgets can override these two to catch
changes in active & visual state
*/
-
+
virtual void set_active_state (Gtkmm2ext::ActiveState);
virtual void set_visual_state (Gtkmm2ext::VisualState);
/* set_focus_handler() will cause all button-press events on any
CairoWidget to invoke this slot/functor/function/method/callback.
-
+
We do this because in general, CairoWidgets do not grab
keyboard focus, but a button press on them should
clear focus from any active text entry.
void on_style_changed (const Glib::RefPtr<Gtk::Style>&);
bool on_button_press_event (GdkEventButton*);
Gdk::Color get_parent_bg ();
-
+
/* this is an additional virtual "on_..." method. Glibmm does not
provide a direct signal for name changes, so this acts as a proxy.
*/
Glib::SignalProxyProperty _name_proxy;
sigc::connection _parent_style_change;
Widget * _current_parent;
-
+
};
#endif
public:
CairoCell(int32_t id);
virtual ~CairoCell() {}
-
+
int32_t id() const { return _id; }
virtual void render (Cairo::RefPtr<Cairo::Context>&) = 0;
void set_width_chars (CairoTextCell* cell, uint32_t);
void set_draw_background (bool yn) { _draw_bg = yn; }
-
+
void set_colors (double cr, double cg, double cb, double ca) {
r = cr;
g = cg;
void set_xpad (double x) { _xpad = x; queue_resize(); }
double ypad() const { return _ypad; }
void set_ypad (double y) { _ypad = y; queue_resize(); }
-
+
double corner_radius() const { return _corner_radius; }
void set_corner_radius (double r) { _corner_radius = r; queue_draw (); }
Glib::PropertyProxy<uint32_t> property_state();
void set_pixbuf(uint32_t state, Glib::RefPtr<Gdk::Pixbuf> pixbuf);
-
+
typedef sigc::signal<void, const Glib::ustring&> SignalChanged;
SignalChanged& signal_changed();
private:
Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_;
Glib::Property<bool> property_active_;
-
+
Glib::RefPtr<Gdk::Pixbuf> active_pixbuf;
Glib::RefPtr<Gdk::Pixbuf> inactive_pixbuf;
Gtk::TreeView::on_drag_begin (context);
start_object_drag ();
}
-
+
void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& context, guint time) {
suggested_action = context->get_suggested_action();
TreeView::on_drag_leave (context, time);
struct DragData {
DragData () : source (0) {}
-
+
Gtk::TreeView* source;
int data_column;
std::string object_type;
};
-
+
static DragData drag_data;
void start_object_drag () {
selection_data.set (8, (guchar*)&c, 1);
}
}
-
+
void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time) {
if (suggested_action) {
/* this is a drag motion callback. just update the status to
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
return;
}
-
+
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
-
+
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
-
+
} else if (selection_data.get_target() == object_type) {
-
+
end_object_drag (const_cast<Glib::RefPtr<Gdk::DragContext>& > (context), x, y);
} else {
if (drag_data.source == 0) {
return;
}
-
+
Glib::RefPtr<Gtk::TreeModel> model = drag_data.source->get_model();
DataType v;
Gtk::TreeSelection::ListHandle_Path selection = drag_data.source->get_selection()->get_selected_rows ();
-
+
for (Gtk::TreeSelection::ListHandle_Path::iterator x = selection.begin(); x != selection.end(); ++x) {
model->get_iter (*x)->get_value (drag_data.data_column, v);
l.push_back (v);
}
-
+
*source = drag_data.source;
}
namespace Gtkmm2ext {
-/** Parent class for children of a DnDVBox */
+/** Parent class for children of a DnDVBox */
class /*LIBGTKMM2EXT_API*/ DnDVBoxChild
{
public:
virtual ~DnDVBoxChild () {}
-
+
/** @return The widget that is to be put into the DnDVBox */
virtual Gtk::Widget& widget () = 0;
-
+
/** @return An EventBox containing the widget that should be used for selection, dragging etc. */
virtual Gtk::EventBox& action_widget () = 0;
signal_drag_leave().connect (mem_fun (*this, &DnDVBox::drag_leave));
_internal_vbox.show ();
-
+
drag_dest_set (_targets);
signal_drag_data_received().connect (mem_fun (*this, &DnDVBox::drag_data_received));
}
-
+
virtual ~DnDVBox ()
{
clear ();
-
+
delete _drag_icon;
}
child->action_widget().signal_drag_end().connect (sigc::bind (mem_fun (*this, &DnDVBox::drag_end), child));
child->action_widget().signal_button_press_event().connect (sigc::bind (mem_fun (*this, &DnDVBox::button_press), child));
child->action_widget().signal_button_release_event().connect (sigc::bind (mem_fun (*this, &DnDVBox::button_release), child));
-
+
_internal_vbox.pack_start (child->widget(), false, false);
-
+
_children.push_back (child);
child->widget().show ();
}
T* after;
std::pair<T*, double> r;
-
+
r.second = get_children_around_position (y, &before, &r.first, &after);
return r;
{
return create_or_update_placeholder (get_child_at_position (y).second);
}
-
+
/** Children have been reordered by a drag */
sigc::signal<void> Reordered;
return bottom;
}
-
+
/** Look at a y coordinate and find the children below y, and the ones either side.
* @param y y position.
* @param before Filled in with the child before, or 0.
while (y >= bottom && j != _children.end()) {
top = bottom;
-
+
*before = *j;
++i;
++j;
void drag_begin (Glib::RefPtr<Gdk::DragContext> const & context, T* child)
{
_drag_child = child;
-
+
/* make up an icon for the drag */
_drag_icon = new Gtk::Window (Gtk::WINDOW_POPUP);
-
+
Gtk::Allocation a = child->action_widget().get_allocation ();
_drag_icon->set_size_request (a.get_width(), a.get_height());
-
+
_drag_icon->signal_expose_event().connect (sigc::mem_fun (*this, &DnDVBox::icon_expose));
_drag_icon->set_name (get_name ());
int w, h;
_drag_icon->get_size (w, h);
_drag_icon->drag_set_as_icon (context, w / 2, h / 2);
-
+
_drag_source = this;
}
cairo_rectangle (cr, 0, 0, w, h);
cairo_fill (cr);
cairo_destroy (cr);
-
+
return false;
}
-
+
void drag_data_get (Glib::RefPtr<Gdk::DragContext> const &, Gtk::SelectionData & selection_data, guint, guint, T* child)
{
selection_data.set (selection_data.get_target(), 8, (const guchar *) &child, sizeof (&child));
}
-
+
void drag_data_received (
Glib::RefPtr<Gdk::DragContext> const & context, int /*x*/, int y, Gtk::SelectionData const & selection_data, guint /*info*/, guint time
)
{
/* work out where it was dropped */
std::pair<T*, double> const drop = get_child_at_position (y);
-
+
if (_drag_source == this) {
/* dropped from ourselves onto ourselves */
/* where in the list this child should be dropped */
int target = drop.second + 0.5;
-
+
/* find out whether the child was `picked up' from before the drop position */
int n = 0;
typename std::list<T*>::const_iterator i = _children.begin ();
++i;
++n;
}
-
+
/* if so, adjust the drop position to account for this */
if (n < target) {
--target;
}
-
+
_internal_vbox.reorder_child (child->widget(), target);
}
-
+
} else {
-
+
/* drag started in another DnDVBox; raise a signal to say what happened */
-
+
std::list<T*> dropped = _drag_source->selection ();
DropFromAnotherBox (_drag_source, drop.first, context);
}
-
+
context->drag_finish (false, false, time);
}
-
+
void drag_end (Glib::RefPtr<Gdk::DragContext> const &, T *)
{
delete _drag_icon;
_drag_icon = 0;
-
+
_drag_child = 0;
remove_placeholder ();
if (child) {
_expecting_unwanted_button_event = true;
}
-
+
if (ev->button == 1 || ev->button == 3) {
if (!selected (child)) {
if (selecting && !was_selected) {
add_to_selection (*i);
}
-
+
if (!selecting && !done) {
if (selected (*i)) {
selecting = true;
}
} else {
-
+
if ((ev->state & Gdk::CONTROL_MASK) == 0) {
clear_selection ();
}
-
+
if (child) {
add_to_selection (child);
}
}
-
+
SelectionChanged (); /* EMIT SIGNAL */
-
+
} else {
/* XXX THIS NEEDS GENERALIZING FOR OS X */
if (ev->button == 1 && (ev->state & Gdk::CONTROL_MASK)) {
return ButtonPress (ev, child); /* EMIT SIGNAL */
}
-
+
bool button_release (GdkEventButton* ev, T* child)
{
if (_expecting_unwanted_button_event == true && child == 0) {
setup_child_state (*i);
}
}
-
+
void add_to_selection (T* child)
{
if ( !child->is_selectable() )
setup_child_state (c);
}
}
-
+
T* child_from_widget (Gtk::Widget const * w) const
{
typename std::list<T*>::const_iterator i = _children.begin();
while (i != _children.end() && &(*i)->widget() != w) {
++i;
}
-
+
if (i == _children.end()) {
return 0;
}
return *i;
}
-
+
Gtk::VBox _internal_vbox;
std::list<Gtk::TargetEntry> _targets;
std::list<T*> _children;
Gtk::Label* _placeholder;
/** Our child being dragged, or 0 */
T* _drag_child;
-
+
static DnDVBox* _drag_source;
-
+
};
template <class T>
DnDVBox<T>* DnDVBox<T>::_drag_source = 0;
-
+
}
{
public:
FocusEntry ();
-
+
protected:
bool on_button_press_event (GdkEventButton*);
bool on_button_release_event (GdkEventButton*);
public:
GroupedButtons (uint32_t nbuttons, uint32_t first_active);
GroupedButtons (std::vector<Gtk::ToggleButton *>&);
-
+
Gtk::ToggleButton& button (uint32_t which) {
return *buttons[which];
}
sigc::signal<void> theme_changed;
static bool just_hide_it (GdkEventAny *, Gtk::Window *);
-
+
protected:
virtual void handle_fatal (const char *);
virtual void display_message (const char *prefix, gint prefix_len,
static void set_insert_note_button (guint);
static guint insert_note_modifier() { return insert_note_mod; }
static void set_insert_note_modifier(guint);
-
+
static bool is_edit_event (GdkEventButton*);
static bool is_delete_event (GdkEventButton*);
static bool is_insert_note_event (GdkEventButton*);
to a display value (0.0 .. 1.0)
*/
virtual double to_display_value (double) = 0;
-
+
virtual double adjust (double nominal_delta) = 0;
private:
};
} /* namespace */
-
+
#endif // __gtkmm2ext_motion_feedback_h__
public:
PersistentTooltip (Gtk::Widget *, bool draggable = false, int margin_y = 0);
virtual ~PersistentTooltip ();
-
+
void set_tip (std::string);
void set_font (Pango::FontDescription font);
void set_center_alignment (bool align_to_center);
double grab_start;
int overall_height;
bool dragging;
-
+
float default_value;
void adjustment_changed ();
void set_min_page_size(double page_size);
int get_handle_size() { return handle_size; }
-
+
inline int position_of(Component comp) { return position[comp]; }
sigc::signal0<void> DragStarting;
}; /* namespace */
-#endif // __gtkmm2ext_slider_controller_h__
+#endif // __gtkmm2ext_slider_controller_h__
void insert_file (const std::string &);
void scroll_to_bottom ();
-
+
void deliver ();
};
LIBGTKMM2EXT_API void get_ink_pixel_size (Glib::RefPtr<Pango::Layout>,
int& width, int& height);
-
+
LIBGTKMM2EXT_API void get_pixel_size (Glib::RefPtr<Pango::Layout>,
int& width, int& height);
-
+
LIBGTKMM2EXT_API void set_size_request_to_display_given_text (Gtk::Widget &w,
const gchar *text,
gint hpadding,
gint vpadding);
-
+
LIBGTKMM2EXT_API void set_size_request_to_display_given_text_width (Gtk::Widget& w,
const gchar* htext,
gint hpadding,
LIBGTKMM2EXT_API bool set_active_text_if_present (Gtk::ComboBoxText&,
const std::string);
-
+
template<class T> /*LIBGTKMM2EXT_API*/ void deferred_delete (void *ptr) {
delete static_cast<T *> (ptr);
}
LIBGTKMM2EXT_API void container_clear (Gtk::Container&);
/* C++ API for rounded rectangles */
-
+
LIBGTKMM2EXT_API void rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
LIBGTKMM2EXT_API void rounded_top_left_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r=10);
ExplicitActive,
ImplicitActive,
};
-
+
enum LIBGTKMM2EXT_API VisualState {
/* these can be OR-ed together */
NoVisualState = 0x0,
IdleAdjustment::underlying_adjustment_value_changed ()
{
last_vc = g_get_monotonic_time();
-
+
if (timeout_queued) {
return;
}
Glib::signal_timeout().connect(mem_fun(*this, &IdleAdjustment::timeout_handler), 250);
timeout_queued = true;
-}
+}
gint
IdleAdjustment::timeout_handler ()
string new_path = user_keybindings_path;
new_path += ".old";
-
+
if (::g_rename (user_keybindings_path.c_str(), new_path.c_str())) {
error << string_compose (_("Cannot rename your own keybinding file (%1)"), strerror (errno)) << endmsg;
return -1;
value = new Label;
value->set_justify (Gtk::JUSTIFY_RIGHT);
value->show ();
-
+
value_packer->add (*value);
hpacker = manage (new HBox);
_controllable->set_value (_controllable->lower ());
}
break;
-
+
case 3:
if (pixwin.has_grab()) {
if (grab_is_fine) {
_controllable->set_value (_controllable->upper());
break;
}
-
+
return retval;
}
GdkWindow *window = pixwin.get_window()->gobj();
double display_val = to_display_value (_controllable->get_value());
int32_t phase = lrint (display_val * 64.0);
-
+
// skip middle phase except for true middle value
if (type == Rotary && phase == 32) {
GdkColor dark;
GdkColor bright;
ProlooksHSV* hsv;
-
+
hsv = prolooks_hsv_new_for_gdk_color (base_color->gobj());
bright = (prolooks_hsv_to_gdk_color (hsv, &col2), col2);
prolooks_hsv_set_saturation (hsv, 0.66);
prolooks_hsv_set_value (hsv, 0.67);
dark = (prolooks_hsv_to_gdk_color (hsv, &col3), col3);
-
+
cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size * 64, size);
cairo_t* cr = cairo_create (surface);
-
+
for (int i = 0; i < 64; ++i) {
cairo_save (cr);
core_draw (cr, i, size, 20, size*i, 0, &bright, &dark);
cairo_restore (cr);
}
-
+
if (cairo_surface_write_to_png (surface, path) != CAIRO_STATUS_SUCCESS) {
error << string_compose (_("motionfeedback: could not save image set to %1"), path) << endmsg;
return pixbuf;
}
-
+
cairo_destroy (cr);
cairo_surface_destroy (surface);
-
+
try {
pixbuf = Gdk::Pixbuf::create_from_file (path);
} catch (const Gdk::PixbufError &e) {
g_unlink (path);
g_free (path);
-
+
return pixbuf;
}
cairo_arc (cr, xc, yc, progress_radius, start_angle, end_angle);
cairo_stroke (cr);
-
+
float r = (value) * (((float)bright->red)/G_MAXUINT16) + (1.0-value)*(((float)dark->red)/G_MAXUINT16);
float g = (value) * (((float)bright->green)/G_MAXUINT16) + (1.0-value)*(((float)dark->green)/G_MAXUINT16);
float b = (value) * (((float)bright->blue)/G_MAXUINT16) + (1.0-value)*(((float)dark->blue)/G_MAXUINT16);
cairo_arc (cr, xc, yc, progress_radius_outer-1, 0, 2.0*G_PI);
cairo_fill (cr);
cairo_pattern_destroy (shade_pattern);
-
+
//black border
cairo_set_source_rgb (cr, 0, 0, 0 );
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 1 );
cairo_arc (cr, xc, yc, progress_radius_inner-1, 0, 2.0*G_PI);
cairo_fill (cr);
-
+
//knob shade
shade_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, progress_radius_outer);
cairo_pattern_add_color_stop_rgba (shade_pattern, 0, 1,1,1, 0.5);
cairo_arc (cr, xc, yc, progress_radius_inner-1, 0, 2.0*G_PI);
cairo_fill (cr);
cairo_pattern_destroy (shade_pattern);
-
+
//inner circle
cairo_set_source_rgba (cr, 0.3, 0.3, 0.3, 0.5 );
cairo_arc (cr, xc, yc, progress_radius_inner-5, 0, 2.0*G_PI);
_window->set_transient_for (*tlw);
}
}
-
+
set_tip (_tip);
if (!_window->is_visible ()) {
int sw = gdk_screen_width ();
_target->get_window()->get_origin (rx, ry);
-
+
/* the window needs to be realized first
* for _window->get_width() to be correct.
*/
context->paint();
context->restore();
}
-
+
if (gdk_rectangle_intersect (sliderrect.gobj(), &ev->area, &intersect)) {
context->save();
default:
break;
}
-
+
return false;
}
PixScroller::on_button_release_event (GdkEventButton* ev)
{
double scale;
-
+
if (ev->state & Keyboard::PrimaryModifier) {
if (ev->state & Keyboard::SecondaryModifier) {
scale = 0.05;
PixScroller::on_scroll_event (GdkEventScroll* ev)
{
double scale;
-
+
if (ev->state & Keyboard::PrimaryModifier) {
if (ev->state & Keyboard::SecondaryModifier) {
scale = 0.05;
grab_window = ev->window;
return true;
}
-
+
if (ev->state & Keyboard::PrimaryModifier) {
if (ev->state & Keyboard::SecondaryModifier) {
scale = 0.05;
fract = min (1.0, fract);
fract = max (-1.0, fract);
-
+
fract = -fract;
adj.set_value (adj.get_value() + scale * fract * (adj.get_upper() - adj.get_lower()));
set_size_request_to_display_given_text (label, my_text.c_str(), 25, 10);
label.set_text (my_text);
show_all ();
-
+
if (popdown_time != 0) {
timeout = g_timeout_add (popdown_time,
remove_prompt_timeout,
if (popdown_time != 0 && timeout != -1) {
g_source_remove (timeout);
- }
+ }
if (delete_on_hide) {
std::cerr << "deleting prompter\n" << endl;
set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
set_position (Gtk::WIN_POS_MOUSE);
set_name ("Prompter");
-
+
add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
/*
set_response_sensitive (Gtk::RESPONSE_ACCEPT, false)
to prevent the RESPONSE_ACCEPT button from permitting blank strings.
*/
-
+
entryLabel.set_line_wrap (true);
entryLabel.set_name ("PrompterLabel");
get_vbox()->pack_start (entryBox);
show_all_children();
-}
+}
void
Prompter::on_show ()
} else {
response (Gtk::RESPONSE_CANCEL);
}
-}
+}
void
Prompter::on_entry_changed ()
unzoomed_page += scale * fract * range;
unzoomed_page = min(unzoomed_page, adj.get_upper() - unzoomed_val);
unzoomed_page = max(unzoomed_page, min_page_size);
-
+
if (pinch){
temp = unzoomed_val + unzoomed_page;
unzoomed_val -= scale * fract * range * 0.5;
unzoomed_val = min(unzoomed_val, temp - min_page_size);
unzoomed_val = max(unzoomed_val, adj.get_lower());
}
-
+
break;
case Handle2:
temp = unzoomed_val + unzoomed_page;
unzoomed_val += scale * fract * range;
unzoomed_val = min(unzoomed_val, temp - min_page_size);
unzoomed_val = max(unzoomed_val, adj.get_lower());
-
+
unzoomed_page = temp - unzoomed_val;
-
+
if (pinch){
-
+
unzoomed_page -= scale * fract * range;
}
-
- unzoomed_page = min(unzoomed_page, adj.get_upper() - unzoomed_val);
+
+ unzoomed_page = min(unzoomed_page, adj.get_upper() - unzoomed_val);
unzoomed_page = max(unzoomed_page, min_page_size);
break;
default:
* We don't start doing zoom until we are at least one scroomer width outside the scroomer's
* area.
*/
-
+
if (ev->x > (get_width() * 2)) {
zoom = ev->x - get_width();
-
+
double higher = unzoomed_val + unzoomed_page - half_min_page - val_at_pointer;
double lower = val_at_pointer - (unzoomed_val + half_min_page);
adj.set_page_size (rint (page));
adj.set_value (rint (val));
adj.value_changed();
-
+
return true;
}
unzoomed_val = adj.get_value();
unzoomed_page = adj.get_page_size();
grab_window = ev->window;
-
+
if (ev->button == 3){
pinch = true;
} else {
DragStarting (); /* EMIT SIGNAL */
}
-
+
if (ev->type == GDK_2BUTTON_PRESS && ev->button == 1) {
DoubleClicked();
}
default:
break;
}
-
+
grab_comp = None;
remove_modal_grab();
{
Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
Gtk::TreeModel::iterator iter = tree_sel->get_selected();
-
+
if (iter) {
choice_made (new Result (tview, tree_sel));
} else {
default:
break;
}
-
+
if (realkey != -1) {
SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
false, realkey);
}
/* gdk/quartz maps Command to Meta */
-
+
if (key->accel_mods & GDK_META_MASK) {
use_command = 1;
}
VBox* box1;
box1 = manage (new VBox);
box1->pack_start (close_event_box, false, false, 2);
-
+
window_box.pack_end (*box1, false, false, 2);
own_window.add_events (KEY_PRESS_MASK|KEY_RELEASE_MASK|BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK|POINTER_MOTION_MASK|POINTER_MOTION_HINT_MASK);
own_window.set_type_hint (WINDOW_TYPE_HINT_UTILITY);
own_window.add (window_box);
-
+
own_window.signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
own_window.signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
own_window.signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
{
put_it_back ();
return true;
-}
+}
void
TearOff::put_it_back ()
double x_delta;
double y_delta;
RefPtr<Gdk::Window> win (own_window.get_window());
-
+
own_window.get_pointer (mx, my);
if (!dragging) {
win->get_root_origin (x, y);
win->move ((gint) floor (x + x_delta), (gint) floor (y + y_delta));
-
+
drag_x = ev->x_root;
drag_y = ev->y_root;
-
+
return true;
}
adj = scrollwin.get_vadjustment();
adj->set_value (MAX(0,(adj->get_upper() - adj->get_page_size())));
}
-
+
void
TextViewer::deliver ()
int& height)
{
Pango::Rectangle ink_rect = layout->get_ink_extents ();
-
+
width = PANGO_PIXELS(ink_rect.get_width());
height = PANGO_PIXELS(ink_rect.get_height());
}
{
int width, height;
w.ensure_style ();
-
+
get_pixel_size (w.create_pango_layout (text), width, height);
w.set_size_request(width + hpadding, height + vpadding);
}
{
int width, height;
w.ensure_style ();
-
+
get_pixel_size (w.create_pango_layout (text), width, height);
w.set_size_request(width + hpadding, height + vpadding);
}
break;
}
}
-
+
if (i == strings.end()) {
/* make a copy of the strings then add one that has a descender */
copy = strings;
} else {
to_use = &strings;
}
-
+
for (vector<string>::const_iterator i = to_use->begin(); i != to_use->end(); ++i) {
get_pixel_size (w.create_pango_layout (*i), width, height);
width_max = max(width_max,width);
{
guint8 const* src_pixel = src;
guint8* dst_pixel = dst;
-
+
/* cairo pixel data is endian-dependent ARGB with A in the most significant 8 bits,
with premultipled alpha values (see preceding function)
#else
#error ardour does not currently support PDP-endianess
-#endif
+#endif
dst_pixel += 4;
src_pixel += 4;
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
cairo_t* cr = cairo_create (surface);
cairo_text_extents_t te;
-
+
cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
cairo_select_font_face (cr, font.get_family().c_str(),
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, font.get_size() / Pango::SCALE);
cairo_text_extents (cr, name.c_str(), &te);
-
+
cairo_move_to (cr, 0.5, int (0.5 - te.height / 2 - te.y_bearing + clip_height / 2));
cairo_show_text (cr, name.c_str());
-
+
convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
cairo_destroy(cr);
/* XXX: might need special care to get the ellipsis character, not sure
how that works
- */
+ */
string s = string (layout->get_text ().substr(line->get_start_index(), line->get_length()));
-
+
cerr << "fit to pixels of " << str << " returns " << s << endl;
return s;
using namespace std;
namespace {
-
+
// I don't know if this should be translated.
const char* const title_separator = X_(" - ");
_channel_number = channelnum;
reset (0, 1, false);
-}
+}
void
Channel::connect_signals ()
} else if ((tb->controller_number >= 32 &&
tb->controller_number <= 63)) {
-
+
int cn = tb->controller_number - 32;
cv = (unsigned short) _controller_val[cn];
high 7.
*/
-
+
if (_controller_14bit[cn] == false) {
_controller_14bit[cn] = true;
cv = (cv << 7) | (tb->value & 0x7f);
} else {
/* controller can only take 7 bit values */
-
+
_controller_val[tb->controller_number] =
(controller_value_t) tb->value;
}
::closesocket (sockin);
sockin = -1;
}
-
+
if (sockout >= 0) {
::closesocket (sockout);
sockout = -1;
addrin.sin_family = AF_INET;
addrin.sin_addr.s_addr = htonl(INADDR_ANY);
addrin.sin_port = htons(base_port);
-
+
if (::bind(sockin, (struct sockaddr *) (&addrin), sizeof(addrin)) < 0) {
::perror("bind");
return false;
}
-
+
// Will Hall, 2007
// INADDR_ANY will bind to default interface,
// specify alternate interface nameon which to bind...
} else {
if_addr_in.s_addr = htonl (INADDR_ANY);
}
-
+
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ::inet_addr("225.0.0.37");
mreq.imr_interface.s_addr = if_addr_in.s_addr;
::perror("socket(out)");
return false;
}
-
+
// Will Hall, Oct 2007
if (!ifname.empty()) {
struct in_addr if_addr_out;
return false;
}
}
-
+
::memset(&addrout, 0, sizeof(struct sockaddr_in));
addrout.sin_family = AF_INET;
addrout.sin_addr.s_addr = ::inet_addr("225.0.0.37");
addrout.sin_port = htons (base_port);
-
+
// Turn off loopback...
int loop = 0;
if (::setsockopt(sockout, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop, sizeof (loop)) < 0) {
error << "cannot set non-blocking mode for IP MIDI output socket (" << ::strerror (errno) << ')' << endmsg;
return false;
}
-
+
return true;
#else
return false;
* parser. This will emit appropriate signals that will be handled
* by anyone who cares.
*/
-
+
unsigned char buf[1024];
struct sockaddr_in sender;
socklen_t slen = sizeof(sender);
if (r >= 0) {
_parser->set_timestamp (timestamp);
-
+
for (int i = 0; i < r; ++i) {
_parser->scanner (buf[i]);
}
bool all_notes_off (timestamp_t timestamp) {
return channel_msg (MIDI::controller, 123, 0, timestamp);
}
-
+
bool control (byte id, byte value, timestamp_t timestamp) {
return channel_msg (MIDI::controller, id, value, timestamp);
}
-
+
bool note_on (byte note, byte velocity, timestamp_t timestamp) {
return channel_msg (MIDI::on, note, velocity, timestamp);
}
-
+
bool note_off (byte note, byte velocity, timestamp_t timestamp) {
return channel_msg (MIDI::off, note, velocity, timestamp);
}
-
+
bool aftertouch (byte value, timestamp_t timestamp) {
return channel_msg (MIDI::chanpress, value, 0, timestamp);
}
size_t _notes_on;
void reset (timestamp_t timestamp, framecnt_t nframes, bool notes_off = true);
-
+
void process_note_off (Parser &, EventTwoBytes *);
void process_note_on (Parser &, EventTwoBytes *);
void process_controller (Parser &, EventTwoBytes *);
static const int lowest_ipmidi_port_default = 21928;
-private:
+private:
int sockin;
int sockout;
struct sockaddr_in addrout;
: _bank(std::max(0, std::min(bank_num, 16383)))
, _program(std::max(0, std::min(program_num, 127)))
{}
-
+
inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
_bank = id._bank;
_program = id._program;
return *this;
}
-
+
inline bool operator==(const PatchPrimaryKey& id) const {
return (_bank == id._bank &&
_program == id._program);
}
-
+
/** Strict weak ordering. */
inline bool operator<(const PatchPrimaryKey& id) const {
if (_bank < id._bank) {
};
class PatchBank;
-
+
class LIBMIDIPP_API Patch
{
public:
const std::string& name() const { return _name; }
void set_name(const std::string& name) { _name = name; }
-
+
const std::string& note_list_name() const { return _note_list_name; }
uint8_t program_number() const { return _id.program(); }
const std::string& name() const { return _name; }
void set_name(const std::string& name) { _name = name; }
-
+
const PatchBanks& patch_banks() const { return _patch_banks; }
bool available_for_channel(uint8_t channel) const {
return _available_for_channels.find(channel) != _available_for_channels.end();
}
-
+
boost::shared_ptr<Patch> find_patch(const PatchPrimaryKey& key) {
return _patch_map[key];
}
-
+
boost::shared_ptr<Patch> previous_patch(const PatchPrimaryKey& key) {
for (PatchList::const_iterator i = _patch_list.begin();
i != _patch_list.end();
}
}
}
-
+
return boost::shared_ptr<Patch>();
}
-
+
boost::shared_ptr<Patch> next_patch(const PatchPrimaryKey& key) {
for (PatchList::const_iterator i = _patch_list.begin();
i != _patch_list.end();
}
}
}
-
+
return boost::shared_ptr<Patch>();
}
const std::string& name() const { return _name; }
void set_name(const std::string& name) { _name = name; }
-
+
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
-
+
/// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
const std::string& channel_name_set_name_by_channel(uint8_t channel) {
assert(channel <= 15);
return _channel_name_set_assignments[channel];
}
-
+
private:
/// array index = channel number
/// string contents = name of channel name set
typedef std::map<std::string, boost::shared_ptr<ControlNameList> > ControlNameLists;
typedef std::map<std::string, boost::shared_ptr<ValueNameList> > ValueNameLists;
typedef std::map<std::string, PatchNameList> PatchNameLists;
-
+
MasterDeviceNames() {};
virtual ~MasterDeviceNames() {};
-
+
const std::string& manufacturer() const { return _manufacturer; }
void set_manufacturer(const std::string& manufacturer) { _manufacturer = manufacturer; }
-
+
const Models& models() const { return _models; }
void set_models(const Models some_models) { _models = some_models; }
uint8_t number);
const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
-
+
boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name);
boost::shared_ptr<ChannelNameSet> channel_name_set_by_channel(const std::string& mode, uint8_t channel);
boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key);
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
-
+
private:
std::string _manufacturer;
Models _models;
public:
// Maps Model names to MasterDeviceNames
typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
-
+
MIDINameDocument() {}
MIDINameDocument(const std::string& filename);
virtual ~MIDINameDocument() {};
const std::string& author() const { return _author; }
void set_author(const std::string& author) { _author = author; }
-
+
boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
-
+
const MasterDeviceNames::Models& all_models() const { return _all_models; }
-
+
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
cmdChase = 0xB,
cmdCommandErrorReset = 0xC,
cmdMmcReset = 0xD,
-
+
cmdIllegalMackieJogStart = 0x20,
cmdIllegalMackieJogStop = 0x21,
-
+
cmdWrite = 0x40,
cmdMaskedWrite = 0x41,
cmdRead = 0x42,
cmdWait = 0x7C,
cmdResume = 0x7F
};
-
+
MachineControl ();
void set_ports (MIDI::Port* input, MIDI::Port* output);
Port* input_port() { return _input_port; }
Port* output_port() { return _output_port; }
-
+
void set_receive_device_id (byte id);
void set_send_device_id (byte id);
byte receive_device_id () const { return _receive_device_id; }
/* Signals to connect to if you want to run "callbacks"
when certain MMC commands are received.
*/
-
+
MMCSignal Stop;
MMCSignal Play;
MMCSignal DeferredPlay;
/* The second argument is the shuttle speed, the third is
true if the direction is "forwards", false for "reverse"
*/
-
+
PBD::Signal3<void,MachineControl&,float,bool> Shuttle;
/* The second argument specifies the desired track record enabled
PBD::Signal3<void,MachineControl &,size_t,bool>
TrackRecordStatusChange;
-
+
/* The second argument specifies the desired track record enabled
status.
*/
PBD::Signal3<void,MachineControl &,size_t,bool>
TrackMuteChange;
-
+
/* The second argument points to a byte array containing
the locate target value in MMC Standard Time Code
format (5 bytes, roughly: hrs/mins/secs/frames/subframes)
PBD::Signal2<void,MachineControl &, const byte *> Locate;
/* The second argument is the number of steps to jump */
-
+
PBD::Signal2<void,MachineControl &, int> Step;
#define MMC_NTRACKS 48
/* note: these are not currently in use */
-
+
byte updateRate;
byte responseError;
byte commandError;
byte responseSegment;
byte wait;
byte resume;
-
+
private:
byte _receive_device_id;
byte _send_device_id;
int do_locate (byte *, size_t len);
int do_step (byte *, size_t len);
int do_shuttle (byte *, size_t len);
-
+
void write_track_status (byte *, size_t len, byte reg);
void spp_start ();
void spp_continue ();
MachineControlCommand () : _command (MachineControl::Command (0)) {}
MachineControlCommand (MachineControl::Command);
MachineControlCommand (Timecode::Time);
-
+
MIDI::byte* fill_buffer (MachineControl *mmc, MIDI::byte *) const;
private:
message the next time ::scanner() parses such a message. It should
therefore be set before every byte passed into ::scanner().
*/
-
+
framecnt_t get_timestamp() const { return _timestamp; }
void set_timestamp (const framecnt_t timestamp) { _timestamp = timestamp; }
/* signals that anyone can connect to */
-
+
BankSignal bank_change;
TwoByteSignal note_on;
TwoByteSignal note_off;
MTC_Status mtc_running() const { return _mtc_running; }
const byte *mtc_current() const { return _mtc_time; }
bool mtc_locked() const { return _mtc_locked; }
-
+
PBD::Signal3<void, Parser &, int, framecnt_t> mtc_qtr;
PBD::Signal3<void, const byte *, bool, framecnt_t> mtc_time;
PBD::Signal1<void, MTC_Status> mtc_status;
}
void reset_mtc_state ();
-
+
private:
/* tracing */
-
+
std::ostream *trace_stream;
std::string trace_prefix;
void trace_event (Parser &p, byte *msg, size_t len);
MTC_Status _mtc_running;
bool _mtc_locked;
byte last_qtr_frame;
-
+
framecnt_t _timestamp;
ParseState pre_variable_state;
IsInput = 0x1, /* MUST MATCH JACK's JackPortIsInput */
IsOutput = 0x2, /* MUST MATCH JACK's JackPortIsOutput */
};
-
+
Port (std::string const &, Flags);
Port (const XMLNode&);
virtual ~Port ();
Channel *channel (channel_t chn) {
return _channel[chn&0x7F];
}
-
+
Parser* parser () {
return _parser;
}
-
+
const char *name () const { return _tagname.c_str(); }
bool ok () const { return _ok; }
{
byte buf[1];
-
+
text_receiver.listen_to (error);
text_receiver.listen_to (info);
text_receiver.listen_to (fatal);
namespace Name
{
-
+
Patch::Patch (std::string name, uint8_t p_number, uint16_t b_number)
: _name (name)
, _id (p_number, b_number)
return -1; // Failed to find a program number anywhere
}
}
-
+
XMLNode* use_note_name_list = node.child("UsesNoteNameList");
if (use_note_name_list) {
_note_list_name = use_note_name_list->property ("Name")->value();
os << (int) (*x) << ' ';
}
os << endl;
-
+
for (ChannelNameSet::PatchBanks::const_iterator pbi = cns._patch_banks.begin(); pbi != cns._patch_banks.end(); ++pbi) {
os << "\tPatch Bank " << (*pbi)->name() << " with " << (*pbi)->patch_name_list().size() << " patches\n";
for (PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
ChannelNameSet::set_patch_banks (const ChannelNameSet::PatchBanks& pb)
{
_patch_banks = pb;
-
+
_patch_map.clear ();
_patch_list.clear ();
_patch_list_name = "";
_available_for_channels.clear ();
-
+
for (PatchBanks::const_iterator pbi = _patch_banks.begin(); pbi != _patch_banks.end(); ++pbi) {
for (PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
_patch_map[(*pni)->patch_primary_key()] = (*pni);
error << "No author information in MIDNAM file" << endmsg;
return -1;
}
-
+
if (author->front()->children().size() > 0) {
_author = author->front()->children().front()->content();
}
_master_device_names_list.insert(
std::pair<std::string, boost::shared_ptr<MasterDeviceNames> >
(*model, master_device_names));
-
+
_all_models.insert(*model);
}
}
sysex_buf[3] != 0x7) { /* MMC Response */
return false;
}
-
+
return true;
}
len -= skiplen;
} while (len > 1); /* skip terminating EOX byte */
-}
+}
int
MachineControl::do_masked_write (MIDI::byte *msg, size_t len)
/* return the number of bytes "consumed" */
int retval = msg[1] + 2; /* bytes following + 2 */
-
+
switch (msg[2]) {
case 0x4f: /* Track Record Ready Status */
write_track_status (&msg[3], len - 3, msg[2]);
bit 4: aux track b
the format of the message (its an MMC Masked Write) is:
-
+
0x41 Command Code
<count> byte count of following data
<name> byte value of the field being written
bitmap being written to
<mask> ones in the mask indicate which bits will be changed
<data> new data for the byte being written
-
+
by the time this code is executing, msg[0] is the
byte number of the target byte. if its zero, we
are writing to a special byte in the standard
special. hence the bits for tracks 1 + 2 are bits
5 and 6 of the first byte of the track
bitmap. so:
-
+
change track 1: msg[0] = 0; << first byte of track bitmap
msg[1] = 0100000; << binary: bit 5 set
-
+
change track 2: msg[0] = 0; << first byte of track bitmap
msg[1] = 1000000; << binary: bit 6 set
-
+
change track 3: msg[0] = 1; << second byte of track bitmap
msg[1] = 0000001; << binary: bit 0 set
-
+
the (msg[0] * 8) - 6 computation is an attempt to
extract the value of the first track: ie. the one
that would be indicated by bit 0 being set.
-
+
so, if msg[0] = 0, msg[1] = 0100000 (binary),
what happens is that base_track = -5, but by the
time we check the correct bit, n = 5, and so the
*/
bool val = (msg[2] & (1<<n));
-
+
switch (reg) {
case 0x4f:
trackRecordStatus[base_track+n] = val;
TrackRecordStatusChange (*this, base_track+n, val);
break;
-
+
case 0x62:
trackMute[base_track+n] = val;
TrackMuteChange (*this, base_track+n, val);
} else {
forward = true;
}
-
+
left_shift = (sh & 0x38);
integral = ((sh & 0x7) << left_shift) | (sm >> (7 - left_shift));
{
byte buf[1];
-
+
text_receiver.listen_to (error);
text_receiver.listen_to (info);
text_receiver.listen_to (fatal);
}
/* full MTC */
-
+
fake_mtc_time[0] = sysex_buf[8]; // frames
fake_mtc_time[1] = sysex_buf[7]; // minutes
fake_mtc_time[2] = sysex_buf[6]; // seconds
fake_mtc_time[3] = (sysex_buf[5] & 0x1f); // hours
-
+
_mtc_fps = MTC_FPS ((sysex_buf[5] & 0x60) >> 5); // fps
fake_mtc_time[4] = (byte) _mtc_fps;
#endif
if (_mtc_running == MTC_Stopped) {
-
+
/* we are stopped but are seeing qtr frame messages */
if (consecutive_qtr_frame_cnt == 0) {
/* first quarter frame */
if (which_quarter_frame != 0 && which_quarter_frame != 7) {
-
+
last_qtr_frame = which_quarter_frame;
consecutive_qtr_frame_cnt++;
}
-
+
// cerr << "first seen qframe = " << (int) last_qtr_frame << endl;
return;
} else if (consecutive_qtr_frame_cnt == 1) {
/* third quarter frame */
-
+
#ifdef DEBUG_MTC
cerr << "second seen qframe = " << (int) which_quarter_frame << endl;
#endif
case MTC_Backward:
if (which_quarter_frame == 0) {
expected_mtc_quarter_frame_code = 7;
-
+
} else {
expected_mtc_quarter_frame_code = which_quarter_frame - 1;
}
case MTC_Stopped:
break;
}
-
+
} else {
-
+
/* already running */
// for testing bad MIDI connections etc.
*/
boost::optional<bool> res = mtc_skipped ();
-
+
if (res.get_value_or (false)) {
/* no error, reset next expected frame */
case MTC_Backward:
if (which_quarter_frame == 0) {
expected_mtc_quarter_frame_code = 7;
-
+
} else {
expected_mtc_quarter_frame_code = which_quarter_frame - 1;
}
#ifdef DEBUG_MTC
cerr << "SKIPPED, next expected = " << expected_mtc_quarter_frame_code << endl;
-#endif
+#endif
return;
}
#endif
reset_mtc_state ();
mtc_status (MTC_Stopped);
-
+
return;
} else {
case 5: // minutes MS nibble
_qtr_mtc_time[2] |= (msg[1] & 0xf)<<4;
break;
-
+
case 6: // hours LS nibble
_qtr_mtc_time[3] |= msg[1] & 0xf;
break;
case 7:
-
+
/* last quarter frame msg has the MS bit of
the hour in bit 0, and the SMPTE FPS type
in bits 5 and 6
*/
-
+
_qtr_mtc_time[3] |= ((msg[1] & 0x1) << 4);
_mtc_fps = MTC_FPS ((msg[1] & 0x6) >> 1);
_qtr_mtc_time[4] = _mtc_fps;
break;
}
-
+
#ifdef DEBUG_MTC
cerr << "Emit MTC Qtr\n";
#endif
switch (_mtc_running) {
case MTC_Forward:
if (which_quarter_frame == 7) {
-
+
/* we've reached the final of 8 quarter frame messages.
store the time, reset the pending time holder,
and signal anyone who wants to know the time.
*/
-
+
if (consecutive_qtr_frame_cnt >= 8) {
memcpy (_mtc_time, _qtr_mtc_time, sizeof (_mtc_time));
memset (_qtr_mtc_time, 0, sizeof (_qtr_mtc_time));
mtc_time (_mtc_time, false, _timestamp);
}
expected_mtc_quarter_frame_code = 0;
-
+
} else {
expected_mtc_quarter_frame_code = which_quarter_frame + 1;
}
break;
-
+
case MTC_Backward:
if (which_quarter_frame == 0) {
-
+
/* we've reached the final of 8 quarter frame messages.
store the time, reset the pending time holder,
and signal anyone who wants to know the time.
case MIDI::any:
return "any midi message";
-
+
case off:
return "note off";
-
+
case on:
return "note on";
-
+
case polypress:
return "aftertouch";
-
+
case MIDI::controller:
return "controller";
-
+
case program:
return "program change";
-
+
case chanpress:
return "channel pressure";
-
+
case MIDI::pitchbend:
return "pitch bend";
-
+
case MIDI::sysex:
return "system exclusive";
-
+
case MIDI::song:
return "song position";
-
+
case MIDI::tune:
return "tune";
-
+
case MIDI::eox:
return "end of sysex";
-
+
case MIDI::timing:
return "timing";
-
+
case MIDI::start:
return "start";
-
+
case MIDI::stop:
return "continue";
-
+
case MIDI::contineu:
return "stop";
-
+
case active:
return "active sense";
-
+
default:
return "unknow MIDI event type";
}
if ((o = trace_stream) == NULL) { /* can be asynchronously removed */
return;
}
-
+
type = (eventType) (msg[0]&0xF0);
switch (type) {
<< (int) msg[2]
<< endmsg;
break;
-
+
case on:
*o << trace_prefix
<< "Channel "
<< (int) msg[2]
<< endmsg;
break;
-
+
case polypress:
*o << trace_prefix
<< "Channel "
<< (int) msg[1]
<< endmsg;
break;
-
+
case MIDI::controller:
*o << trace_prefix
<< "Channel "
<< (int) msg[2]
<< endmsg;
break;
-
+
case program:
*o << trace_prefix
<< "Channel "
<< (int) msg[1]
<< endmsg;
break;
-
+
case chanpress:
*o << trace_prefix
<< "Channel "
<< (int) msg[1]
<< endmsg;
break;
-
+
case MIDI::pitchbend:
*o << trace_prefix
<< "Channel "
<< ((msg[2]<<7)|msg[1])
<< endmsg;
break;
-
+
case MIDI::sysex:
if (len == 1) {
switch (msg[0]) {
default:
*o << trace_prefix
<< "System Exclusive (1 byte : " << hex << (int) *msg << dec << ')'
- << endmsg;
+ << endmsg;
break;
}
} else {
*o << (int) msgbuf[i] << ' ';
}
*o << dec << ']' << endmsg;
-
+
}
break;
-
+
case MIDI::song:
*o << trace_prefix << "Song" << endmsg;
break;
-
+
case MIDI::tune:
*o << trace_prefix << "Tune" << endmsg;
break;
-
+
case MIDI::eox:
*o << trace_prefix << "End-of-System Exclusive" << endmsg;
break;
-
+
case MIDI::timing:
*o << trace_prefix << "Timing" << endmsg;
break;
-
+
case MIDI::start:
*o << trace_prefix << "Start" << endmsg;
break;
-
+
case MIDI::stop:
*o << trace_prefix << "Stop" << endmsg;
break;
-
+
case MIDI::contineu:
*o << trace_prefix << "Continue" << endmsg;
break;
-
+
case active:
*o << trace_prefix << "Active Sense" << endmsg;
break;
-
+
default:
*o << trace_prefix << "Unrecognized MIDI message" << endmsg;
break;
boost::optional<int> edit_result;
// cerr << "parse: " << hex << (int) inbyte << dec << " state = " << state << " msgindex = " << msgindex << " runnable = " << runnable << endl;
-
+
/* Check active sensing early, so it doesn't interrupt sysex.
-
+
NOTE: active sense messages are not considered to fit under
"any" for the purposes of callbacks. If a caller wants
active sense messages handled, which is unlikely, then
every other MIDI message in terms of semantics that its
counter-productive to treat them similarly.
*/
-
+
if (inbyte == 0xfe) {
message_counter[inbyte]++;
if (!_offline) {
}
return;
}
-
+
/* If necessary, allocate larger message buffer. */
-
+
if (msgindex >= msglen) {
msglen *= 2;
msgbuf = (unsigned char *) realloc (msgbuf, msglen);
}
-
+
/*
Real time messages can occur ANYPLACE,
but do not interrupt running status.
*/
bool rtmsg = false;
-
+
switch (inbyte) {
case 0xf8:
rtmsg = true;
if (rtmsg) {
boost::optional<int> res = edit (&inbyte, 1);
-
+
if (res.get_value_or (1) >= 0 && !_offline) {
realtime_msg (inbyte);
}
-
+
return;
}
}
}
}
-
+
/*
* Status bytes always start a new message, except EOX
*/
-
+
if (statusbit) {
msgindex = 0;
return;
}
-
+
/*
* We've got a Data byte.
*/
-
+
msgbuf[msgindex++] = inbyte;
switch (state) {
* messages, so just handle it silently.
*/
break;
-
+
case NEEDTWOBYTES:
/* wait for the second byte */
if (msgindex < 3)
return;
/*FALLTHRU*/
-
+
case NEEDONEBYTE:
/* We've completed a 1 or 2 byte message. */
edit_result = edit (msgbuf, msgindex);
if (edit_result.get_value_or (1)) {
-
+
/* message not cancelled by an editor */
-
+
message_counter[msgbuf[0] & 0xF0]++;
if (!_offline) {
signal (msgbuf, msgindex);
}
}
-
+
if (runnable) {
/* In Runnable mode, we reset the message
index, but keep the callbacks_pending and state the
state = NEEDSTATUS;
}
break;
-
+
case VARIABLELENGTH:
/* nothing to do */
break;
switch (msgtype) {
case none:
break;
-
+
case off:
channel_active_preparse[chan_i] (*this);
note_off (*this, (EventTwoBytes *) &msg[1]);
(*this, (EventTwoBytes *) &msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case on:
channel_active_preparse[chan_i] (*this);
channel_active_postparse[chan_i] (*this);
break;
-
+
case MIDI::controller:
channel_active_preparse[chan_i] (*this);
controller (*this, (EventTwoBytes *) &msg[1]);
(*this, (EventTwoBytes *) &msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case program:
channel_active_preparse[chan_i] (*this);
program_change (*this, msg[1]);
channel_program_change[chan_i] (*this, msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case chanpress:
channel_active_preparse[chan_i] (*this);
pressure (*this, msg[1]);
channel_pressure[chan_i] (*this, msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case polypress:
channel_active_preparse[chan_i] (*this);
poly_pressure (*this, (EventTwoBytes *) &msg[1]);
(*this, (EventTwoBytes *) &msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case MIDI::pitchbend:
channel_active_preparse[chan_i] (*this);
pitchbend (*this, (msg[2]<<7)|msg[1]);
channel_pitchbend[chan_i] (*this, (msg[2]<<7)|msg[1]);
channel_active_postparse[chan_i] (*this);
break;
-
+
case MIDI::sysex:
sysex (*this, msg, len);
break;
process_mtc_quarter_frame (msg);
mtc_quarter_frame (*this, *msg);
break;
-
+
case MIDI::position:
position (*this, msg, len);
break;
-
+
case MIDI::song:
song (*this, msg, len);
break;
-
+
case MIDI::tune:
tune (*this);
-
+
default:
/* XXX some kind of warning ? */
break;
}
-
+
any (*this, msg, len);
}
/* this hack deals with the possibility of our first MIDI
bytes being running status messages.
*/
-
+
channel_msg (0x90);
state = NEEDSTATUS;
}
Port::clock (timestamp_t timestamp)
{
static byte clockmsg = 0xf8;
-
+
if (sends_output()) {
return midimsg (&clockmsg, 1, timestamp);
}
-
+
return false;
}
} else {
root->add_property ("mode", "output");
}
-
+
#if 0
byte device_inquiry[6];
device_inquiry[0] = 0x06;
device_inquiry[0] = 0x02;
device_inquiry[0] = 0xf7;
-
+
write (device_inquiry, sizeof (device_inquiry), 0);
#endif
if (pan != 0.0f) {
/* pan is not 1 but also not 0, so we must do it "properly" */
-
+
mix_buffers_with_gain(dst,src,nframes,pan);
/* XXX it would be nice to mark the buffer as written to */
} else {
/* pan is 1 so we can just copy the input samples straight in */
-
+
mix_buffers_no_gain(dst,src,nframes);
/* XXX it would be nice to mark the buffer as written to */
if (pan != 0.0f) {
/* pan is 1 but also not 0, so we must do it "properly" */
-
+
//obufs.get_audio(1).read_from (srcbuf, nframes);
mix_buffers_with_gain(dst,src,nframes,pan);
if (pan != 0.0f) {
/* pan is not 1 but also not 0, so we must do it "properly" */
-
+
mix_buffers_with_gain(dst,src,nframes,pan);
// obufs.get_audio(1).read_from (srcbuf, nframes);
-
+
/* XXX it would be nice to mark the buffer as written to */
}
} else {
/* pan is 1 so we can just copy the input samples straight in */
-
+
mix_buffers_no_gain(dst,src,nframes);
/* XXX it would be nice to mark the buffer as written to */
std::pair<double, double> position_range () const;
std::pair<double, double> width_range () const;
-
+
void set_position (double);
void set_width (double);
using namespace std;
using namespace PBD;
using namespace Glib;
-
+
uint64_t BaseUI::rt_bit = 1;
BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type();
{
Glib::Threads::Mutex::Lock lm (_run_lock);
_running.signal ();
-
+
return false; // don't call it again
}
if (ioc & IO_IN) {
request_channel.drain ();
-
+
/* there may been an error. we'd rather handle requests first,
and then get IO_HUP or IO_ERR on the next loop.
*/
if (size) {
#ifdef HAVE_EXECINFO
strings = ::backtrace_symbols (trace, size);
-#endif
+#endif
if (strings) {
for (i = 3; i < 5+18 && i < size; i++) {
str << strings[i] << std::endl;
if (ptr == 0) {
return false;
}
-
+
return interesting_pointers().find (ptr) != interesting_pointers().end();
}
if (is_interesting_object (old_obj)) {
if (debug_out) {
cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count
- << " (total sp's = " << sptrs().size() << ')' << endl;
+ << " (total sp's = " << sptrs().size() << ')' << endl;
}
PointerMap::iterator x = sptrs().find (sp);
-
+
if (x != sptrs().end()) {
sptrs().erase (x);
if (debug_out) {
newpair.second = new SPDebug (new Backtrace());
sptrs().insert (newpair);
-
+
if (debug_out) {
cerr << "assignment created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count
<< " UC = " << new_use_count
- << " (total sp's = " << sptrs().size() << ')' << endl;
+ << " (total sp's = " << sptrs().size() << ')' << endl;
cerr << *newpair.second << endl;
}
}
if (is_interesting_object (old_obj)) {
if (debug_out) {
cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count
- << " (total sp's = " << sptrs().size() << ')' << endl;
+ << " (total sp's = " << sptrs().size() << ')' << endl;
}
PointerMap::iterator x = sptrs().find (sp);
-
+
if (x != sptrs().end()) {
sptrs().erase (x);
if (debug_out) {
newpair.second = new SPDebug (new Backtrace());
sptrs().insert (newpair);
-
+
if (debug_out) {
cerr << "reset created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count
<< " UC = " << new_use_count
- << " (total sp's = " << sptrs().size() << ')' << endl;
+ << " (total sp's = " << sptrs().size() << ')' << endl;
cerr << *newpair.second << endl;
}
}
string front = str.substr (0, first_space);
string back = str.substr (first_space);
- vector<string> path;
+ vector<string> path;
split (front, path, '/');
if (path.size() < 2) {
return -1;
}
- vector<string> rest;
+ vector<string> rest;
split (back, rest, ' ');
if (rest.size() < 1) {
return -1;
}
} else if (path[1] == "send") {
-
+
if (path.size() == 3 && rest.size() == 2) {
if (path[2] == "gain") {
_subtype = SendGain;
return -1;
}
}
-
+
return 0;
}
{
if (banked()) {
return _rid + _bank_offset;
- }
+ }
return _rid;
}
if (n < _target.size()) {
return _target[n];
}
-
+
return 0;
}
}
/* whatever the length is now, use it */
-
+
return orig;
}
} else if( ('A'<=hi) && (hi<='F') ) {
hi -= ('A'-10);
}
-
+
lo = (int) loc;
-
+
if( ('0'<=lo) && (lo<='9') ) {
lo -= '0';
} else if( ('a'<=lo) && (lo<='f') ) {
secs -= (hrs * 3600LL);
int64_t mins = secs / 60LL;
secs -= (mins * 60LL);
-
+
int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs;
int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate));
float fractional_secs = (float) frames_remaining / sample_rate;
-
+
char duration_str[64];
sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
-
+
return duration_str;
}
error << "cannot set non-blocking mode for x-thread pipe (read) (" << ::strerror (errno) << ')' << endmsg;
return;
}
-
+
if (fcntl (fds[1], F_SETFL, O_NONBLOCK)) {
error << "cannot set non-blocking mode for x-thread pipe (write) (%2)" << ::strerror (errno) << ')' << endmsg;
return;
// make the socket non-blockable if required
u_long mode = (u_long)non_blocking;
int otp_result = 0;
-
+
otp_result = ioctlsocket(send_socket, FIONBIO, &mode);
if (otp_result != NO_ERROR) {
std::cerr << "CrossThreadChannel::CrossThreadChannel() Send socket cannot be set to non blocking mode with error: " << WSAGetLastError() << std::endl;
std::cerr << "CrossThreadChannel::CrossThreadChannel() Setting receive socket address to local failed with error: " << WSAGetLastError() << std::endl;
return;
}
-
+
// construct IOChannel
receive_channel = g_io_channel_win32_new_socket((gint)receive_socket);
-
+
// set binary data type
GIOStatus g_status = g_io_channel_set_encoding (receive_channel, NULL, NULL);
if (G_IO_STATUS_NORMAL != g_status ) {
{
char c = 0;
- // write one byte to wake up a thread which is listening our IOS
+ // write one byte to wake up a thread which is listening our IOS
sendto(send_socket, &c, sizeof(c), 0, (SOCKADDR*)&recv_address, sizeof(recv_address) );
}
if (G_IO_STATUS_NORMAL != g_status) {
std::cerr << "CrossThreadChannel::CrossThreadChannel() Cannot drain from read buffer! " << g_status << std::endl;
-
+
if (g_error) {
std::cerr << "Error is Domain: " << g_error->domain << " Code: " << g_error->code << std::endl;
g_clear_error(&g_error);
return -1;
}
}
-
+
// fetch the message from the channel.
GIOStatus g_status = g_io_channel_read_chars (receive_channel, &msg, sizeof(msg), &read, &g_error);
}
}
}
-
+
debug_bits = bits;
-
+
return 0;
}
{
string::const_iterator it1 = s1.begin();
string::const_iterator it2 = s2.begin();
-
+
while ((it1 != s1.end()) && (it2 != s2.end())) {
if(::toupper(*it1) != ::toupper(*it2)) {//letters differ?
// return -1 to indicate 'smaller than', 1 otherwise
newpair.first = type;
newpair.second = EnumRegistration (v, s, false);
-
+
result = registry.insert (newpair);
if (!result.second) {
newpair.first = type;
newpair.second = EnumRegistration (v, s, true);
-
+
result = registry.insert (newpair);
if (!result.second) {
} else {
return read_distinct (x->second, value);
}
-}
+}
string
EnumWriter::write_bits (EnumRegistration& er, int value)
}
do {
-
+
comma = str.find_first_of (',');
string segment = str.substr (0, comma);
for (vector<string>::const_iterator e = ecopy.begin(); e != ecopy.end(); ++e) {
string::size_type equal = (*e).find_first_of ('=');
-
+
if (equal == string::npos) {
/* say what? an environ value without = ? */
continue;
}
-
+
string var_name = (*e).substr (0, equal);
g_unsetenv(var_name.c_str());
}
* want, and many of the objects we want to do this with already
* inherit (indirectly) from sigc::trackable.
*/
-
+
if (ir->event_loop) {
Glib::Threads::Mutex::Lock lm (ir->event_loop->slot_invalidation_mutex());
for (list<BaseRequestObject*>::iterator i = ir->requests.begin(); i != ir->requests.end(); ++i) {
return __builtin_ffs(x);
#elif defined (COMPILER_MSVC)
unsigned long index;
-#ifdef WIN64
+#ifdef WIN64
if (0 != _BitScanForward64(&index, (__int64)x))
#else
if (0 != _BitScanForward(&index, (unsigned long)x))
info << string_compose (_("CPU vendor: %1"), cpu_vendor) << endmsg;
if (num_ids > 0) {
-
+
/* Now get CPU/FPU flags */
-
+
__cpuid (cpu_info, 1);
if ((cpu_info[2] & (1<<27)) /* OSXSAVE */ &&
}
/* Figure out CPU/FPU denormal handling capabilities */
-
+
if (cpu_info[3] & (1 << 24)) {
-
+
char** fxbuf = 0;
-
+
/* DAZ wasn't available in the first version of SSE. Since
setting a reserved bit in MXCSR causes a general protection
fault, we need to be able to check the availability of this
assert (fxbuf);
(void) posix_memalign ((void **) fxbuf, 16, 512);
assert (*fxbuf);
-#endif
-
+#endif
+
memset (*fxbuf, 0, 512);
-
+
#ifdef COMPILER_MSVC
char *buf = *fxbuf;
__asm {
: "memory"
);
#endif
-
+
uint32_t mxcsr_mask = *((uint32_t*) &((*fxbuf)[28]));
-
+
/* if the mask is zero, set its default value (from intel specs) */
-
+
if (mxcsr_mask == 0) {
mxcsr_mask = 0xffbf;
}
-
+
if (mxcsr_mask & (1<<6)) {
_flags = Flags (_flags | HasDenormalsAreZero);
}
-
+
#if !defined HAVE_POSIX_MEMALIGN && defined PLATFORM_WINDOWS
_aligned_free (*fxbuf);
_aligned_free (fxbuf);
const int parameter_end = 0x80000004;
string cpu_brand;
-
+
if (cpu_info[0] >= parameter_end) {
char* cpu_string_ptr = cpu_string;
-
+
for (int parameter = 0x80000002; parameter <= parameter_end &&
cpu_string_ptr < &cpu_string[sizeof(cpu_string)]; parameter++) {
__cpuid(cpu_info, parameter);
}
}
#endif /* !ARCH_X86 */
-}
+}
FPU::~FPU ()
{
{
Glib::Threads::Mutex::Lock lm (*counter_lock);
_id = _counter++;
-}
+}
int
ID::string_assign (string str)
}
return 0;
-#endif
+#endif
}
void cache_aligned_free (void* memptr)
}
return 0;
-#endif
+#endif
}
void aligned_free (void* memptr)
MD5::digestFile (char *filename)
{
Init();
-
+
FILE *file;
int len;
unsigned char buffer[1024];
MD5::Transform (uint32_t state[4], uint8_t const * block)
{
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
+
Decode (x, block, 64);
-
+
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
+
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
+
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
MD5::Decode (uint32_t *output, uint8_t const * input, size_t len)
{
size_t i, j;
-
+
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
unsigned int matchlen;
const char *cpath = path.c_str();
char best[PATH_MAX+1];
-
+
if ((mntf = setmntent ("/etc/mtab", "r")) == 0) {
return "";
}
unsigned int matchlen;
const char *cpath = path.c_str();
char best[PATH_MAX+1];
-
+
/* From the manpage, under "BUGS" : "The memory allocated by getmntinfo() cannot be free(3)'d by the
application."
-
+
Thus: we do NOT try to free memory allocated by getmntinfo()
*/
}
}
}
-
+
return best;
}
#endif // HAVE_GETMNTENT
#ifdef TEST_MOUNTPOINT
-
+
main (int argc, char *argv[])
{
printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str());
b = c;
c = a % b;
}
-
+
return b;
}
has_equal++;
} else
current_argv_len = strlen(current_argv);
-
+
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
// possibly need to add that functionality here at a later date.
} else {
char temp[(_MAX_PATH+1)*6]; // Allow for maximum length of a path in wchar characters
-
+
// POSIX 'realpath()' requires that the buffer size is at
// least PATH_MAX+1, so assume that the user knew this !!
if (0 != rpath) {
snprintf (resolved_path, _MAX_PATH+1, "%s", Glib::locale_to_utf8 (temp).c_str());
}
-
+
}
-
+
return (rpath);
}
regex_t compiled_pattern;
const int nmatches = 100;
regmatch_t matches[nmatches];
-
+
if (regcomp (&compiled_pattern, "\\$([a-zA-Z_][a-zA-Z0-9_]*|\\{[a-zA-Z_][a-zA-Z0-9_]*\\})", REG_EXTENDED)) {
std::cerr << "bad regcomp\n";
return path;
if (regexec (&compiled_pattern, path.c_str(), nmatches, matches, 0)) {
break;
}
-
+
/* matches[0] gives the entire match */
-
+
string match = path.substr (matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so);
-
+
/* try to get match from the environment */
if (match[1] == '{') {
/* Initialize windows socket DLL for PBD::CrossThreadChannel
*/
-
+
if (WSAStartup(MAKEWORD(1,1),&wsaData) != 0) {
fatal << X_("Windows socket initialization failed with error: ") << WSAGetLastError() << endmsg;
abort();
#ifdef PLATFORM_WINDOWS
PBD::MMCSS::deinitialize ();
WSACleanup();
-#endif
+#endif
EnumWriter::destroy ();
FPU::destroy ();
cleanup_request_buffer (void* ptr)
{
RequestBuffer* rb = (RequestBuffer*) ptr;
-
+
/* this is called when the thread for which this request buffer was
* allocated dies. That could be before or after the end of the UI
* event loop for which this request buffer provides communication.
* a request. If the UI has finished processing requests, then
* we will leak this buffer object.
*/
-
+
rb->dead = true;
}
when the thread exits, and ensures that the buffer is marked
dead. it will then be deleted during a call to handle_ui_requests()
*/
-
+
per_thread_request_buffer.set (b);
}
++tmp;
request_buffers.erase (i);
i = tmp;
- } else {
+ } else {
++i;
}
}
if (req->invalidation) {
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_name()));
-
+
/* after this call, if the object referenced by the
* invalidation record is deleted, it will no longer
* try to mark the request as invalid.
*/
request_buffer_map_lock.unlock ();
-
+
/* unlock the request lock while we execute the request, so
* that we don't needlessly block other threads (note: not RT
* threads since they have their own queue) from making requests.
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_name(), req->type));
do_request (req);
delete req;
- } else {
+ } else {
/* If called from a different thread, we first check to see if
* the calling thread is registered with this UI. If so, there
}
RequestObject *req = get_request (BaseUI::CallSlot);
-
+
if (req == 0) {
return;
}
/* copy semantics: copy the functor into the request object */
req->the_slot = f;
-
+
/* the invalidation record is an object which will carry out
* invalidation of any requests associated with it when it is
* destroyed. it can be null. if its not null, associate this
}
send_request (req);
-}
+}
RequestBufferMap request_buffers;
static Glib::Threads::Private<RequestBuffer> per_thread_request_buffer;
-
+
Glib::Threads::Mutex request_list_lock;
std::list<RequestObject*> request_list;
-
+
RequestObject* get_request (RequestType);
void handle_ui_requests ();
void send_request (RequestObject *);
{
return g_atomic_int_dec_and_test (&m_value);
}
-
+
bool operator-- ()
{
return decrement_and_test ();
std::string name() const { return _name; }
bool ok() const { return _ok; }
-
+
static RequestType new_request_type();
static RequestType CallSlot;
static RequestType Quit;
virtual ~Command() { /* NOTE: derived classes must call drop_references() */ }
virtual void operator() () = 0;
-
+
void set_name (const std::string& str) { _name = str; }
const std::string& name() const { return _name; }
virtual void undo() = 0;
virtual void redo() { (*this)(); }
-
+
virtual XMLNode &get_state();
virtual int set_state(const XMLNode&, int /*version*/) { /* noop */ return 0; }
}
++arg_no;
-
+
return *this;
}
else if (is_number(fmt[i + 1])) { // aha! a spec!
// save string
output.push_back(fmt.substr(b, i - b));
-
+
int n = 1; // number of digits
int spec_no = 0;
spec_no /= 10;
output_list::iterator pos = output.end();
--pos; // safe since we have just inserted a string>
-
+
specs.insert(specification_map::value_type(spec_no, pos));
-
+
// jump over spec string
i += n;
b = i;
static PBD::Signal1<void,PBD::Controllable*> StopLearning;
static PBD::Signal1<void,Controllable*> Destroyed;
-
+
PBD::Signal0<void> Changed;
int set_state (const XMLNode&, int version);
*/
CrossThreadChannel(bool non_blocking);
~CrossThreadChannel();
-
+
/** Tell the listening thread that is has work to do.
*/
void wakeup();
-
+
/* if the listening thread cares about the precise message
* it is being sent, then ::deliver() can be used to send
* a single byte message rather than a simple wakeup. These
/** Call this to suspend malloc checking until a call to resume_rt_malloc_checks */
LIBPBD_API extern void suspend_rt_malloc_checks ();
-/** Resume malloc checking after a suspension */
+/** Resume malloc checking after a suspension */
LIBPBD_API extern void resume_rt_malloc_checks ();
}
public:
Destructible() {}
virtual ~Destructible () { Destroyed(); }
-
+
PBD::Signal0<void> Destroyed;
PBD::Signal0<void> DropReferences;
}
~unknown_enumeration () throw() {}
-
+
virtual const char *what() const throw() {
return _message.c_str();
}
private:
void clear () const;
-
+
bool _armed;
std::string _envname;
std::map<std::string,std::string> e;
x &= ~(255 << 23);
x += 127 << 23;
*exp_ptr = x;
-
+
val = ((-1.0f/3) * t.f + 2) * t.f - 2.0f/3;
-
+
return (val + log_2);
}
static FPU* instance();
static void destroy();
-
+
bool has_flush_to_zero () const { return _flags & HasFlushToZero; }
bool has_denormals_are_zero () const { return _flags & HasDenormalsAreZero; }
bool has_sse () const { return _flags & HasSSE; }
bool has_sse2 () const { return _flags & HasSSE2; }
bool has_avx () const { return _flags & HasAVX; }
-
+
private:
Flags _flags;
virtual XMLNode &get_state() {
std::stringstream ss;
-
+
XMLNode *node = new XMLNode("FunctorCommand");
node->add_property("type_name", typeid(obj_type).name());
node->add_property("functor", functor_name);
void print (char* buf, uint32_t bufsize) const;
std::string to_s() const;
-
+
static uint64_t counter() { return _counter; }
static void init_counter (uint64_t val) { _counter = val; }
static void init ();
{
public:
MD5();
-
+
// an MD5 digest is a 16-byte number (32 hex digits)
uint8_t digestRaw[16] ;
-
+
// This version of the digest is actually
// a "printf'd" version of the digest.
char digestChars[33] ;
-
+
void writeToString ();
char* digestFile (char *filename);
char* digestMemory (uint8_t const * memchunk, size_t len);
};
context_t context;
-
+
void Init ();
void Transform (uint32_t state[4], uint8_t const * block);
void Encode (uint8_t *output, uint32_t const *input, size_t len);
void Decode (uint32_t *output, uint8_t const * input, size_t len);
void Update (uint8_t const *input, size_t inputLen);
void Final ();
-
+
};
#endif /* __libpbd_md5_h__ */
void add_state (XMLNode* node) {
node->add_property ("obj_id", _object.id().to_s());
}
-
+
void object_died () {
/* The object we are binding died, so drop references to ourselves */
this->drop_references ();
/* The binder's object died, so we must die */
_binder->DropReferences.connect_same_thread (_binder_death_connection, boost::bind (&MementoCommand::binder_dying, this));
}
-
+
~MementoCommand () {
drop_references ();
delete before;
XMLNode* node = new XMLNode(name);
_binder->add_state (node);
-
+
node->add_property ("type_name", _binder->type_name ());
if (before) {
node->add_child_copy(*before);
}
-
+
if (after) {
node->add_child_copy(*after);
}
virtual void *alloc ();
virtual void release (void *);
-
+
std::string name() const { return _name; }
guint available() const { return free_list.read_space(); }
guint used() const { return free_list.bufsize() - available(); }
guint total() const { return free_list.bufsize(); }
-
+
protected:
RingBuffer<void*> free_list; ///< a list of pointers to free items within block
std::string _name;
/* MANAGEMENT OF Stateful State */
-
+
bool set_value (XMLNode const & node) {
XMLProperty const* p = node.property (property_name());
node.add_property (property_name(), to_string (_current));
}
-
+
/* MANAGEMENT OF HISTORY */
-
+
void clear_changes () {
_have_old = false;
}
/* TRANSFERRING HISTORY TO / FROM A StatefulDiffCommand */
-
+
void get_changes_as_xml (XMLNode* history_node) const {
XMLNode* node = history_node->add_child (property_name());
node->add_property ("from", to_string (_old));
Property<T>* clone () const {
return new Property<T> (this->property_id(), this->_old, this->_current);
}
-
+
Property<T>* clone_from_xml (const XMLNode& node) const {
XMLNodeList const & children = node.children ();
XMLNodeList::const_iterator i = children.begin();
}
XMLProperty* from = (*i)->property ("from");
XMLProperty* to = (*i)->property ("to");
-
+
if (!from || !to) {
return 0;
}
-
+
return new Property<T> (this->property_id(), from_string (from->value()), from_string (to->value ()));
}
Property (PropertyDescriptor<std::string> d, std::string const & o, std::string const & c)
: PropertyTemplate<std::string> (d, o, c)
{}
-
+
Property<std::string>* clone () const {
return new Property<std::string> (this->property_id(), _old, _current);
}
{
public:
typedef boost::shared_ptr<T> Ptr;
-
+
SharedStatefulProperty (PropertyID d, Ptr p)
: PropertyBase (d)
, _current (p)
{
-
+
}
SharedStatefulProperty (PropertyID d, Ptr o, Ptr c)
, _old (o)
, _current (c)
{
-
+
}
bool set_value (XMLNode const & node) {
namespace PBD {
class LIBPBD_API PropertyList;
-class LIBPBD_API StatefulDiffCommand;
+class LIBPBD_API StatefulDiffCommand;
/** A unique identifier for a property of a Stateful object */
typedef GQuark PropertyID;
struct LIBPBD_TEMPLATE_API PropertyDescriptor {
PropertyDescriptor () : property_id (0) {}
PropertyDescriptor (PropertyID pid) : property_id (pid) {}
-
+
PropertyID property_id;
typedef T value_type;
};
/** Invert the changes in this property */
virtual void invert () = 0;
-
+
/* TRANSFERRING HISTORY TO / FROM A StatefulDiffCommand */
* StatefulDiffCommand node.
*/
virtual void get_changes_as_xml (XMLNode *) const = 0;
-
+
/** If this Property has changed, clone it and add it to a given list.
* Used for making StatefulDiffCommands.
*/
/* VARIOUS */
-
+
virtual PropertyBase* clone () const = 0;
/** Set this property's current state from another */
return _property_id == pid;
}
-protected:
+protected:
/* copy construction only by subclasses */
PropertyBase (PropertyBase const & b)
: _property_id (b._property_id)
{}
-
+
private:
PropertyID _property_id;
namespace PBD {
-/** A list of properties, mapped using their ID */
+/** A list of properties, mapped using their ID */
class LIBPBD_API PropertyList : public std::map<PropertyID, PropertyBase*>
{
public:
public:
Receiver ();
virtual ~Receiver ();
-
+
void listen_to (Transmitter &);
void hangup ();
buf = new T[size];
reset ();
}
-
+
virtual ~RingBuffer() {
delete [] buf;
}
g_atomic_int_set (&write_idx, w);
g_atomic_int_set (&read_idx, r);
}
-
+
guint read (T *dest, guint cnt);
guint write (T const * src, guint cnt);
void get_read_vector (rw_vector *);
void get_write_vector (rw_vector *);
-
+
void decrement_read_idx (guint cnt) {
g_atomic_int_set (&read_idx, (g_atomic_int_get(&read_idx) - cnt) & size_mask);
}
guint write_space () const {
guint w, r;
-
+
w = g_atomic_int_get (&write_idx);
r = g_atomic_int_get (&read_idx);
-
+
if (w > r) {
return ((r - w + size) & size_mask) - 1;
} else if (w < r) {
return size - 1;
}
}
-
+
guint read_space () const {
guint w, r;
-
+
w = g_atomic_int_get (&write_idx);
r = g_atomic_int_get (&read_idx);
-
+
if (w > r) {
return w - r;
} else {
guint free_cnt;
guint cnt2;
guint w, r;
-
+
w = g_atomic_int_get (&write_idx);
r = g_atomic_int_get (&read_idx);
-
+
if (w > r) {
free_cnt = w - r;
} else {
vec->len[1] = cnt2 & size_mask;
} else {
-
+
/* Single part vector: just the rest of the buffer */
-
+
vec->buf[0] = &buf[r];
vec->len[0] = free_cnt;
vec->buf[1] = 0;
guint free_cnt;
guint cnt2;
guint w, r;
-
+
w = g_atomic_int_get (&write_idx);
r = g_atomic_int_get (&read_idx);
-
+
if (w > r) {
free_cnt = ((r - w + size) & size_mask) - 1;
} else if (w < r) {
} else {
free_cnt = size - 1;
}
-
+
cnt2 = w + free_cnt;
if (cnt2 > size) {
-
+
/* Two part vector: the rest of the buffer after the
current write ptr, plus some from the start of
the buffer.
buf = new T[size];
reset ();
}
-
+
virtual ~RingBufferNPT () {
delete [] buf;
}
g_atomic_int_set (&write_ptr, w);
g_atomic_int_set (&read_ptr, r);
}
-
+
size_t read (T *dest, size_t cnt);
size_t write (const T *src, size_t cnt);
void get_read_vector (rw_vector *);
void get_write_vector (rw_vector *);
-
+
void decrement_read_ptr (size_t cnt) {
g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) % size);
}
size_t write_space () {
size_t w, r;
-
+
w = g_atomic_int_get (&write_ptr);
r = g_atomic_int_get (&read_ptr);
-
+
if (w > r) {
return ((r - w + size) % size) - 1;
} else if (w < r) {
return size - 1;
}
}
-
+
size_t read_space () {
size_t w, r;
-
+
w = g_atomic_int_get (&write_ptr);
r = g_atomic_int_get (&read_ptr);
-
+
if (w > r) {
return w - r;
} else {
size_t free_cnt;
size_t cnt2;
size_t w, r;
-
+
w = g_atomic_int_get (&write_ptr);
r = g_atomic_int_get (&read_ptr);
-
+
if (w > r) {
free_cnt = w - r;
} else {
vec->len[1] = cnt2 % size;
} else {
-
+
/* Single part vector: just the rest of the buffer */
-
+
vec->buf[0] = &buf[r];
vec->len[0] = free_cnt;
vec->buf[1] = 0;
size_t free_cnt;
size_t cnt2;
size_t w, r;
-
+
w = g_atomic_int_get (&write_ptr);
r = g_atomic_int_get (&read_ptr);
-
+
if (w > r) {
free_cnt = ((r - w + size) % size) - 1;
} else if (w < r) {
} else {
free_cnt = size - 1;
}
-
+
cnt2 = w + free_cnt;
if (cnt2 > size) {
-
+
/* Two part vector: the rest of the buffer after the
current write ptr, plus some from the start of
the buffer.
* Add another directory path to the search path.
*/
LIBPBD_TEMPLATE_MEMBER_API Searchpath& operator+= (const std::string& directory_path);
-
+
/**
* Concatenate another Searchpath onto this.
*/
LIBPBD_TEMPLATE_MEMBER_API const Searchpath operator+ (const Searchpath& other);
-
+
/**
* Add another path to the search path.
*/
fromPath,
fromFILE
};
-
+
bool _ok;
int _type;
std::string path;
void multithreaded (bool yn) {
use_list_lock = yn;
}
-
+
void add (int condition, Selectable *s);
void remove (Selectable *);
int select (unsigned long usecs);
bool changed () const {
return !_changes.added.empty() || !_changes.removed.empty();
}
-
+
void clear_changes () {
_changes.added.clear ();
_changes.removed.clear ();
if (!changed ()) {
return;
}
-
+
/* Create a property with just the changes and not the actual values */
SequenceProperty<Container>* a = create ();
a->_changes = _changes;
changes.add (a);
-
+
if (cmd) {
/* whenever one of the items emits DropReferences, make sure
that the Destructible we've been told to notify hears about
XMLNodeList const children = node.children ();
/* find the node for this property name */
-
+
std::string const c = capitalize (property_name ());
XMLNodeList::const_iterator i = children.begin();
while (i != children.end() && (*i)->name() != c) {
}
/* create a property with the changes */
-
+
SequenceProperty<Container>* p = create ();
XMLNodeList const & grandchildren = (*i)->children ();
}
_val.clear ();
}
-
+
typename Container::size_type size() const {
return _val.size();
}
, _changes (p._changes)
, _update_callback (p._update_callback)
{}
-
+
Container _val; ///< our actual container of things
ChangeRecord _changes; ///< changes to the container (adds/removes) that have happened since clear_changes() was last called
boost::function<void(const ChangeRecord&)> _update_callback;
-private:
+private:
virtual SequenceProperty<Container>* create () const = 0;
};
return r;
}
};
-
+
typedef boost::shared_ptr<Connection> UnscopedConnection;
-
+
class LIBPBD_API ScopedConnection
{
public:
if (_c == o) {
return *this;
}
-
+
disconnect ();
_c = o;
return *this;
private:
UnscopedConnection _c;
};
-
+
class LIBPBD_API ScopedConnectionList : public boost::noncopyable
{
public:
ScopedConnectionList();
virtual ~ScopedConnectionList ();
-
+
void add_connection (const UnscopedConnection& c);
void drop_connections ();
(1) (unlikely) we make a connection involving a callback on the
same object from 2 threads. (wouldn't that just be appalling
programming style?)
-
+
(2) where we are dropping connections in one thread and adding
one from another.
*/
ConnectionList _list;
};
-#include "pbd/signals_generated.h"
-
+#include "pbd/signals_generated.h"
+
} /* namespace */
#endif /* __pbd_signals_h__ */
for (x = all.begin(); x != all.end(); ++x) {
char **strings;
size_t i;
-
+
strings = backtrace_symbols ((*x)->allocation_backtrace, (*x)->allocation_backtrace_size);
-
+
if (strings) {
stream << "--- ALLOCATED SHARED_PTR @ " << (*x) << std::endl;
for (i = 0; i < (*x)->allocation_backtrace_size && i < 50U; i++) {
virtual bool apply_changes (PropertyBase const &);
PropertyChange apply_changes (PropertyList const &);
-
+
const OwnedPropertyList& properties() const { return *_properties; }
void add_property (PropertyBase& s);
void add_properties (XMLNode &);
PropertyChange set_values (XMLNode const &);
-
+
/* derived classes can implement this to do cross-checking
of property values after either a PropertyList or XML
driven property change.
namespace PBD
{
-class StatefulDestructible;
+class StatefulDestructible;
class PropertyList;
/** A Command which stores its action as the differences between the before and after
template<class T> /*LIBPBD_API*/ void vector_delete (std::vector<T *> *vec)
{
typename std::vector<T *>::iterator i;
-
+
for (i = vec->begin(); i != vec->end(); i++) {
delete *i;
}
template<class T> void /*LIBPBD_API*/ set_delete (std::set<T *> *sset)
{
typename std::set<T *>::iterator i;
-
+
for (i = sset->begin(); i != sset->end(); i++) {
delete *i;
}
void touch () {
(object.*method)();
}
-
+
protected:
T& object;
void (T::*method)(void);
void touch () {
(object.*method)(arg);
}
-
+
protected:
T1& object;
void (T1::*method)(T2);
void touch () {
(object.*method)(arg1, arg2);
}
-
+
protected:
T1& object;
void (T1::*method)(T2,T3);
T2 arg1;
T3 arg2;
};
-
+
#endif // __pbd_touchable_h__
/* hmm. not a Transmitter, so just put a newline on
it and assume that that will be enough.
*/
-
+
ostr << std::endl;
}
bool _clearing;
friend void command_death (UndoTransaction*, Command *);
-
+
void about_to_explicitly_delete ();
};
public:
UndoHistory();
~UndoHistory() {}
-
+
void add (UndoTransaction* ut);
void undo (unsigned int n);
void redo (unsigned int n);
-
+
unsigned long undo_depth() const { return UndoList.size(); }
unsigned long redo_depth() const { return RedoList.size(); }
-
+
std::string next_undo() const { return (UndoList.empty() ? std::string() : UndoList.back()->name()); }
std::string next_redo() const { return (RedoList.empty() ? std::string() : RedoList.back()->name()); }
PBD::Signal0<void> Changed;
PBD::Signal0<void> BeginUndoRedo;
PBD::Signal0<void> EndUndoRedo;
-
+
private:
bool _clearing;
uint32_t _depth;
public:
Unwinder (T& var, T new_val) : _var (var), _old_val (var) { var = new_val; }
~Unwinder () { _var = _old_val; }
-
+
private:
T& _var;
T _old_val;
private:
bool read_internal(bool validate);
-
+
std::string _filename;
XMLNode* _root;
xmlDocPtr _doc;
XMLProperty* property(const std::string&);
const XMLProperty* property(const char* n) const { return const_cast<XMLNode*>(this)->property(n); }
const XMLProperty* property(const std::string& n) const { return const_cast<XMLNode*>(this)->property(n); }
-
+
XMLProperty* add_property(const char* name, const std::string& value);
XMLProperty* add_property(const char* name, const char* value = "");
XMLProperty* add_property(const char* name, const long value);
}
/** Release an item's memory by writing its location to the free list */
-void
+void
Pool::release (void *ptr)
{
free_list.write (&ptr, 1);
PerThreadPool::add_to_trash (CrossThreadPool* p)
{
Glib::Threads::Mutex::Lock lm (_trash_mutex);
-
+
if (!_trash) {
warning << "Pool " << p->name() << " has no trash collector; a memory leak has therefore occurred" << endmsg;
return;
/* we have a lock here so that multiple threads can safely call add_to_trash (even though there
can only be one writer to the _trash RingBuffer)
*/
-
+
_trash->write (&p, 1);
}
, pending (nitems)
, _parent (p)
{
-
+
}
void
{
void* ptr;
bool did_release = false;
-
+
DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 has %3 pending free entries waiting, status size %4 free %5 used %6\n", pthread_name(), name(), pending.read_space(),
total(), available(), used()));
-
+
while (pending.read (&ptr, 1) == 1) {
DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 pushes back a pending free list entry before allocating\n", pthread_name(), name()));
free_list.write (&ptr, 1);
PropertyList::PropertyList()
: _property_owner (true)
{
-
+
}
PropertyList::PropertyList (PropertyList const & other)
pthread_set_name (const char *str)
{
/* copy string and delete it when exiting */
-
+
thread_name.set (strdup (str));
}
void
pthread_kill_all (int signum)
-{
+{
pthread_mutex_lock (&thread_map_lock);
for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
if (!pthread_equal ((*i), pthread_self())) {
void
pthread_cancel_all ()
-{
+{
pthread_mutex_lock (&thread_map_lock);
for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ) {
void
pthread_cancel_one (pthread_t thread)
-{
+{
pthread_mutex_lock (&thread_map_lock);
for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
if (pthread_equal ((*i), thread)) {
// the search path rather than replace?
*i = Glib::build_filename (*i, subdir);
}
-
+
return *this;
}
}
/* this semaphore does not exist for IPC */
-
+
if (sem_unlink (name)) {
throw failed_constructor ();
}
return path;
}
}
-
+
uint32_t so_far = (len - last_sep);
uint32_t space_for = target_characters - so_far;
res += path.substr (last_sep - space_for, len - last_sep + space_for - 3);
res += "...";
return res;
-
+
}
}
int status;
try {
-
+
char* realname = abi::__cxa_demangle (l.c_str(), 0, 0, &status);
std::string d (realname);
free (realname);
return d;
} catch (std::exception) {
-
+
}
return l;
if ((p - b) <= 1) {
return symbol_demangle (l);
}
-
+
std::string const fn = l.substr (b + 1, p - b - 1);
return symbol_demangle (fn);
strings = backtrace_symbols (array, size);
if (strings) {
-
+
for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
out << " " << demangle (strings[i]) << std::endl;
}
-
+
free (strings);
}
} else {
to by _extra_xml if a new Extra node is found, but not
otherwise.
*/
-
+
const XMLNode* xtra = node.child ("Extra");
if (xtra) {
_instant_xml->add_child_copy (node);
std::string instant_xml_path = Glib::build_filename (directory_path, "instant.xml");
-
+
XMLTree tree;
tree.set_filename(instant_xml_path);
Stateful::get_changes_as_properties (Command* cmd) const
{
PropertyList* pl = new PropertyList;
-
+
for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) {
i->second->get_changes_as_properties (*pl, cmd);
}
Stateful::set_values (XMLNode const & node)
{
PropertyChange c;
-
+
for (OwnedPropertyList::iterator i = _properties->begin(); i != _properties->end(); ++i) {
if (i->second->set_value (node)) {
c.add (i->first);
for (PropertyList::const_iterator pp = property_list.begin(); pp != property_list.end(); ++pp) {
DEBUG_TRACE (DEBUG::Stateful, string_compose ("in plist: %1\n", pp->second->property_name()));
}
-
+
for (PropertyList::const_iterator i = property_list.begin(); i != property_list.end(); ++i) {
if ((p = _properties->find (i->first)) != _properties->end()) {
DEBUG::Stateful,
string_compose ("actually setting property %1 using %2\n", p->second->property_name(), i->second->property_name())
);
-
+
if (apply_changes (*i->second)) {
c.add (i->first);
}
i->second->property_name()));
}
}
-
+
post_set (c);
send_change (c);
void
split (string str, vector<string>& result, char splitchar)
-{
+{
string::size_type pos;
string remaining;
string::size_type len = str.length();
void
split (ustring str, vector<ustring>& result, char splitchar)
-{
+{
ustring::size_type pos;
ustring remaining;
ustring::size_type len = str.length();
/* if pid is non-zero, the child task is still executing (i.e. it did
* not exit in response to stdin being closed). try to kill it.
*/
-
+
if (pid) {
::kill(pid, SIGTERM);
::usleep(250000);
_fred.clear_changes ();
CPPUNIT_ASSERT (_fred.changed() == false);
-
+
_fred = 5;
CPPUNIT_ASSERT (_fred == 5);
CPPUNIT_ASSERT (_fred.changed() == true);
void testBasic ();
static void make_property_quarks ();
-
+
private:
PBD::Property<int> _fred;
};
void emit () {
Fred ();
}
-
+
PBD::Signal0<void> Fred;
};
e->emit ();
delete r;
e->emit ();
-
+
CPPUNIT_ASSERT_EQUAL (1, N);
}
text_receiver.listen_to (PBD::warning);
ScalarPropertiesTest::make_property_quarks ();
-
+
CppUnit::TestResult testresult;
CppUnit::TestResultCollector collectedresults;
testresult.addListener (&collectedresults);
-
+
CppUnit::BriefTestProgressListener progress;
testresult.addListener (&progress);
-
+
CppUnit::TestRunner testrunner;
testrunner.addTest (CppUnit::TestFactoryRegistry::getRegistry ().makeTest ());
testrunner.run (testresult);
-
+
CppUnit::CompilerOutputter compileroutputter (&collectedresults, std::cerr);
compileroutputter.write ();
XMLTree doc(testdata_path);
// "//bank" gives as last element an empty element libxml bug????
boost::shared_ptr<XMLSharedNodeList> result = doc.find("//bank[@name]");
-
+
// cout << "Found " << result->size() << " banks" << endl;
assert(result->size() == 8);
// int counter = 1;
// " with name: " << (*j)->property("name")->value() << endl;
}
}
-
+
// cout << endl << endl << "Test 2: RosegardenPatchFile.xml: Find all programs whose program name contains 'Latin'" << endl;
-
+
result = doc.find("/rosegarden-data/studio/device/bank/program[contains(@name, 'Latin')]");
assert(result->size() == 5);
-
+
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
// cout << "\t found program " << (*i)->property("id")->value() <<
// " with name: " << (*i)->property("name")->value() << endl;
}
// cout << endl << endl << "Test 3: TestSession.ardour: find all Sources where captured-for contains the string 'Guitar'" << endl;
-
+
// We have to allocate a new document here, or we get segfaults
std::string testsession_path;
CPPUNIT_ASSERT (find_file (test_search_path (), "TestSession.ardour", testsession_path));
XMLTree doc2(testsession_path);
result = doc2.find("/Session/Sources/Source[contains(@captured-for, 'Guitar')]");
assert(result->size() == 16);
-
+
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
// cout << "\t found source '" << (*i)->property("name")->value() <<
// "' with id: " << (*i)->property("id")->value() << endl;
}
-
+
// cout << endl << endl << "Test 4: TestSession.ardour: Find all elements with an 'id' and 'name' attribute" << endl;
-
+
result = doc2.find("//*[@id and @name]");
-
+
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
assert((*i)->property("id"));
assert((*i)->property("name"));
// "' with id: " << (*i)->property("id")->value() <<
// "' and name: " << (*i)->property("name")->value() << endl;
}
-
+
// cout << endl << endl << "Test 5: ProtoolsPatchFile.midnam: Get Banks and Patches for 'Name Set 1'" << endl;
-
+
std::string testmidnam_path;
CPPUNIT_ASSERT (find_file (test_search_path (), "ProtoolsPatchFile.midnam", testmidnam_path));
XMLTree doc3(testmidnam_path);
result = doc3.find("/MIDINameDocument/MasterDeviceNames/ChannelNameSet[@Name='Name Set 1']/PatchBank");
assert(result->size() == 16);
-
+
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
// cout << "\t found Patchbank " << (*i)->property("Name")->value() << endl;
boost::shared_ptr<XMLSharedNodeList> patches = doc3.find ("//Patch[@Name]", i->get());
// cout << endl << endl << "Test 5: ProtoolsPatchFile.midnam: Find attribute nodes" << endl;
result = doc3.find("//@Value");
-
+
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
boost::shared_ptr<XMLNode> node = (*i);
// cout << "\t found attribute node: " << node->name()
// << " value: " << node->attribute_value() << endl;
- }
-
+ }
+
// cout << endl << endl << "Test 6: ProtoolsPatchFile.midnam: Find available channels on 'Name Set 1'" << endl;
result = doc3.find(
"//ChannelNameSet[@Name = 'Name Set 1']//AvailableChannel[@Available = 'true']/@Channel");
-
+
assert(result->size() == 15);
for(XMLSharedNodeList::const_iterator i = result->begin(); i != result->end(); ++i) {
boost::shared_ptr<XMLNode> node = (*i);
// cout << "\t found available Channel: " << node->name()
// << " value: " << node->attribute_value() << endl;
- }
-
+ }
+
}
/* note: iostreams are already thread-safe: no external
lock required.
*/
-
+
cout << name << prefix << str << endl;
if (chn == Transmitter::Fatal) {
send = 0;
break;
}
-}
+}
void
Transmitter::deliver ()
seekg (0, ios::beg);
/* do the right thing if this should not return */
-
+
if (does_not_return()) {
#ifndef PLATFORM_WINDOWS
// TODO !!!! Commented out temporarily (for Windows)
sigset_t mask;
-
+
sigemptyset (&mask);
sigsuspend (&mask);
/*NOTREACHED*/
{
UndoRedoSignaller exception_safe_signaller (*this);
-
+
while (n--) {
if (RedoList.size() == 0) {
return;
using namespace std;
namespace PBD {
-
+
void
strip_whitespace_edges (string& str)
{
string::size_type i;
string::size_type len;
string::size_type s = 0;
-
+
len = str.length();
if (len == 1) {
}
/* strip front */
-
+
for (i = 0; i < len; ++i) {
if (!isspace (str[i])) {
break;
if (s == i) {
return;
}
-
+
do {
if (!isspace (str[i]) || i == 0) {
break;
--i;
} while (true);
-
+
str = str.substr (s, (i - s) + 1);
} else {
HRESULT hr;
LPITEMIDLIST pidl = 0;
char *utf8_folder_path = 0;
-
+
if (S_OK == (hr = SHGetSpecialFolderLocation (0, csidl, &pidl))) {
if (SHGetPathFromIDListW (pidl, path)) {
, _doc (xmlCopyDoc (from->_doc, 1))
, _compression(from->compression())
{
-
+
}
XMLTree::~XMLTree()
} else {
_doc = xmlParseFile(_filename.c_str());
}
-
+
/* check if parsing suceeded */
if (_doc == NULL) {
if (validate) {
if (validate) {
xmlFreeParserCtxt(ctxt);
}
-
+
return true;
}
XMLPropertyIterator curprop;
XMLNodeList nodes;
XMLNodeIterator curnode;
-
+
clear_lists ();
_name = from.name();
set_content(from.content());
-
+
props = from.properties();
for (curprop = props.begin(); curprop != props.end(); ++curprop) {
add_property((*curprop)->name().c_str(), (*curprop)->value());
}
-
+
nodes = from.children();
for (curnode = nodes.begin(); curnode != nodes.end(); ++curnode) {
add_child_copy(**curnode);
} else {
ctxt = xmlXPathNewContext(_doc);
}
-
+
boost::shared_ptr<XMLSharedNodeList> result =
boost::shared_ptr<XMLSharedNodeList>(find_impl(ctxt, xpath));
-
+
xmlXPathFreeContext(ctxt);
if (doc) {
xmlFreeDoc (doc);
{
string ns(n);
map<string,XMLProperty*>::iterator iter;
-
+
if ((iter = _propmap.find(ns)) != _propmap.end()) {
iter->second->set_value (v);
return iter->second;
s << " " << (*i)->name() << "=\"" << (*i)->value() << "\"";
}
s << ">\n";
-
+
for (XMLNodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) {
(*i)->dump (s, p + " ");
}
-
+
s << p << "</" << _name << ">\n";
}
}
break;
}
}
-
+
wavnumber = 0;
i+=16;
while (i < len && numberofwavs > 0) {
for (i = 0; i < n; ++i) mult[i] = 1.0;
switch (m_type) {
-
+
case RectangularWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * 0.5;
}
break;
-
+
case BartlettWindow:
for (i = 0; i < n/2; ++i) {
mult[i] = mult[i] * (i / T(n/2));
mult[i + n/2] = mult[i + n/2] * (1.0 - (i / T(n/2)));
}
break;
-
+
case HammingWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * (0.54 - 0.46 * cos(2 * M_PI * i / n));
}
break;
-
+
case HanningWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * (0.50 - 0.50 * cos(2 * M_PI * i / n));
}
break;
-
+
case BlackmanWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * (0.42 - 0.50 * cos(2 * M_PI * i / n)
+ 0.08 * cos(4 * M_PI * i / n));
}
break;
-
+
case GaussianWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * exp((-1.0 / (n*n)) * ((T(2*i) - n) *
(T(2*i) - n)));
}
break;
-
+
case ParzenWindow:
for (i = 0; i < n; ++i) {
mult[i] = mult[i] * (1.0 - fabs((T(2*i) - n) / T(n + 1)));
}
break;
}
-
+
m_cache = mult;
}
}
int Chromagram::initialise( ChromaConfig Config )
-{
+{
m_FMin = Config.min; // min freq
m_FMax = Config.max; // max freq
m_BPO = Config.BPO; // bins per octave
m_normalise = Config.normalise; // if frame normalisation is required
// No. of constant Q bins
- m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
+ m_uK = ( unsigned int ) ceil( m_BPO * log(m_FMax/m_FMin)/log(2.0));
// Create array for chroma result
m_chromadata = new double[ m_BPO ];
ConstantQConfig.max = m_FMax;
ConstantQConfig.BPO = m_BPO;
ConstantQConfig.CQThresh = Config.CQThresh;
-
+
// Initialise ConstantQ operator
m_ConstantQ = new ConstantQ( ConstantQConfig );
m_frameSize = m_ConstantQ->getfftlength();
m_hopSize = m_ConstantQ->gethop();
- // Initialise FFT object
+ // Initialise FFT object
m_FFT = new FFTReal(m_frameSize);
m_FFTRe = new double[ m_frameSize ];
// Calculate ConstantQ frame
m_ConstantQ->process( real, imag, m_CQRe, m_CQIm );
-
+
// add each octave of cq data into Chromagram
const unsigned octaves = (int)floor(double( m_uK/m_BPO))-1;
for (unsigned octave = 0; octave <= octaves; octave++)
class Chromagram
{
-public:
+public:
Chromagram( ChromaConfig Config );
~Chromagram();
-
+
double* process( const double *data ); // time domain
double* process( const double *real, const double *imag ); // frequency domain
void unityNormalise( double* src );
// Complex arithmetic
double kabs( double real, double imag );
-
+
// Results
unsigned int getK() { return m_uK;}
unsigned int getFrameSize() { return m_frameSize; }
Window<double> *m_window;
double *m_windowbuf;
-
+
double* m_chromadata;
double m_FMin;
double m_FMax;
sk->js.reserve( m_FFTLength*2 );
sk->real.reserve( m_FFTLength*2 );
sk->imag.reserve( m_FFTLength*2 );
-
+
// for each bin value K, calculate temporal kernel, take its fft to
//calculate the spectral kernel then threshold it to make it sparse and
//add it to the sparse kernels matrix
double squareThreshold = m_CQThresh * m_CQThresh;
FFT m_FFT(m_FFTLength);
-
+
for (unsigned k = m_uK; k--; )
{
for (unsigned u=0; u < m_FFTLength; u++)
//do fft of hammingWindow
m_FFT.process( 0, hammingWindowRe, hammingWindowIm, transfHammingWindowRe, transfHammingWindowIm );
-
+
for (unsigned j=0; j<( m_FFTLength ); j++)
{
// perform thresholding
const double squaredBin = squaredModule( transfHammingWindowRe[ j ], transfHammingWindowIm[ j ]);
if (squaredBin <= squareThreshold) continue;
-
+
// Insert non-zero position indexes, doubled because they are floats
sk->is.push_back(j);
sk->js.push_back(k);
const double *real = &(sk->real[0]);
const double *imag = &(sk->imag[0]);
const unsigned int sparseCells = sk->real.size();
-
+
for (unsigned i = 0; i<sparseCells; i++)
{
const unsigned row = cqbin[i];
const double *real = &(sk->real[0]);
const double *imag = &(sk->imag[0]);
const unsigned int sparseCells = sk->real.size();
-
+
for (unsigned i = 0; i<sparseCells; i++)
{
const unsigned row = cqbin[i];
};
class ConstantQ {
-
+
//public functions incl. sparsekernel so can keep out of loop in main
public:
void process( const double* FFTRe, const double* FFTIm,
double out = 0.54 - 0.46*cos(2*PI*n/len);
return(out);
}
-
+
int getnumwin() { return m_numWin;}
double getQ() { return m_dQ;}
int getK() {return m_uK ;}
private:
void initialise( CQConfig Config );
void deInitialise();
-
+
double* m_CQdata;
unsigned int m_FS;
double m_FMin;
m_magHistory = new double[ m_halfLength ];
memset(m_magHistory,0, m_halfLength*sizeof(double));
-
+
m_phaseHistory = new double[ m_halfLength ];
memset(m_phaseHistory,0, m_halfLength*sizeof(double));
case DF_HFC:
retVal = HFC( m_halfLength, m_magnitude);
break;
-
+
case DF_SPECDIFF:
retVal = specDiff( m_halfLength, m_magnitude);
break;
-
+
case DF_PHASEDEV:
retVal = phaseDev( m_halfLength, m_thetaAngle);
break;
-
+
case DF_COMPLEXSD:
retVal = complexSD( m_halfLength, m_magnitude, m_thetaAngle);
break;
retVal = broadband( m_halfLength, m_magnitude);
break;
}
-
+
return retVal;
}
for( i = 0; i < length; i++)
{
temp = fabs( (src[ i ] * src[ i ]) - (m_magHistory[ i ] * m_magHistory[ i ]) );
-
+
diff= sqrt(temp);
// (See note in phaseDev below.)
// does significantly damage its ability to work with quieter
// music, so I'm removing it and counting the result always.
// Same goes for the spectral difference measure above.
-
+
tmpVal = fabs(dev);
val += tmpVal ;
m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
m_phaseHistory[ i ] = srcPhase[ i ];
}
-
-
+
+
return val;
}
{
tmpPhase = (srcPhase[ i ]- 2*m_phaseHistory[ i ]+m_phaseHistoryOld[ i ]);
dev= MathUtilities::princarg( tmpPhase );
-
+
meas = m_magHistory[i] - ( srcMagnitude[ i ] * exp( j * dev) );
tmpReal = real( meas );
tmpImag = imag( meas );
val += sqrt( (tmpReal * tmpReal) + (tmpImag * tmpImag) );
-
+
m_phaseHistoryOld[ i ] = m_phaseHistory[ i ] ;
m_phaseHistory[ i ] = srcPhase[ i ];
m_magHistory[ i ] = srcMagnitude[ i ];
double phaseDev(unsigned int length, double *srcPhase);
double complexSD(unsigned int length, double *srcMagnitude, double *srcPhase);
double broadband(unsigned int length, double *srcMagnitude);
-
+
private:
void initialise( DFConfig Config );
void deInitialise();
Qfilta = Config.QuadThresh.a ;
Qfiltb = Config.QuadThresh.b ;
Qfiltc = Config.QuadThresh.c ;
-
+
m_DFProcessingParams.length = m_DFLength;
m_DFProcessingParams.LPOrd = Config.LPOrd;
m_DFProcessingParams.LPACoeffs = Config.LPACoeffs;
m_DFProcessingParams.winPost = Config.WinT.post;
m_DFProcessingParams.AlphaNormParam = Config.alpha;
m_DFProcessingParams.isMedianPositive = false;
-
+
m_DFSmoothing = new DFProcess( m_DFProcessingParams );
m_workBuffer = new double[ m_DFLength ];
{
if (len < 4) return;
- vector <double> m_maxima;
+ vector <double> m_maxima;
// Signal conditioning
m_DFSmoothing->process( src, m_workBuffer );
-
+
for( unsigned int u = 0; u < len; u++)
{
- m_maxima.push_back( m_workBuffer[ u ] );
+ m_maxima.push_back( m_workBuffer[ u ] );
}
-
+
quadEval( m_maxima, onsets );
for(unsigned int b = 0; b < m_maxima.size(); b++)
vector <int> m_maxIndex;
vector <int> m_onsetPosition;
-
+
vector <double> m_maxFit;
vector <double> m_poly;
vector <double> m_err;
for (int k = -2; k <= 2; ++k)
{
selMax = src[ m_maxIndex[j] + k ] ;
- m_maxFit.push_back(selMax);
+ m_maxFit.push_back(selMax);
}
double f = m_poly[0];
{
idx.push_back(m_maxIndex[j]);
}
-
+
m_maxFit.clear();
}
public:
PeakPicking( PPickParams Config );
virtual ~PeakPicking();
-
+
void process( double* src, unsigned int len, vector<int> &onsets );
void initialise( PPickParams Config );
void deInitialise();
int quadEval( vector<double> &src, vector<int> &idx );
-
+
DFProcConfig m_DFProcessingParams;
unsigned int m_DFLength ;
double* m_workBuffer;
-
+
DFProcess* m_DFSmoothing;
};
void PhaseVocoder::process(double *src, double *mag, double *theta)
{
FFTShift( m_n, src);
-
+
m_fft->process(0, src, m_realOut, m_imagOut);
getMagnitude( m_n/2, mag, m_realOut, m_imagOut);
}
void PhaseVocoder::getMagnitude(unsigned int size, double *mag, double *real, double *imag)
-{
+{
unsigned int j;
for( j = 0; j < size; j++)
for( k = 0; k < size; k++)
{
theta[ k ] = atan2( -imag[ k ], real[ k ]);
- }
+ }
}
double a[ 9 ];
double b[ 9 ];
-
+
double* decBuffer;
};
fft->process(false, frame, real, imag);
constq->process(real, imag, cqre, cqim);
-
+
for (int i = 0; i < ncoeff; ++i) {
cq[i] += sqrt(cqre[i] * cqre[i] + cqim[i] * cqim[i]);
}
}
mfcc->process(frame, ccout);
-
+
for (int i = 0; i < ncoeff; ++i) {
cc[i] += ccout[i];
}
<< " features with " << features[0].size() << " coefficients (ncoeff = " << ncoeff << ", ncomponents = " << ncomponents << ")" << std::endl;
*/
// copy the features to a native array and use the existing C segmenter...
- double** arrFeatures = new double*[features.size()];
+ double** arrFeatures = new double*[features.size()];
for (int i = 0; i < features.size(); i++)
{
if (featureType == FEATURE_TYPE_UNKNOWN) {
arrFeatures[i] = new double[features[0].size()];
for (int j = 0; j < features[0].size(); j++)
- arrFeatures[i][j] = features[i][j];
+ arrFeatures[i][j] = features[i][j];
} else {
arrFeatures[i] = new double[ncoeff+1]; // allow space for the normalised envelope
for (int j = 0; j < ncoeff; j++)
- arrFeatures[i][j] = features[i][j];
+ arrFeatures[i][j] = features[i][j];
}
}
-
+
q = new int[features.size()];
-
+
if (featureType == FEATURE_TYPE_UNKNOWN ||
featureType == FEATURE_TYPE_MFCC)
cluster_segment(q, arrFeatures, features.size(), features[0].size(), nHMMStates, histogramLength,
else
constq_segment(q, arrFeatures, features.size(), nbins, ncoeff, featureType,
nHMMStates, histogramLength, nclusters, neighbourhoodLimit);
-
+
// convert the cluster assignment sequence to a segmentation
- makeSegmentation(q, features.size());
-
+ makeSegmentation(q, features.size());
+
// de-allocate arrays
delete [] q;
for (int i = 0; i < features.size(); i++)
delete [] arrFeatures[i];
delete [] arrFeatures;
-
+
// clear the features
clear();
}
segmentation.segments.clear();
segmentation.nsegtypes = nclusters;
segmentation.samplerate = samplerate;
-
+
Segment segment;
segment.start = 0;
segment.type = q[0];
-
+
for (int i = 1; i < len; i++)
{
if (q[i] != q[i-1])
protected:
void makeSegmentation(int* q, int len);
-
+
void extractFeaturesConstQ(const double *, int);
void extractFeaturesMFCC(const double *, int);
MFCC* mfcc;
model_t* model; // the HMM
int* q; // the decoded HMM state sequence
- vector<vector<double> > histograms;
+ vector<vector<double> > histograms;
- feature_types featureType;
+ feature_types featureType;
double hopSize; // in seconds
double windowSize; // in seconds
ostream& operator<<(ostream& os, const Segmentation& s)
{
os << "structure_name : begin_time end_time\n";
-
+
for (int i = 0; i < s.segments.size(); i++)
{
Segment seg = s.segments[i];
os << std::fixed << seg.type << ':' << '\t' << std::setprecision(6) << seg.start / static_cast<double>(s.samplerate)
<< '\t' << std::setprecision(6) << seg.end / static_cast<double>(s.samplerate) << "\n";
}
-
+
return os;
}
public:
int nsegtypes; // number of segment types, so possible types are {0,1,...,nsegtypes-1}
int samplerate;
- vector<Segment> segments;
+ vector<Segment> segments;
};
ostream& operator<<(ostream& os, const Segmentation& s);
because a, b represent probability distributions */
double q, d;
int i;
-
+
d = 0;
for (i = 0; i < n; i++)
{
d += b[i] * log(b[i] / q);
}
}
- return d;
-}
+ return d;
+}
void cluster_melt(double *h, int m, int n, double *Bsched, int t, int k, int l, int *c) {
double lambda, sum, beta, logsumexp, maxlp;
int** nc; /* neighbour counts for each histogram */
double** lp; /* soft assignment probs for each histogram */
int* oldc; /* previous hard assignments (to check convergence) */
-
+
/* NB h is passed as a 1d row major array */
-
+
/* parameter values */
lambda = DEFAULT_LAMBDA;
if (l > 0)
B = 2 * limit + 1;
maxiter0 = 20; /* number of iterations at initial temperature */
maxiter1 = 5; /* number of iterations at subsequent temperatures */
-
- /* allocate memory */
+
+ /* allocate memory */
cl = (double**) malloc(k*sizeof(double*));
for (i= 0; i < k; i++)
cl[i] = (double*) malloc(m*sizeof(double));
-
+
nc = (int**) malloc(n*sizeof(int*));
for (i= 0; i < n; i++)
nc[i] = (int*) malloc(k*sizeof(int));
-
+
lp = (double**) malloc(n*sizeof(double*));
for (i= 0; i < n; i++)
lp[i] = (double*) malloc(k*sizeof(double));
-
+
oldc = (int*) malloc(n * sizeof(int));
-
+
/* initialise */
for (i = 0; i < k; i++)
{
{
cl[i][j] /= sum; /* normalise */
}
- }
+ }
//print_array(cl, k, m);
-
+
for (i = 0; i < n; i++)
c[i] = 1; /* initially assign all histograms to cluster 1 */
-
+
for (a = 0; a < t; a++)
{
beta = Bsched[a];
-
+
if (a == 0)
maxiter = maxiter0;
else
maxiter = maxiter1;
-
+
for (it = 0; it < maxiter; it++)
{
//if (it == maxiter - 1)
// mexPrintf("hasn't converged after %d iterations\n", maxiter);
-
+
for (i = 0; i < n; i++)
{
/* save current hard assignments */
oldc[i] = c[i];
-
+
/* calculate soft assignment logprobs for each cluster */
sum = 0;
for (j = 0; j < k; j++)
{
lp[i][ j] = -beta * kldist(cl[j], &h[i*m], m);
-
+
/* update matching neighbour counts for this histogram, based on current hard assignments */
/* old version:
- nc[i][j] = 0;
+ nc[i][j] = 0;
if (i >= limit && i <= n - 1 - limit)
{
for (b = i - limit; b <= i + limit; b++)
for (b = b0; b <= b1; b++)
if (c[b] == j+1)
nc[i][j]--;
-
+
sum += exp(lp[i][j]);
}
-
+
/* normalise responsibilities and add duration logprior */
logsumexp = log(sum);
for (j = 0; j < k; j++)
- lp[i][j] -= logsumexp + lambda * nc[i][j];
+ lp[i][j] -= logsumexp + lambda * nc[i][j];
}
//print_array(lp, n, k);
/*
mexPrintf("\n");
}
*/
-
-
+
+
/* update the assignments now that we know the duration priors
based on the current assignments */
for (i = 0; i < n; i++)
c[i] = j+1;
}
}
-
+
/* break if assignments haven't changed */
i = 0;
while (i < n && oldc[i] == c[i])
i++;
if (i == n)
break;
-
+
/* update reference histograms now we know new responsibilities */
for (j = 0; j < k; j++)
{
for (i = 0; i < n; i++)
{
cl[j][b] += exp(lp[i][j]) * h[i*m+b];
- }
+ }
}
-
- sum = 0;
+
+ sum = 0;
for (i = 0; i < n; i++)
sum += exp(lp[i][j]);
for (b = 0; b < m; b++)
cl[j][b] /= sum; /* normalise */
- }
-
+ }
+
//print_array(cl, k, m);
//mexPrintf("\n\n");
}
}
-
+
/* free memory */
for (i = 0; i < k; i++)
free(cl[i]);
for (i = 0; i < n; i++)
free(lp[i]);
free(lp);
- free(oldc);
+ free(oldc);
}
int t, b, oct, ix;
//double maxchroma; /* max chroma value at each time, for normalisation */
//double sum; /* for normalisation */
-
+
for (t = 0; t < nframes; t++)
{
for (b = 0; b < bins; b++)
maxchroma = chroma[t][b];
if (maxchroma > 0)
for (b = 0; b < bins; b++)
- chroma[t][b] /= maxchroma;
+ chroma[t][b] /= maxchroma;
*/
}
}
double ss;
double env;
double maxenv = 0;
-
+
/* convert const-Q features to dB scale */
for (i = 0; i < nframes; i++)
for (j = 0; j < ncoeff; j++)
features[i][j] = 10.0 * log10(features[i][j]+DBL_EPSILON);
-
- /* normalise each feature vector and add the norm as an extra feature dimension */
+
+ /* normalise each feature vector and add the norm as an extra feature dimension */
for (i = 0; i < nframes; i++)
{
ss = 0;
}
/* normalise the envelopes */
for (i = 0; i < nframes; i++)
- features[i][ncoeff] /= maxenv;
+ features[i][ncoeff] /= maxenv;
}
/* return histograms h[nx*m] of data x[nx] into m bins using a sliding window of length h_len (MUST BE ODD) */
for (j = 0; j < m; j++)
h[i*m+j] /= norm;
}
-
+
/* duplicate histograms at beginning and end to create one histogram for each data value supplied */
for (i = 0; i < hlen/2; i++)
for (j = 0; j < m; j++)
int histogram_length, int nclusters, int neighbour_limit)
{
int i, j;
-
+
/*****************************/
if (0) {
/* try just using the predominant bin number as a 'decoded state' */
{
maxval = features[i][j];
maxbin = j;
- }
+ }
}
if (maxval > chroma_thresh)
q[i] = maxbin;
else
q[i] = feature_length;
}
-
+
}
if (1) {
/*****************************/
-
-
+
+
/* scale all the features to 'balance covariances' during HMM training */
double scale = 10;
for (i = 0; i < frames_read; i++)
for (j = 0; j < feature_length; j++)
features[i][j] *= scale;
-
+
/* train an HMM on the features */
-
+
/* create a model */
model_t* model = hmm_init(features, frames_read, feature_length, nHMM_states);
-
+
/* train the model */
hmm_train(features, frames_read, model);
-/*
+/*
printf("\n\nafter training:\n");
hmm_print(model);
-*/
+*/
/* decode the hidden state sequence */
viterbi_decode(features, frames_read, model, q);
hmm_close(model);
-
+
/*****************************/
}
/*****************************/
-
+
/*
fprintf(stderr, "HMM state sequence:\n");
fprintf(stderr, "%d ", q[i]);
fprintf(stderr, "\n\n");
*/
-
+
/* create histograms of states */
double* h = (double*) malloc(frames_read*nHMM_states*sizeof(double)); /* vector in row major order */
create_histograms(q, frames_read, nHMM_states, histogram_length, h);
-
+
/* cluster the histograms */
int nbsched = 20; /* length of inverse temperature schedule */
double* bsched = (double*) malloc(nbsched*sizeof(double)); /* inverse temperature schedule */
for (i = 1; i < nbsched; i++)
bsched[i] = alpha * bsched[i-1];
cluster_melt(h, nHMM_states, frames_read, bsched, nbsched, nclusters, neighbour_limit, q);
-
+
/* now q holds a sequence of cluster assignments */
-
+
free(h);
free(bsched);
}
int feature_length;
double** chroma;
int i;
-
+
if (feature_type == FEATURE_TYPE_CONSTQ)
{
/* fprintf(stderr, "Converting to dB and normalising...\n");
- */
+ */
mpeg7_constq(features, frames_read, ncoeff);
-/*
+/*
fprintf(stderr, "Running PCA...\n");
-*/
+*/
/* do PCA on the features (but not the envelope) */
int ncomponents = 20;
pca_project(features, frames_read, ncoeff, ncomponents);
-
+
/* copy the envelope so that it immediatly follows the chosen components */
for (i = 0; i < frames_read; i++)
- features[i][ncomponents] = features[i][ncoeff];
-
+ features[i][ncomponents] = features[i][ncoeff];
+
feature_length = ncomponents + 1;
-
+
/**************************************
//TEST
// feature file name
strcpy(file_name, dir);
strcat(file_name, trackname);
strcat(file_name, "_features_c20r8h0.2f0.6.mat");
-
+
// get the features from Matlab from mat-file
int frames_in_file;
readmatarray_size(file_name, 2, &frames_in_file, &feature_length);
features[frames_read-missing_frames][i] = features[frames_read-missing_frames-1][i];
--missing_frames;
}
-
+
free(file_name);
******************************************/
-
+
cluster_segment(q, features, frames_read, feature_length, nHMM_states, histogram_length, nclusters, neighbour_limit);
}
-
+
if (feature_type == FEATURE_TYPE_CHROMA)
{
/*
fprintf(stderr, "Converting to chroma features...\n");
-*/
+*/
/* convert constant-Q to normalised chroma features */
chroma = (double**) malloc(frames_read*sizeof(double*));
for (i = 0; i < frames_read; i++)
chroma[i] = (double*) malloc(bins*sizeof(double));
cq2chroma(features, frames_read, ncoeff, bins, chroma);
feature_length = bins;
-
+
cluster_segment(q, chroma, frames_read, feature_length, nHMM_states, histogram_length, nclusters, neighbour_limit);
-
+
for (i = 0; i < frames_read; i++)
free(chroma[i]);
free(chroma);
DFProcess::DFProcess( DFProcConfig Config )
{
filtSrc = NULL;
- filtDst = NULL;
+ filtDst = NULL;
m_filtScratchIn = NULL;
m_filtScratchOut = NULL;
filtSrc = new double[ m_length ];
filtDst = new double[ m_length ];
-
+
//Low Pass Smoothing Filter Config
m_FilterConfigParams.ord = Config.LPOrd;
m_FilterConfigParams.ACoeffs = Config.LPACoeffs;
m_FilterConfigParams.BCoeffs = Config.LPBCoeffs;
-
- m_FiltFilt = new FiltFilt( m_FilterConfigParams );
+
+ m_FiltFilt = new FiltFilt( m_FilterConfigParams );
}
void DFProcess::deInitialise()
{
if (index >= m_length) break;
-
+
l = 0;
for( j = i; j < ( i + m_winPost + m_winPre + 1); j++)
{
l++;
}
-
+
scratch[ index++ ] = MathUtilities::median( y, l);
}
for( i = 0; i < m_length; i++ )
{
val = src[ i ] - scratch[ i ];// - 0.033;
-
+
if( m_isMedianPositive )
{
if( val > 0 )
dst[ i ] = val;
}
}
-
+
delete [] y;
delete [] scratch;
}
void process( double* src, double* dst );
-
+
private:
void initialise( DFProcConfig Config );
void deInitialise();
m_filtScratchIn = NULL;
m_filtScratchOut = NULL;
m_ord = 0;
-
+
initialise( Config );
}
m_filterConfig.ord = Config.ord;
m_filterConfig.ACoeffs = Config.ACoeffs;
m_filterConfig.BCoeffs = Config.BCoeffs;
-
+
m_filter = new Filter( m_filterConfig );
}
void FiltFilt::process(double *src, double *dst, unsigned int length)
-{
+{
unsigned int i;
if (length == 0) return;
m_filtScratchIn = new double[ nExt ];
m_filtScratchOut = new double[ nExt ];
-
+
for( i = 0; i< nExt; i++ )
{
m_filtScratchIn[ i ] = 0.0;
{
m_filtScratchIn[ i + nFact ] = src[ i ];
}
-
+
////////////////////////////////
// Do 0Ph filtering
m_filter->process( m_filtScratchIn, m_filtScratchOut, nExt);
-
+
// reverse the series for FILTFILT
for ( i = 0; i < nExt; i++)
{
// do FILTER again
m_filter->process( m_filtScratchIn, m_filtScratchOut, nExt);
-
+
// reverse the series back
for ( i = 0; i < nExt; i++)
{
for( i = 0; i < length; i++ )
{
dst[ index++ ] = m_filtScratchOut[ i + nFact ];
- }
+ }
delete [] m_filtScratchIn;
delete [] m_filtScratchOut;
void reset();
void process( double *src, double *dst, unsigned int length );
-
+
private:
void initialise( FilterConfig Config );
if( m_dataFrame != NULL )
{
- delete [] m_dataFrame;
+ delete [] m_dataFrame;
m_dataFrame = NULL;
}
m_dataFrame = new double[ m_frameLength ];
if( m_strideFrame != NULL )
{
- delete [] m_strideFrame;
+ delete [] m_strideFrame;
m_strideFrame = NULL;
}
m_strideFrame = new double[ m_stepSize ];
for( unsigned int u = 0; u < m_frameLength; u++)
{
dst[ u ] = m_srcBuffer[ m_ulSrcIndex++ ];
- }
+ }
m_ulSrcIndex -= ( m_frameLength - m_stepSize );
}
else
{
dst[ u ] = m_srcBuffer[ m_ulSrcIndex++ ];
}
-
+
for( unsigned int u = 0; u < zero; u++ )
{
dst[ rem + u ] = 0;
}
// JENSEN-SHANNON CALCULATION
- sd1 = 0.5*oldspec[i] + 0.5*newspec[i];
+ sd1 = 0.5*oldspec[i] + 0.5*newspec[i];
SD = SD + (-sd1*log(sd1)) + (0.5*(oldspec[i]*log(oldspec[i]))) + (0.5*(newspec[i]*log(newspec[i])));
}
// now apply comb filtering
int numelem = 4;
-
+
for (unsigned int i = 2;i < rcf.size();i++) // max beat period
{
for (int a = 1;a <= numelem;a++) // number of comb elements
{
tmat.push_back ( d_vec_t() ); // adds a new column
for (unsigned int j=0; j<wv.size(); j++)
- {
+ {
tmat[i].push_back(0.); // fill with zeros initially
}
}
for (unsigned int i=20;i <wv.size()-20; i++)
{
for (unsigned int j=20; j<wv.size()-20; j++)
- {
+ {
double mu = static_cast<double>(i);
tmat[i][j] = exp( (-1.*pow((j-mu),2.)) / (2.*pow(sigma,2.)) );
}
delta.push_back( d_vec_t());
psi.push_back( i_vec_t());
for (unsigned int j=0; j<rcfmat[i].size(); j++)
- {
+ {
delta[i].push_back(0.); // fill with zeros initially
psi[i].push_back(0); // fill with zeros initially
}
void ChangeDetectionFunction::setFilterWidth(const int iWidth)
{
m_iFilterWidth = iWidth*2+1;
-
+
// it is assumed that the gaussian is 0 outside of +/- FWHM
// => filter width = 2*FWHM = 2*2.3548*sigma
m_dFilterSigma = double(m_iFilterWidth) / double(2*2.3548);
m_vaGaussian.resize(m_iFilterWidth);
-
+
double dScale = 1.0 / (m_dFilterSigma*sqrt(2*PI));
-
+
for (int x = -(m_iFilterWidth-1)/2; x <= (m_iFilterWidth-1)/2; x++)
{
double w = dScale * std::exp ( -(x*x)/(2*m_dFilterSigma*m_dFilterSigma) );
m_vaGaussian[x + (m_iFilterWidth-1)/2] = w;
}
-
+
#ifdef DEBUG_CHANGE_DETECTION_FUNCTION
std::cerr << "Filter sigma: " << m_dFilterSigma << std::endl;
std::cerr << "Filter width: " << m_iFilterWidth << std::endl;
{
ChangeDistance retVal;
retVal.resize(rTCSGram.getSize(), 0.0);
-
+
TCSGram smoothedTCSGram;
for (int iPosition = 0; iPosition < rTCSGram.getSize(); iPosition++)
{
int iSkipLower = 0;
-
+
int iLowerPos = iPosition - (m_iFilterWidth-1)/2;
int iUpperPos = iPosition + (m_iFilterWidth-1)/2;
-
+
if (iLowerPos < 0)
{
iSkipLower = -iLowerPos;
iLowerPos = 0;
}
-
+
if (iUpperPos >= rTCSGram.getSize())
{
int iMaxIndex = rTCSGram.getSize() - 1;
iUpperPos = iMaxIndex;
}
-
+
TCSVector smoothedVector;
// for every bin of the vector, calculate the smoothed value
for (int iPC = 0; iPC < 6; iPC++)
- {
+ {
size_t j = 0;
double dSmoothedValue = 0.0;
TCSVector rCV;
-
+
for (int i = iLowerPos; i <= iUpperPos; i++)
{
rTCSGram.getTCSVector(i, rCV);
smoothedVector[iPC] = dSmoothedValue;
}
-
+
smoothedTCSGram.addTCSVector(smoothedVector);
}
if the current estimate is not confident enough, look further into the future/the past
e.g., High frequency content, zero crossing rate, spectral flatness
*/
-
+
TCSVector nextTCS;
TCSVector previousTCS;
-
+
int iWindow = 1;
// while (previousTCS.magnitude() < 0.1 && (iPosition-iWindow) > 0)
// std::cout << previousTCS.magnitude() << std::endl;
iWindow++;
}
-
+
iWindow = 1;
-
+
// while (nextTCS.magnitude() < 0.1 && (iPosition+iWindow) < (rTCSGram.getSize()-1) )
{
smoothedTCSGram.getTCSVector(iPosition+iWindow, nextTCS);
{
distance += std::pow(nextTCS[j] - previousTCS[j], 2.0);
}
-
+
retVal[iPosition] = std::pow(distance, 0.5);
}
ChangeDistance process(const TCSGram& rTCSGram);
private:
void setFilterWidth(const int iWidth);
-
+
private:
valarray<double> m_vaGaussian;
double m_dFilterSigma;
std::pair<long, TCSVector> p;
p.first = lMilliSeconds;
p.second = rTCSVector;
-
+
m_VectorList.push_back(p);
}
void TCSGram::printDebug()
{
vectorlist_t::iterator vectorIterator = m_VectorList.begin();
-
+
while (vectorIterator != m_VectorList.end())
{
vectorIterator->second.printDebug();
class TCSGram
{
-public:
+public:
TCSGram();
~TCSGram();
void getTCSVector(int, TCSVector&) const;
m_Basis.resize(6);
int i = 0;
-
-
+
+
// circle of fifths
m_Basis[i].resize(12);
for (int iP = 0; iP < 12; iP++)
{
m_Basis[i][iP] = std::sin( (7.0 / 6.0) * iP * PI);
}
-
+
i++;
m_Basis[i].resize(12);
{
m_Basis[i][iP] = std::cos( (7.0 / 6.0) * iP * PI);
}
-
+
i++;
-
-
+
+
// circle of major thirds
m_Basis[i].resize(12);
for (int iP = 0; iP < 12; iP++)
{
m_Basis[i][iP] = 0.6 * std::sin( (2.0 / 3.0) * iP * PI);
}
-
+
i++;
m_Basis[i].resize(12);
{
m_Basis[i][iP] = 1.1 * std::sin( (3.0 / 2.0) * iP * PI);
}
-
+
i++;
m_Basis[i].resize(12);
{
TCSVector vaRetVal;
vaRetVal.resize(6, 0.0);
-
+
for (int i = 0; i < 6; i++)
{
for (int iP = 0; iP < 12; iP++)
vaRetVal[i] += m_Basis[i][iP] * rVector[iP];
}
}
-
+
return vaRetVal;
}
public:
ChromaVector(size_t uSize = 12) : std::valarray<double>()
{ resize(uSize, 0.0f); }
-
+
virtual ~ChromaVector() {};
-
+
void printDebug()
{
for (int i = 0; i < size(); i++)
{
std::cout << (*this)[i] << ";";
}
-
+
std::cout << std::endl;
}
-
+
void normalizeL1()
{
// normalize the chroma vector (L1 norm)
double dSum = 0.0;
-
+
for (size_t i = 0; i < 12; (dSum += std::abs((*this)[i++]))) ;
for (size_t i = 0; i < 12; dSum > 0.0000001?((*this)[i] /= dSum):(*this)[i]=0.0, i++) ;
for (size_t i = 0; i < 12; ++i) (*this)[i] = 0.0;
}
-
+
};
class TCSVector : public std::valarray<double>
public:
TCSVector() : std::valarray<double>()
{ resize(6, 0.0f); }
-
+
virtual ~TCSVector() {};
void printDebug()
{
std::cout << (*this)[i] << ";";
}
-
+
std::cout << std::endl;
}
-
+
double magnitude() const
{
double dMag = 0.0;
-
+
for (size_t i = 0; i < 6; i++)
{
dMag += std::pow((*this)[i], 2.0);
}
-
+
return std::sqrt(dMag);
}
}
static unsigned int numberOfBitsNeeded(unsigned int p_nSamples)
-{
+{
int i;
if( p_nSamples < 2 )
hpd.clear();
unsigned int flength = 0;
-
+
switch (wavelet) {
case Haar:
hpd.push_back(-0.22414386804186);
hpd.push_back(-0.12940952255092);
flength = 4;
- break;
+ break;
case Daubechies_3:
lpd.push_back(0.03522629188210);
hpd.push_back(-0.00000000000000);
flength = 80;
break;
-
+
case Symlet_2:
lpd.push_back(-0.12940952255092);
lpd.push_back(0.22414386804186);
hpd.push_back(0.01540410932703);
flength = 12;
break;
-
+
case Symlet_7:
lpd.push_back(0.00268181456826);
lpd.push_back(-0.00104738488868);
{
int i, j, d, e, t;
double s, ss;
-
+
model_t* model;
model = (model_t*) malloc(sizeof(model_t));
model->N = N;
- model->L = L;
+ model->L = L;
model->p0 = (double*) malloc(N*sizeof(double));
model->a = (double**) malloc(N*sizeof(double*));
model->mu = (double**) malloc(N*sizeof(double*));
model->cov = (double**) malloc(L*sizeof(double*));
for (i = 0; i < L; i++)
model->cov[i] = (double*) malloc(L*sizeof(double));
-
+
srand(time(0));
double* global_mean = (double*) malloc(L*sizeof(double));
-
+
/* find global mean */
for (d = 0; d < L; d++)
{
global_mean[d] += x[t][d];
global_mean[d] /= T;
}
-
+
/* calculate global diagonal covariance */
for (d = 0; d < L; d++)
{
model->cov[d][d] += (x[t][d] - global_mean[d]) * (x[t][d] - global_mean[d]);
model->cov[d][d] /= T-1;
}
-
+
/* set all means close to global mean */
for (i = 0; i < N; i++)
{
/* ideally the random number would be Gaussian(0,1), as a hack we make it uniform on [-0.25,0.25] */
model->mu[i][d] = global_mean[d] + (0.5 * rand() / (double) RAND_MAX - 0.25) * sqrt(model->cov[d][d]);
}
- }
-
+ }
+
/* random intial and transition probs */
s = 0;
for (i = 0; i < N; i++)
}
for (i = 0; i < N; i++)
model->p0[i] /= s;
-
+
free(global_mean);
-
+
return model;
}
void hmm_close(model_t* model)
{
int i;
-
+
for (i = 0; i < model->N; i++)
{
free(model->a[i]);
free(model->mu);
for (i = 0; i < model->L; i++)
free(model->cov[i]);
- free(model->cov);
- free(model);
+ free(model->cov);
+ free(model);
}
void hmm_train(double** x, int T, model_t* model)
{
int i, t;
double loglik; /* overall log-likelihood at each iteration */
-
+
int N = model->N;
int L = model->L;
double* p0 = model->p0;
double** a = model->a;
double** mu = model->mu;
double** cov = model->cov;
-
- /* allocate memory */
+
+ /* allocate memory */
double** gamma = (double**) malloc(T*sizeof(double*));
double*** xi = (double***) malloc(T*sizeof(double**));
for (t = 0; t < T; t++)
for (i = 0; i < N; i++)
xi[t][i] = (double*) malloc(N*sizeof(double));
}
-
+
/* temporary memory */
double* gauss_y = (double*) malloc(L*sizeof(double));
- double* gauss_z = (double*) malloc(L*sizeof(double));
-
+ double* gauss_z = (double*) malloc(L*sizeof(double));
+
/* obs probs P(j|{x}) */
double** b = (double**) malloc(T*sizeof(double*));
for (t = 0; t < T; t++)
b[t] = (double*) malloc(N*sizeof(double));
-
+
/* inverse covariance and its determinant */
double** icov = (double**) malloc(L*sizeof(double*));
for (i = 0; i < L; i++)
icov[i] = (double*) malloc(L*sizeof(double));
double detcov;
-
+
double thresh = 0.0001;
- int niter = 50;
+ int niter = 50;
int iter = 0;
double loglik1, loglik2;
int foundnan = 0;
- while (iter < niter && !foundnan && !(iter > 1 && (loglik - loglik1) < thresh * (loglik1 - loglik2)))
+ while (iter < niter && !foundnan && !(iter > 1 && (loglik - loglik1) < thresh * (loglik1 - loglik2)))
{
++iter;
-/*
+/*
fprintf(stderr, "calculating obsprobs...\n");
fflush(stderr);
-*/
+*/
/* precalculate obs probs */
invert(cov, L, icov, &detcov);
-
+
for (t = 0; t < T; t++)
{
//int allzero = 1;
for (i = 0; i < N; i++)
{
b[t][i] = exp(loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z));
-
+
//if (b[t][i] != 0)
// allzero = 0;
}
}
*/
}
-/*
+/*
fprintf(stderr, "forwards-backwards...\n");
fflush(stderr);
-*/
+*/
forward_backwards(xi, gamma, &loglik, &loglik1, &loglik2, iter, N, T, p0, a, b);
-/*
- fprintf(stderr, "iteration %d: loglik = %f\n", iter, loglik);
+/*
+ fprintf(stderr, "iteration %d: loglik = %f\n", iter, loglik);
fprintf(stderr, "re-estimation...\n");
fflush(stderr);
*/
foundnan = 1;
continue;
}
-
+
baum_welch(p0, a, mu, cov, N, T, L, x, xi, gamma);
-
+
/*
printf("a:\n");
for (i = 0; i < model->N; i++)
*/
//hmm_print(model);
}
-
+
/* deallocate memory */
for (t = 0; t < T; t++)
{
}
free(gamma);
free(xi);
- free(b);
-
+ free(b);
+
for (i = 0; i < L; i++)
free(icov[i]);
free(icov);
-
+
free(gauss_y);
free(gauss_z);
}
void mlss_reestimate(double* p0, double** a, double** mu, double** cov, int N, int T, int L, int* q, double** x)
{
/* fit a single Gaussian to observations in each state */
-
+
/* calculate the mean observation in each state */
-
+
/* calculate the overall covariance */
-
+
/* count transitions */
-
+
/* estimate initial probs from transitions (???) */
}
void baum_welch(double* p0, double** a, double** mu, double** cov, int N, int T, int L, double** x, double*** xi, double** gamma)
{
int i, j, t;
-
+
double* sum_gamma = (double*) malloc(N*sizeof(double));
-
+
/* temporary memory */
double* u = (double*) malloc(L*L*sizeof(double));
double* yy = (double*) malloc(T*L*sizeof(double));
- double* yy2 = (double*) malloc(T*L*sizeof(double));
-
+ double* yy2 = (double*) malloc(T*L*sizeof(double));
+
/* re-estimate transition probs */
for (i = 0; i < N; i++)
{
for (t = 0; t < T-1; t++)
sum_gamma[i] += gamma[t][i];
}
-
+
for (i = 0; i < N; i++)
{
if (sum_gamma[i] == 0)
for (t = 0; t < T-1; t++)
a[i][j] += xi[t][i][j];
//s += a[i][j];
- a[i][j] /= sum_gamma[i];
+ a[i][j] /= sum_gamma[i];
}
/*
for (j = 0; j < N; j++)
}
*/
}
-
+
/* NB: now we need to sum gamma over all t */
for (i = 0; i < N; i++)
sum_gamma[i] += gamma[T-1][i];
-
+
/* re-estimate initial probs */
for (i = 0; i < N; i++)
p0[i] = gamma[0][i];
-
+
/* re-estimate covariance */
int d, e;
double sum_sum_gamma = 0;
for (i = 0; i < N; i++)
- sum_sum_gamma += sum_gamma[i];
-
+ sum_sum_gamma += sum_gamma[i];
+
/*
for (d = 0; d < L; d++)
{
for (t = 0; t < T; t++)
for (j = 0; j < N; j++)
cov[d][e] += gamma[t][j] * (x[t][d] - mu[j][d]) * (x[t][e] - mu[j][e]);
-
+
cov[d][e] /= sum_sum_gamma;
-
+
if (ISNAN(cov[d][e]))
{
printf("cov[%d][%d] was nan\n", d, e);
for (e = 0; e < d; e++)
cov[d][e] = cov[e][d];
*/
-
+
/* using BLAS */
for (d = 0; d < L; d++)
for (e = 0; e < L; e++)
cov[d][e] = 0;
-
+
for (j = 0; j < N; j++)
{
for (d = 0; d < L; d++)
yy[d*T+t] = x[t][d] - mu[j][d];
yy2[d*T+t] = gamma[t][j] * (x[t][d] - mu[j][d]);
}
-
+
cblas_dgemm(CblasColMajor, CblasTrans, CblasNoTrans, L, L, T, 1.0, yy, T, yy2, T, 0, u, L);
-
+
for (e = 0; e < L; e++)
for (d = 0; d < L; d++)
cov[d][e] += u[e*L+d];
}
-
+
for (d = 0; d < L; d++)
for (e = 0; e < L; e++)
- cov[d][e] /= T; /* sum_sum_gamma; */
-
+ cov[d][e] /= T; /* sum_sum_gamma; */
+
//printf("sum_sum_gamma = %f\n", sum_sum_gamma); /* fine, = T IS THIS ALWAYS TRUE with pooled cov?? */
-
+
/* re-estimate means */
for (j = 0; j < N; j++)
{
mu[j][d] /= sum_gamma[j];
}
}
-
+
/* deallocate memory */
free(sum_gamma);
free(yy);
{
/* forwards-backwards with scaling */
int i, j, t;
-
+
double** alpha = (double**) malloc(T*sizeof(double*));
double** beta = (double**) malloc(T*sizeof(double*));
for (t = 0; t < T; t++)
alpha[t] = (double*) malloc(N*sizeof(double));
beta[t] = (double*) malloc(N*sizeof(double));
}
-
+
/* scaling coefficients */
double* c = (double*) malloc(T*sizeof(double));
-
+
/* calculate forward probs and scale coefficients */
c[0] = 0;
for (i = 0; i < N; i++)
{
alpha[0][i] = p0[i] * b[0][i];
c[0] += alpha[0][i];
-
+
//printf("p0[%d] = %f, b[0][%d] = %f\n", i, p0[i], i, b[0][i]);
}
c[0] = 1 / c[0];
for (i = 0; i < N; i++)
{
- alpha[0][i] *= c[0];
-
+ alpha[0][i] *= c[0];
+
//printf("alpha[0][%d] = %f\n", i, alpha[0][i]); /* OK agrees with Matlab */
}
-
+
*loglik1 = *loglik;
*loglik = -log(c[0]);
if (iter == 2)
*loglik2 = *loglik;
-
+
for (t = 1; t < T; t++)
- {
+ {
c[t] = 0;
for (j = 0; j < N; j++)
{
for (i = 0; i < N; i++)
alpha[t][j] += alpha[t-1][i] * a[i][j];
alpha[t][j] *= b[t][j];
-
+
c[t] += alpha[t][j];
}
-
+
/*
if (c[t] == 0)
{
exit(-1);
}
*/
-
+
c[t] = 1 / c[t];
for (j = 0; j < N; j++)
alpha[t][j] *= c[t];
-
+
//printf("c[%d] = %e\n", t, c[t]);
-
+
*loglik -= log(c[t]);
}
-
+
/* calculate backwards probs using same coefficients */
for (i = 0; i < N; i++)
beta[T-1][i] = 1;
{
for (i = 0; i < N; i++)
beta[t][i] *= c[t];
-
+
if (t == 0)
break;
-
+
for (i = 0; i < N; i++)
{
beta[t-1][i] = 0;
for (j = 0; j < N; j++)
beta[t-1][i] += a[i][j] * b[t][j] * beta[t][j];
}
-
+
t--;
}
-
+
/*
printf("alpha:\n");
for (t = 0; t < T; t++)
}
printf("\n\n");
*/
-
+
/* calculate posterior probs */
double tot;
for (t = 0; t < T; t++)
}
for (i = 0; i < N; i++)
{
- gamma[t][i] /= tot;
-
- //printf("gamma[%d][%d] = %f\n", t, i, gamma[t][i]);
+ gamma[t][i] /= tot;
+
+ //printf("gamma[%d][%d] = %f\n", t, i, gamma[t][i]);
}
- }
-
+ }
+
for (t = 0; t < T-1; t++)
{
tot = 0;
for (j = 0; j < N; j++)
xi[t][i][j] /= tot;
}
-
+
/*
// CHECK - fine
// gamma[t][i] = \sum_j{xi[t][i][j]}
for (j = 0; j < N; j++)
tot += xi[3][1][j];
printf("gamma[3][1] = %f, sum_j(xi[3][1][j]) = %f\n", gamma[3][1], tot);
- */
-
+ */
+
for (t = 0; t < T; t++)
{
free(alpha[t]);
int i, j, t;
double max;
int havemax;
-
+
int N = model->N;
int L = model->L;
double* p0 = model->p0;
double** a = model->a;
double** mu = model->mu;
double** cov = model->cov;
-
+
/* inverse covariance and its determinant */
double** icov = (double**) malloc(L*sizeof(double*));
for (i = 0; i < L; i++)
icov[i] = (double*) malloc(L*sizeof(double));
double detcov;
-
+
double** logb = (double**) malloc(T*sizeof(double*));
double** phi = (double**) malloc(T*sizeof(double*));
int** psi = (int**) malloc(T*sizeof(int*));
phi[t] = (double*) malloc(N*sizeof(double));
psi[t] = (int*) malloc(N*sizeof(int));
}
-
+
/* temporary memory */
double* gauss_y = (double*) malloc(L*sizeof(double));
- double* gauss_z = (double*) malloc(L*sizeof(double));
-
+ double* gauss_z = (double*) malloc(L*sizeof(double));
+
/* calculate observation logprobs */
invert(cov, L, icov, &detcov);
for (t = 0; t < T; t++)
for (i = 0; i < N; i++)
logb[t][i] = loggauss(x[t], L, mu[i], icov, detcov, gauss_y, gauss_z);
-
+
/* initialise */
for (i = 0; i < N; i++)
{
phi[0][i] = log(p0[i]) + logb[0][i];
psi[0][i] = 0;
}
-
+
for (t = 1; t < T; t++)
{
for (j = 0; j < N; j++)
}
}
}
-
+
/* find maximising state at time T-1 */
max = phi[T-1][0];
q[T-1] = 0;
}
}
-
+
/* track back */
t = T - 2;
while (t >= 0)
q[t] = psi[t+1][q[t+1]];
t--;
}
-
+
/* de-allocate memory */
for (i = 0; i < L; i++)
free(icov[i]);
free(logb);
free(phi);
free(psi);
-
+
free(gauss_y);
free(gauss_z);
}
for(j=0; j < L; j++)
for (i=0; i < L; i++)
a[j*L+i] = cov[i][j];
-
- int M = (int) L;
+
+ int M = (int) L;
int* ipiv = (int *) malloc(L*L*sizeof(int));
int ret;
-
+
/* LU decomposition */
ret = dgetrf_(&M, &M, a, &M, ipiv, &ret); /* ret should be zero, negative if cov is singular */
if (ret < 0)
fprintf(stderr, "Covariance matrix was singular, couldn't invert\n");
exit(-1);
}
-
+
/* find determinant */
double det = 1;
for(i = 0; i < L; i++)
if (det < 0)
det = -det;
*detcov = det;
-
+
/* allocate required working storage */
#ifndef HAVE_ATLAS
int lwork = -1;
double lwbest = 0.0;
dgetri_(&M, a, &M, ipiv, &lwbest, &lwork, &ret);
- lwork = (int) lwbest;
+ lwork = (int) lwbest;
double* work = (double*) malloc(lwork*sizeof(double));
#endif
-
+
/* find inverse */
dgetri_(&M, a, &M, ipiv, work, &lwork, &ret);
for(j=0; j < L; j++)
for (i=0; i < L; i++)
- icov[i][j] = a[j*L+i];
-
-#ifndef HAVE_ATLAS
+ icov[i][j] = a[j*L+i];
+
+#ifndef HAVE_ATLAS
free(work);
#endif
- free(a);
+ free(a);
}
/* probability of multivariate Gaussian given mean, inverse and determinant of covariance */
}
s = cblas_ddot(L, z, 1, y, 1);
//for (i = 0; i < L; i++)
- // s += z[i] * y[i];
-
+ // s += z[i] * y[i];
+
return exp(-s/2.0) / (pow(2*PI, L/2.0) * sqrt(detcov));
}
}
s = cblas_ddot(L, z, 1, y, 1);
//for (i = 0; i < L; i++)
- // s += z[i] * y[i];
-
+ // s += z[i] * y[i];
+
ret = -0.5 * (s + L * log(2*PI) + log(detcov));
-
+
/*
// TEST
if (ISINF(ret) > 0)
if (ISINF(ret) < 0)
printf("loggauss returning -infinity\n");
if (ISNAN(ret))
- printf("loggauss returning nan\n");
+ printf("loggauss returning nan\n");
*/
-
+
return ret;
}
unsigned int i;
double temp = 0.0;
double a=0.0;
-
+
for( i = 0; i < len; i++)
{
temp = data[ i ];
-
+
a += ::pow( fabs(temp), double(alpha) );
}
a /= ( double )len;
unsigned int len = data.size();
double temp = 0.0;
double a=0.0;
-
+
for( i = 0; i < len; i++)
{
temp = data[ i ];
-
+
a += ::pow( fabs(temp), double(alpha) );
}
a /= ( double )len;
double retVal =0.0;
double s = sum( src, len );
-
+
retVal = s / (double)len;
return retVal;
unsigned int count)
{
double sum = 0.;
-
+
for (unsigned int i = 0; i < count; ++i)
{
sum += src[start + i];
*min = *max = 0;
return;
}
-
+
*min = data[0];
*max = data[0];
{
*max = temp ;
}
-
+
}
}
unsigned int index = 0;
unsigned int i;
double temp = 0.0;
-
+
double max = pData[0];
for( i = 0; i < Length; i++)
max = temp ;
index = i;
}
-
+
}
if (pMax) *pMax = max;
unsigned int index = 0;
unsigned int i;
double temp = 0.0;
-
+
double max = data[0];
for( i = 0; i < data.size(); i++)
max = temp ;
index = i;
}
-
+
}
if (pMax) *pMax = max;
if (sz == 0) return;
std::vector<double> smoothed(sz);
-
+
int p_pre = 8;
int p_post = 7;
class MathUtilities
{
-public:
+public:
static double round( double x );
static void getFrameMinMax( const double* data, unsigned int len, double* min, double* max );
{
int l, k, j, i;
double scale, hh, h, g, f;
-
+
for (i = n-1; i >= 1; i--)
{
l = i - 1;
{
int m, l, iter, i, k;
double s, r, p, g, f, dd, c, b;
-
+
for (i = 1; i < n; i++)
e[i-1] = e[i];
e[n-1] = 0.0;
{
int i, j, k, k2;
double **symmat, **symmat2, *evals, *interm;
-
+
//TODO: assert ncomponents < m
-
+
symmat = (double**) malloc(m*sizeof(double*));
for (i = 0; i < m; i++)
symmat[i] = (double*) malloc(m*sizeof(double));
-
+
covcol(data, n, m, symmat);
-
+
/*********************************************************************
Eigen-reduction
**********************************************************************/
-
+
/* Allocate storage for dummy and new vectors. */
evals = (double*) malloc(m*sizeof(double)); /* Storage alloc. for vector of eigenvalues */
interm = (double*) malloc(m*sizeof(double)); /* Storage alloc. for 'intermediate' vector */
tred2(symmat, m, evals, interm); /* Triangular decomposition */
tqli(evals, interm, m, symmat); /* Reduction of sym. trid. matrix */
/* evals now contains the eigenvalues,
-columns of symmat now contain the associated eigenvectors. */
+columns of symmat now contain the associated eigenvectors. */
/*
printf("\nEigenvalues:\n");
printf("Eigenvalues are often expressed as cumulative\n");
printf("percentages, representing the 'percentage variance\n");
printf("explained' by the associated axis or principal component.)\n");
-
+
printf("\nEigenvectors:\n");
printf("(First three; their definition in terms of original vbes.)\n");
for (j = 0; j < m; j++) {
}
}
-/*
+/*
printf("\nProjections of row-points on first 3 prin. comps.:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < 3; j++) {
BasicUI::~BasicUI ()
{
-
+
}
void
if (session->get_play_range ()) {
session->request_play_range (0);
}
-
+
if (from_last_start && rolling) {
session->request_locate (session->last_transport_start(), true);
BasicUI::prev_marker ()
{
framepos_t pos = session->locations()->first_mark_before (session->transport_frame());
-
+
if (pos >= 0) {
session->request_locate (pos, session->transport_rolling());
} else {
if (momentary) {
_solo_release = new SoloMuteRelease (_route->soloed());
}
-
+
if (global) {
-
+
if (_solo_release) {
_solo_release->routes = _session->get_routes ();
}
-
+
if (Config->get_solo_control_is_listen_control()) {
_session->set_listen (_session->get_routes(), !_route->listening(), Session::rt_cleanup, true);
} else {
_session->set_solo (_session->get_routes(), !_route->soloed(), Session::rt_cleanup, true);
}
-
+
} else if (exclusive) {
-
+
if (_solo_release) {
_solo_release->exclusive = true;
-
+
boost::shared_ptr<RouteList> routes = _session->get_routes();
-
+
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
if ((*i)->soloed ()) {
_solo_release->routes_on->push_back (*i);
}
}
}
-
+
if (Config->get_solo_control_is_listen_control()) {
/* ??? we need a just_one_listen() method */
} else {
_session->set_just_one_solo (_route, true);
}
-
+
} else if (isolate) {
-
+
// shift-click: toggle solo isolated status
-
+
_route->set_solo_isolated (!_route->solo_isolated(), this);
delete _solo_release;
_solo_release = 0;
-
+
} else if (solo_group) {
-
+
/* Primary-button1: solo mix group.
NOTE: Primary-button2 is MIDI learn.
*/
-
+
if (_route->route_group()) {
-
+
if (_solo_release) {
_solo_release->routes = _route->route_group()->route_list();
}
-
+
if (Config->get_solo_control_is_listen_control()) {
_session->set_listen (_route->route_group()->route_list(), !_route->listening(), Session::rt_cleanup, true);
} else {
_session->set_solo (_route->route_group()->route_list(), !_route->soloed(), Session::rt_cleanup, true);
}
}
-
+
} else {
-
+
/* click: solo this route */
-
+
boost::shared_ptr<RouteList> rl (new RouteList);
rl->push_back (route());
-
+
if (_solo_release) {
_solo_release->routes = rl;
}
-
+
if (Config->get_solo_control_is_listen_control()) {
_session->set_listen (rl, !_route->listening());
} else {
if (table_index >= route_table.size()) {
return;
}
-
+
route_table[table_index] = r;
// XXX SHAREDPTR need to handle r->GoingAway
}
boost::shared_ptr<Route> r = route_table[table_index];
-
+
if (r != 0) {
r->set_gain (gain, this);
}
public:
BasicUI (ARDOUR::Session&);
virtual ~BasicUI ();
-
+
void add_marker (const std::string& = std::string());
void register_thread (std::string name);
respond. Typically this will always be GUI->"others" - the GUI pays
no attention to these signals.
*/
-
+
static PBD::Signal1<void,RouteNotificationListPtr> TrackSelectionChanged;
/* the model here is as follows:
bool (*probe)(ControlProtocolDescriptor*);
ControlProtocol* (*initialize)(ControlProtocolDescriptor*,Session*);
void (*destroy)(ControlProtocolDescriptor*,ControlProtocol*);
-
+
};
}
namespace ARDOUR {
class Route;
-
+
typedef std::vector<boost::weak_ptr<ARDOUR::Route> > RouteNotificationList;
typedef boost::shared_ptr<RouteNotificationList> RouteNotificationListPtr;
tranzport_t *open_tranzport()
{
-return open_tranzport_core();
+return open_tranzport_core();
}
void close_tranzport(tranzport_t *z)
{
uint8_t buf[8];
int val;
-
+
memset(buf, 0xff, 8);
val = read(z->udev, buf, 8);
if (val < 0) {
tranzport_t *open_tranzport()
{
-return open_tranzport_core();
+return open_tranzport_core();
}
void close_tranzport(tranzport_t *z)
{
uint8_t buf[8];
int val;
-
+
memset(buf, 0xff, 8);
val = read(z->udev, buf, 8);
if (val < 0) {
unsigned char LightPunch;
unsigned char last_cmd[8];
unsigned char screen[40]; // We'll also have cells
-
+
};
/* prevent races between open() and disconnect() */
/* Always pass one offline event up the stack */
if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; }
if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; }
-
+
#endif
dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail);
next_ring_head = (dev->ring_head+1) % ring_buffer_size;
-
+
if (next_ring_head != dev->ring_tail) {
memcpy(&((*dev->ring_buffer)[dev->ring_head]), dev->interrupt_in_buffer, urb->actual_length);
dev->ring_head = next_ring_head;
dbg_info(&dev->intf->dev, "%s: trying to compress: %02x%02x%02x%02x%02x %02x %02x %02x\n",
__FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
-
+
if(((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 &&
(*dev->ring_buffer)[next_tail].cmd[6] != 0 ) &&
((newwheel > 0 && oldwheel > 0) ||
retval = -EFAULT;
goto unlock_exit;
}
-
+
dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
c+=8;
dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail);
}
retval = c;
-
+
#else
if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) {
retval = -EFAULT;
tranzport_t *open_tranzport()
{
-return open_tranzport_core();
+return open_tranzport_core();
}
void close_tranzport(tranzport_t *z)
{
uint8_t buf[8];
int val;
-
+
memset(buf, 0xff, 8);
val = read(z->udev, buf, 8);
if (val < 0) {
}
return tcp;
-
+
}
void
initialize : new_tranzport_protocol,
destroy : delete_tranzport_protocol
};
-
+
extern "C" {
ControlProtocolDescriptor*
printf("usb screen update failed for some reason... why? \ncmd and data were %02x %02x %02x %02x %02x %02x %02x %02x\n",
cmd[0],cmd[1],cmd[2], cmd[3], cmd[4], cmd[5],cmd[6],cmd[7]);
#endif
- pending += 1;
+ pending += 1;
// Shouldn't need to do this
// screen_invalid[row][col_base] = screen_invalid[row][col_base+1] =
// screen_invalid[row][col_base+2] = screen_invalid[row][col_base+3] = true;
TranzportControlProtocol::show_transport_time ()
{
show_bbt (session->transport_frame ());
-}
+}
void
TranzportControlProtocol::show_smpte (framepos_t where)
error << _("Tranzport: cannot open USB transport") << endmsg;
return -1;
}
-
+
if (usb_claim_interface (udev, 0) < 0) {
error << _("Tranzport: cannot claim USB interface") << endmsg;
usb_close (udev);
return val;
}
-
+
int
TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
{
return 0;
-}
+}
int
TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
int val;
int retry = 0;
if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
-
+
while((val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout))!=8 && retry++ < MAX_RETRY) {
printf("usb_interrupt_write failed, retrying: %d\n", val);
}
return (write_noretry(cmd,timeout_override));
#endif
-}
+}
#else
#error Kernel API not defined yet for Tranzport
for(int r = 0; r < 2; r++) {
for(int c = 0; c < 20; c++) {
if(screen_invalid[r][c]) {
-#if DEBUG_TRANZPORT > 5
+#if DEBUG_TRANZPORT > 5
printf("row: %d,col: %d is damaged, should redraw it\n", r,c);
#endif
return true;
if((row >= 0 && row < 2) && (col >=0 && col < 20)) {
for(int c = col; c < endcol; c++) {
if(screen_invalid[row][c]) {
-#if DEBUG_TRANZPORT > 5
+#if DEBUG_TRANZPORT > 5
printf("row: %d,col: %d is damaged, should redraw it\n", row,c);
#endif
return true;
struct sched_param rtparam;
int err;
memset (&rtparam, 0, sizeof (rtparam));
- rtparam.sched_priority = priority;
+ rtparam.sched_priority = priority;
if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
PBD::info << string_compose (_("%1: can't stop realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
return 1;
if (gain_fraction > 2.0) {
gain_fraction = 2.0;
}
-
+
route_set_gain (0, slider_position_to_gain (gain_fraction));
}
if (gain_fraction < 0.0) {
gain_fraction = 0.0;
}
-
+
route_set_gain (0, slider_position_to_gain (gain_fraction));
}
uint32_t left = strlen (text);
char tmp[5];
int base_col;
-
+
if (row < 0 || row > 1) {
return;
}
int offset = col % 4;
/* copy current cell contents into tmp */
-
+
memcpy (tmp, &screen_pending[row][base_col], 4);
-
+
/* overwrite with new text */
-
+
uint32_t tocopy = min ((4U - offset), left);
-
+
memcpy (tmp+offset, text, tocopy);
-
+
/* copy it back to pending */
-
+
memcpy (&screen_pending[row][base_col], tmp, 4);
-
+
text += tocopy;
left -= tocopy;
col += tocopy;
}
-}
+}
XMLNode&
TranzportControlProtocol::get_state ()
WheelShiftMaster,
WheelShiftMarker
};
-
+
enum WheelMode {
WheelTimeline,
WheelScrub,
WheelIncrSecond,
WheelIncrMinute
};
-
+
enum DisplayMode {
DisplayNormal,
DisplayRecording,
BlingRows,
BlingFlashAll
};
-
+
pthread_t thread;
uint32_t buttonmask;
uint32_t timeout;
void show_current_track ();
void show_track_gain ();
void show_transport_time ();
- void show_bbt (framepos_t where);
+ void show_bbt (framepos_t where);
void show_smpte (framepos_t where);
void show_wheel_mode ();
void show_gain ();
mi.name = prop->value ();
mi.path = fullpath;
-
+
map_info.push_back (mi);
}
}
-
+
void
GenericMidiControlProtocol::drop_all ()
{
}
_send_feedback ();
-
+
last_feedback_time = now;
}
if (!lm.locked ()) {
return;
}
-
+
for (MIDIControllables::iterator r = controllables.begin(); r != controllables.end(); ++r) {
MIDI::byte* end = (*r)->write_feedback (buf, bsize);
if (end != buf) {
{
Glib::Threads::Mutex::Lock lm (pending_lock);
-
+
MIDIPendingControllables::iterator ptmp;
for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
ptmp = i;
if (!mc) {
mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
}
-
+
{
Glib::Threads::Mutex::Lock lm (pending_lock);
{
Glib::Threads::Mutex::Lock lm (pending_lock);
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
-
+
MIDIPendingControllables::iterator tmp;
for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ) {
break;
}
}
-
+
delete dptr;
}
{
if (control != 0) {
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
-
+
for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
MIDIControllable* existingBinding = (*iter);
-
+
if (control == (existingBinding->get_controllable())) {
delete existingBinding;
iter = controllables.erase (iter);
} else {
++iter;
}
-
+
}
}
}
{
if (control != NULL) {
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
-
+
MIDI::channel_t channel = (pos & 0xf);
MIDI::byte value = control_number;
-
+
// Create a MIDIControllable
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *control, false);
// Note: can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
for (MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end();) {
MIDIControllable* existingBinding = (*iter);
-
+
if ((existingBinding->get_control_channel() & 0xf ) == channel &&
existingBinding->get_control_additional() == value &&
(existingBinding->get_control_type() & 0xf0 ) == MIDI::controller) {
-
+
delete existingBinding;
iter = controllables.erase (iter);
} else {
++iter;
}
-
+
}
-
+
// Update the MIDI Controllable based on the the pos param
// Here is where a table lookup for user mappings could go; for now we'll just wing it...
mc->bind_midi(channel, MIDI::controller, value);
}
boost::shared_ptr<Controllable> c;
-
+
{
Glib::Threads::Mutex::Lock lm (pending_lock);
for (MIDIPendingControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
if (!nlist.empty()) {
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
+
if ((prop = (*niter)->property ("id")) != 0) {
-
+
ID id = prop->value ();
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Relearned binding for session: Control ID: %1\n", id.to_s()));
Controllable* c = Controllable::by_id (id);
-
+
if (c) {
MIDIControllable* mc = new MIDIControllable (this, *_input_port->parser(), *c, false);
-
+
if (mc->set_state (**niter, version) == 0) {
controllables.push_back (mc);
}
-
+
} else {
warning << string_compose (
_("Generic MIDI control: controllable %1 not found in session (ignored)"),
sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
Stateful::loading_state_version = (major * 1000) + minor;
}
-
+
const XMLNodeList& children (root->children());
XMLNodeConstIterator citer;
XMLNodeConstIterator gciter;
DEBUG_TRACE (DEBUG::GenericMidi, "Loading bindings\n");
for (citer = children.begin(); citer != children.end(); ++citer) {
-
+
if ((*citer)->name() == "DeviceInfo") {
const XMLProperty* prop;
if (child->property ("uri")) {
/* controllable */
-
+
if ((mc = create_binding (*child)) != 0) {
Glib::Threads::Mutex::Lock lm2 (controllables_lock);
controllables.push_back (mc);
}
}
}
-
+
if ((prop = root->property ("name")) != 0) {
_current_binding = prop->value ();
}
} else {
return 0;
}
-
+
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
-
+
detail = (MIDI::byte) intval;
if ((prop = node.property (X_("channel"))) == 0) {
return 0;
}
-
+
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
} else {
momentary = false;
}
-
+
prop = node.property (X_("uri"));
uri = prop->value();
cnt = 0;
stringstream ss (prop->value());
ss << hex;
-
+
while (ss >> val) {
cnt++;
}
data = new MIDI::byte[cnt];
data_size = cnt;
-
+
{
stringstream ss (prop->value());
ss << hex;
cnt = 0;
-
+
while (ss >> val) {
data[cnt++] = (MIDI::byte) val;
}
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
-
+
detail = (MIDI::byte) intval;
if ((prop = node.property (X_("channel"))) == 0) {
return 0;
}
-
+
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
}
prop = node.property (X_("function"));
-
+
MIDIFunction* mf = new MIDIFunction (*_input_port->parser());
-
+
if (mf->setup (*this, prop->value(), argument, data, data_size)) {
delete mf;
return 0;
cnt = 0;
stringstream ss (prop->value());
ss << hex;
-
+
while (ss >> val) {
cnt++;
}
data = new MIDI::byte[cnt];
data_size = cnt;
-
+
{
stringstream ss (prop->value());
ss << hex;
cnt = 0;
-
+
while (ss >> val) {
data[cnt++] = (MIDI::byte) val;
}
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
-
+
detail = (MIDI::byte) intval;
if ((prop = node.property (X_("channel"))) == 0) {
return 0;
}
-
+
if (sscanf (prop->value().c_str(), "%d", &intval) != 1) {
return 0;
}
}
prop = node.property (X_("action"));
-
+
MIDIAction* ma = new MIDIAction (*_input_port->parser());
if (ma->init (*this, prop->value(), data, data_size)) {
namespace PBD {
class Controllable;
class ControllableDescriptor;
-}
+}
namespace ARDOUR {
class Session;
void drop_bindings ();
void check_used_event (int, int);
-
+
std::string current_binding() const { return _current_binding; }
struct MapInfo {
void prev_bank ();
void set_motorised (bool);
-
+
bool motorised () const {
return _motorised;
}
public:
GMCPGUI (GenericMidiControlProtocol&);
~GMCPGUI ();
-
+
private:
GenericMidiControlProtocol& cp;
Gtk::ComboBoxText map_combo;
}
set_popdown_strings (map_combo, popdowns);
-
+
if (cp.current_binding().empty()) {
map_combo.set_active_text (popdowns[0]);
} else {
table->set_row_spacings (6);
table->set_col_spacings (6);
table->show ();
-
+
int n = 0;
Label* label = manage (new Label (_("MIDI Bindings:")));
table->attach (*label, 0, 1, n, n + 1);
table->attach (map_combo, 1, 2, n, n + 1);
++n;
-
+
map_combo.show ();
label->show ();
-
+
bank_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &GMCPGUI::bank_changed));
label = manage (new Label (_("Current Bank:")));
table->attach (*label, 0, 1, n, n + 1);
table->attach (bank_spinner, 1, 2, n, n + 1);
++n;
-
+
bank_spinner.show ();
label->show ();
new_generic_midi_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s)
{
GenericMidiControlProtocol* gmcp;
-
+
try {
gmcp = new GenericMidiControlProtocol (*s);
} catch (failed_constructor& err) {
return 0;
}
-
+
if (gmcp->set_active (true)) {
delete gmcp;
return 0;
/*initialize : */ new_generic_midi_protocol,
/*destroy : */ delete_generic_midi_protocol
};
-
+
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &generic_midi_descriptor; }
, _momentary (m)
{
set_controllable (&c);
-
+
_learned = true; /* from controllable */
_encoder = No_enc;
setting = false;
if (c == controllable) {
return;
}
-
+
controllable_death_connection.disconnect ();
controllable = c;
}
_control_description = "MIDI control: NoteOn";
break;
-
+
case MIDI::controller:
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIControllable::midi_sense_controller, this, _1, _2));
snprintf (buf, sizeof (buf), "MIDI control: Controller %d", control_additional);
if (!controllable || control_type == none || !feedback || bufsize <= 2) {
return buf;
}
-
+
int const gm = control_to_midi (controllable->get_value());
if (gm == last_value) {
MIDIControllable::max_value_for_type () const
{
/* XXX: this is not complete */
-
+
if (control_type == MIDI::pitchbend) {
return 16383;
}
};
MIDI::byte* write_feedback (MIDI::byte* buf, int32_t& bufsize, bool force = false);
-
+
void midi_rebind (MIDI::channel_t channel=-1);
void midi_forget ();
void learn_about_external_control ();
MIDI::byte get_control_additional () { return control_additional; }
int lookup_controllable();
-
+
private:
int max_value_for_type () const;
case MIDI::on:
_parser.channel_note_on[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_note_on, this, _1, _2));
break;
-
+
case MIDI::controller:
_parser.channel_controller[chn_i].connect_same_thread (midi_sense_connection[0], boost::bind (&MIDIInvokable::midi_sense_controller, this, _1, _2));
break;
MIDI::channel_t get_control_channel () { return control_channel; }
MIDI::eventType get_control_type () { return control_type; }
MIDI::byte get_control_additional () { return control_additional; }
-
+
protected:
GenericMidiControlProtocol* _ui;
std::string _invokable_name;
if (!g_ascii_strcasecmp (name.c_str(), "Scrub")) { return Scrub; }
if (!g_ascii_strcasecmp (name.c_str(), "User A")) { return UserA; }
if (!g_ascii_strcasecmp (name.c_str(), "User B")) { return UserB; }
-
+
/* Strip buttons */
-
+
if (!g_ascii_strcasecmp (name.c_str(), "Record Enable")) { return RecEnable; }
if (!g_ascii_strcasecmp (name.c_str(), "Solo")) { return Solo; }
if (!g_ascii_strcasecmp (name.c_str(), "Mute")) { return Mute; }
enum ID {
/* Global Buttons */
-
+
Track,
Send,
Pan,
CmdAlt,
/* Strip buttons */
-
+
RecEnable,
Solo,
Mute,
: Control (did, name, group)
, _bid (bid)
, _led (did, name + "_led", group) {}
-
+
MidiByteArray zero() { return _led.zero (); }
MidiByteArray set_state (LedState ls) { return _led.set_state (ls); }
-
+
ID bid() const { return _bid; }
-
+
static Control* factory (Surface& surface, Button::ID bid, int id, const std::string&, Group& group);
static int name_to_id (const std::string& name);
static std::string id_to_name (Button::ID);
: _name (name) {}
virtual ~Group() {}
-
+
virtual bool is_strip() const { return false; }
virtual bool is_master() const { return false; }
-
+
virtual void add (Control & control);
-
+
const std::string & name() const { return _name; }
void set_name (const std::string & rhs) { _name = rhs; }
-
+
typedef std::vector<Control*> Controls;
const Controls & controls() const { return _controls; }
-
+
protected:
Controls _controls;
-
+
private:
std::string _name;
};
return normal_ac->start_touch (when);
}
}
-
+
void
Control::stop_touch (bool mark, double when)
{
return normal_ac->stop_touch (mark, when);
}
}
-
+
ostream & operator << (ostream & os, const ArdourSurface::Mackie::Control & control)
{
os << typeid (control).name();
os << ", ";
os << "group: " << control.group().name();
os << " }";
-
+
return os;
}
public:
Control (int id, std::string name, Group& group);
virtual ~Control() {}
-
+
int id() const { return _id; }
const std::string & name() const { return _name; }
Group & group() const { return _group; }
bool in_use () const;
void set_in_use (bool);
-
+
// Keep track of the timeout so it can be updated with more incoming events
sigc::connection in_use_connection;
float get_value ();
void set_value (float val);
-
+
virtual void start_touch (double when);
virtual void stop_touch (bool mark, double when);
}
}
}
-
+
}
} else if ((*i)->name() == "StripButton") {
}
}
}
-
+
}
-
+
}
}
}
LCXT = 0x11,
HUI = 0x5
};
-
+
DeviceInfo();
~DeviceInfo();
static std::map<std::string,DeviceInfo> device_info;
static void reload_device_info();
-
+
std::string& get_global_button_name(Button::ID);
GlobalButtonInfo& get_global_button(Button::ID);
const GlobalButtonsInfo& global_buttons() const { return _global_buttons; }
const StripButtonsInfo& strip_buttons() const { return _strip_buttons; }
-
+
private:
uint32_t _strip_cnt;
uint32_t _extenders;
}
fullpath = Glib::build_filename (fullpath, legalize_for_path (_name) + ".profile");
-
+
XMLTree tree;
tree.set_root (&get_state());
public:
DeviceProfile (const std::string& name = "");
~DeviceProfile();
-
+
std::string get_button_action (Button::ID, int modifier_state) const;
void set_button_action (Button::ID, int modifier_state, const std::string&);
-
+
const std::string& name() const;
void set_path (const std::string&);
static void reload_device_profiles ();
static std::map<std::string,DeviceProfile> device_profiles;
-
+
private:
struct ButtonActions {
std::string plain;
std::string cmdalt;
std::string shiftcontrol;
};
-
+
typedef std::map<Button::ID,ButtonActions> ButtonActionMap;
-
+
std::string _name;
std::string _path;
ButtonActionMap _button_map;
-
+
int set_state (const XMLNode&, int version);
XMLNode& get_state () const;
}
last_update_position = posi;
-
+
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("generate fader message for position %1 (%2)\n", position, posi));
return MidiByteArray (3, 0xe0 + id(), posi & 0x7f, posi >> 7);
}
class Fader : public Control
{
public:
-
+
Fader (int id, std::string name, Group & group)
: Control (id, name, group)
, position (0.0)
MidiByteArray set_position (float);
MidiByteArray zero() { return set_position (0.0); }
-
+
MidiByteArray update_message ();
static Control* factory (Surface&, int id, const char*, Group&);
-
+
private:
float position;
int last_update_position;
Gtk::Label* l;
Gtk::Alignment* align;
int row = 0;
-
+
set_border_width (12);
Gtk::Table* table = Gtk::manage (new Gtk::Table (2, 12));
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table->attach (_surface_combo, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
row++;
-
+
vector<string> surfaces;
-
+
for (std::map<std::string,DeviceInfo>::iterator i = DeviceInfo::device_info.begin(); i != DeviceInfo::device_info.end(); ++i) {
surfaces.push_back (i->first);
}
send_string = _("Surface sends via:");
receive_string = _("Surface receives via:");
}
-
+
l = manage (new Gtk::Label (send_string));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
table->attach (ipmidi_base_port_spinner, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi());
ipmidi_base_port_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::ipmidi_spinner_changed));
-
+
/* leave an extra blank row */
row++;
touch_sensitivity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::touch_sensitive_change));
touch_sensitivity_scale.set_update_policy (Gtk::UPDATE_DISCONTINUOUS);
-
+
l = manage (new Gtk::Label (_("Button click")));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align->add (relay_click_button);
table->attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
l = manage (new Gtk::Label (_("Backlight")));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align->add (backlight_button);
table->attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
l = manage (new Gtk::Label (_("Send Fader Position Only When Touched")));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align->add (absolute_touch_mode_button);
table->attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
l = manage (new Gtk::Label (_("Send Fader Position When Moved")));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
align->add (touch_move_mode_button);
table->attach (*align, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
l = manage (new Gtk::Label (_("Fader Touch Sense Sensitivity")));
l->set_alignment (1.0, 0.5);
table->attach (*l, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
table->attach (touch_sensitivity_scale, 1, 2, 5, 6, AttachOptions(FILL|EXPAND), AttachOptions (0));
table->attach (recalibrate_fader_button, row, row+1, 6, 7, AttachOptions(FILL|EXPAND), AttachOptions (0));
row++;
-
+
table->attach (discover_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), AttachOptions (0));
discover_button.signal_clicked().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::discover_clicked));
row++;
-
+
vector<string> profiles;
-
+
profiles.push_back ("default");
for (std::map<std::string,DeviceProfile>::iterator i = DeviceProfile::device_profiles.begin(); i != DeviceProfile::device_profiles.end(); ++i) {
VBox* fkey_packer = manage (new VBox);
HBox* profile_packer = manage (new HBox);
HBox* observation_packer = manage (new HBox);
-
+
l = manage (new Gtk::Label (_("Profile/Settings:")));
profile_packer->pack_start (*l, false, false);
profile_packer->pack_start (_profile_combo, true, true);
profile_packer->set_spacing (12);
profile_packer->set_border_width (12);
-
+
l = manage (new Gtk::Label (_("* Button available at the original Mackie MCU PRO or current device if enabled (NOT implemented yet). Device specific name presented.")));
observation_packer->pack_start (*l, false, false);
parent = *(rowp);
parent[available_action_columns.name] = _("CmdAlt");
-
+
for (l = labels.begin(), k = keys.begin(), p = paths.begin(), t = tooltips.begin(); l != labels.end(); ++k, ++p, ++t, ++l) {
TreeModel::Row row;
col = manage (new TreeViewColumn (_("Plain"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.plain);
function_key_editor.append_column (*col);
-
+
renderer = make_action_renderer (available_action_model, function_key_columns.shift);
col = manage (new TreeViewColumn (_("Shift"), *renderer));
col->add_attribute (renderer->property_text(), function_key_columns.shift);
/* Probably a key alias */
row[function_key_columns.plain] = action;
} else {
-
+
act = ActionManager::get_action (action.c_str());
if (act) {
row[function_key_columns.plain] = act->get_label();
if (row) {
std::map<std::string,std::string>::iterator i = action_map.find (text);
-
+
if (i == action_map.end()) {
if (!remove) {
return;
{
public:
MackieControlProtocolGUI (MackieControlProtocol &);
-
+
private:
MackieControlProtocol& _cp;
Gtk::ComboBoxText _surface_combo;
Gtk::ComboBoxText _profile_combo;
Gtk::ComboBoxText _input_port_combo;
Gtk::ComboBoxText _output_port_combo;
-
+
struct AvailableActionColumns : public Gtk::TreeModel::ColumnRecord {
AvailableActionColumns() {
add (name);
new_mackie_protocol (ControlProtocolDescriptor*, Session* s)
{
MackieControlProtocol* mcp = 0;
-
+
try {
mcp = new MackieControlProtocol (*s);
/* do not set active here - wait for set_state() */
delete mcp;
mcp = 0;
}
-
+
return mcp;
}
/*initialize : */ new_mackie_protocol,
/*destroy : */ delete_mackie_protocol
};
-
+
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &mackie_descriptor; }
{
public:
enum Mode { scroll };
-
+
JogWheel (MackieControlProtocol & mcp);
/// As the wheel turns...
MIDI::byte msg = 0;
switch (state.state()) {
- case LedState::on:
+ case LedState::on:
msg = 0x7f;
break;
- case LedState::off:
+ case LedState::off:
msg = 0x00;
break;
- case LedState::flashing:
+ case LedState::flashing:
msg = 0x01;
break;
- case LedState::none:
+ case LedState::none:
return MidiByteArray ();
}
-
+
return MidiByteArray (3, 0x90, id(), msg);
}
, state (off)
{
}
-
+
Led & led() { return *this; }
MidiByteArray set_state (LedState);
MidiByteArray zero() { return set_state (off); }
-
+
static Control* factory (Surface&, int id, const char*, Group&);
private:
: _msg( msg )
{
}
-
+
virtual ~MackieControlException() throw () {}
-
+
const char * what() const throw ()
{
return _msg.c_str();
}
-
+
private:
std::string _msg;
};
Swap, /* fader controls secondary, vpot controls primary */
Zero, /* fader controls primary, but doesn't move, vpot controls secondary */
};
-
+
MackieControlProtocol(ARDOUR::Session &);
virtual ~MackieControlProtocol();
static MackieControlProtocol* instance() { return _instance; }
-
+
const Mackie::DeviceInfo& device_info() const { return _device_info; }
Mackie::DeviceProfile& device_profile() { return _device_profile; }
we do not implement get/set_feedback() since this aspect of
support for the protocol is not optional.
*/
-
+
static bool probe();
-
+
Glib::Threads::Mutex surfaces_lock;
typedef std::list<boost::shared_ptr<Mackie::Surface> > Surfaces;
Surfaces surfaces;
void set_master_on_surface_strip (uint32_t surface, uint32_t strip);
void set_monitor_on_surface_strip (uint32_t surface, uint32_t strip);
-
+
uint32_t n_strips (bool with_locked_strips = true) const;
-
+
bool has_editor () const { return true; }
void* get_gui () const;
void tear_down_gui ();
void recalibrate_faders ();
void toggle_backlight ();
void set_touch_sensitivity (int);
-
+
/// rebuild the current bank. Called on route added/removed and
/// remote id changed.
void refresh_current_bank();
/// Turn timecode on and beats off, or vice versa, depending
/// on state of _timecode_type
void update_timecode_beats_led();
-
+
/// this is called to generate the midi to send in response to a button press.
void update_led(Mackie::Surface&, Mackie::Button & button, Mackie::LedState);
void add_down_button (ARDOUR::AutomationType, int surface, int strip);
void remove_down_button (ARDOUR::AutomationType, int surface, int strip);
ControlList down_controls (ARDOUR::AutomationType);
-
+
void add_down_select_button (int surface, int strip);
void remove_down_select_button (int surface, int strip);
void select_range ();
void not_session_load () { _session_load = false; }
void midi_connectivity_established ();
-
+
protected:
// shut down the surface
void close();
// This sets up the notifications and sets the
// controls to the correct values
void update_surfaces();
-
+
// connects global (not strip) signals from the Session to here
// so the surface can be notified of changes from the other UIs.
void connect_session_signals();
-
+
// set all controls to their zero position
void zero_all();
-
+
/**
Fetch the set of routes to be considered for control by the
surface. Excluding master, hidden and control routes, and inactive routes
std::string format_bbt_timecode (ARDOUR::framepos_t now_frame);
std::string format_timecode_timecode (ARDOUR::framepos_t now_frame);
-
+
void do_request (MackieControlUIRequest*);
int stop ();
struct ButtonHandlers {
Mackie::LedState (MackieControlProtocol::*press) (Mackie::Button&);
Mackie::LedState (MackieControlProtocol::*release) (Mackie::Button&);
-
+
ButtonHandlers (Mackie::LedState (MackieControlProtocol::*p) (Mackie::Button&),
Mackie::LedState (MackieControlProtocol::*r) (Mackie::Button&))
: press (p)
typedef std::map<Mackie::Button::ID,ButtonHandlers> ButtonMap;
static MackieControlProtocol* _instance;
-
+
Mackie::DeviceInfo _device_info;
Mackie::DeviceProfile _device_profile;
sigc::connection periodic_connection;
MackieControlProtocol::cursor_right_press (Button& )
{
if (zoom_mode()) {
-
+
if (main_modifier_state() & MODIFIER_OPTION) {
/* reset selected tracks to default vertical zoom */
} else {
ScrollTimeline (page_fraction);
}
-
+
return off;
}
MackieControlProtocol::cursor_up_press (Button&)
{
if (zoom_mode()) {
-
+
if (main_modifier_state() & MODIFIER_CONTROL) {
VerticalZoomInSelected (); /* EMIT SIGNAL */
} else {
void
Meter::notify_metering_state_changed(Surface& surface, bool transport_is_rolling, bool metering_active)
-{
+{
MidiByteArray msg;
-
+
// sysex header
msg << surface.sysex_hdr();
-
+
// code for Channel Meter Enable Message
msg << 0x20;
-
+
// Channel identification
msg << id();
-
+
// Enable (0x07) / Disable (0x00) level meter on LCD, peak hold display on horizontal meter and signal LED
msg << ((transport_is_rolling && metering_active) ? 0x07 : 0x00);
-
+
// sysex trailer
msg << MIDI::eox;
-
+
surface.write (msg);
}
float def = 0.0f; /* Meter deflection %age */
// DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Meter ID %1 dB %2\n", id(), dB));
-
+
if (dB < -70.0f) {
def = 0.0f;
} else if (dB < -60.0f) {
} else {
def = 115.0f;
}
-
+
/* 115 is the deflection %age that would be
when dB=6.0. this is an arbitrary
endpoint for our scaling.
*/
MidiByteArray msg;
-
+
if (def > 100.0f) {
if (!overload_on) {
overload_on = true;
surface.write (MidiByteArray (2, 0xd0, (id() << 4) | 0xe));
-
+
}
} else {
if (overload_on) {
surface.write (MidiByteArray (2, 0xd0, (id() << 4) | 0xf));
}
}
-
+
/* we can use up to 13 segments */
int segment = lrintf ((def/115.0) * 13.0);
-
+
surface.write (MidiByteArray (2, 0xd0, (id()<<4) | segment));
}
Meter (int id, std::string name, Group & group)
: Control (id, name, group)
, overload_on (false) {}
-
+
void send_update (Surface&, float dB);
MidiByteArray zero();
for (size_t i = 0; i < size; ++i)
{
push_back (array[i]);
- }
+ }
}
MidiByteArray::MidiByteArray (size_t count, MIDI::byte first, ...)
{
public:
MidiByteArray() : std::vector<MIDI::byte>() {}
-
+
MidiByteArray( size_t count, MIDI::byte array[] );
/**
Accepts a preceding count, and then a list of bytes
*/
MidiByteArray( size_t count, MIDI::byte first, ... );
-
+
/// copy the given number of bytes from the given array
void copy( size_t count, MIDI::byte arr[] );
};
// center on if val is "very close" to 0.50
MIDI::byte msg = (val > 0.48 && val < 0.58 ? 1 : 0) << 6;
-
+
// Pot/LED mode
msg |= (mode << 4);
if (val < 0){
val = val * -1;
}
-
+
// val, but only if off hasn't explicitly been set
if (onoff) {
if (mode == spread) {
return MidiByteArray (3, 0xb0, 0x20 + id(), msg);
}
-
+
_surface->number(), index, Button::id_to_name (bb->bid()),
bb->id(), b->second.base_id));
}
-}
+}
Strip::~Strip ()
{
}
route_connections.drop_connections ();
-
+
_solo->set_control (boost::shared_ptr<AutomationControl>());
_mute->set_control (boost::shared_ptr<AutomationControl>());
_select->set_control (boost::shared_ptr<AutomationControl>());
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
_surface->number(), _index, _route->name()));
-
+
_solo->set_control (_route->solo_control());
_mute->set_control (_route->mute_control());
set_vpot_parameter (PanAzimuthAutomation);
-
+
_route->solo_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
_route->listen_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
}
_route->gain_control()->Changed.connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
_route->PropertyChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
-
+
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
-
+
if (trk) {
_recenable->set_control (trk->rec_enable_control());
trk->rec_enable_control()->Changed .connect(route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
-
+
}
-
+
// TODO this works when a currently-banked route is made inactive, but not
// when a route is activated which should be currently banked.
-
+
_route->active_changed.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_active_changed, this), ui_context());
_route->DropReferences.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_route_deleted, this), ui_context());
-
+
/* Update */
-
+
notify_all ();
/* setup legal VPot modes for this route */
-
+
build_input_list (_route->input()->n_ports());
build_output_list (_route->output()->n_ports());
if (panner) {
set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
set<Evoral::Parameter>::iterator a;
-
+
if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
possible_pot_parameters.push_back (PanAzimuthAutomation);
}
-
+
if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
possible_pot_parameters.push_back (PanWidthAutomation);
}
Strip::notify_gain_changed (bool force_update)
{
if (_route) {
-
+
Control* control;
if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
}
boost::shared_ptr<AutomationControl> ac = _route->gain_control();
-
+
float gain_coefficient = ac->get_value();
float normalized_position = ac->internal_to_interface (gain_coefficient);
if (force_update || normalized_position != _last_gain_position_written) {
-
+
if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
if (!control->in_use()) {
_surface->write (_vpot->set (normalized_position, true, Pot::wrap));
if (_route) {
string line1;
string fullname = _route->name();
-
+
if (fullname.length() <= 6) {
line1 = fullname;
} else {
line1 = PBD::short_version (fullname, 6);
}
-
+
_surface->write (display (0, line1));
}
}
}
double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value());
-
+
if (force_update || pos != _last_pan_azi_position_written) {
if (control == _fader) {
} else if (control == _vpot) {
_surface->write (_vpot->set (pos, true, Pot::dot));
}
-
+
queue_parameter_display (PanAzimuthAutomation, pos);
queue_display_reset (2000);
_last_pan_azi_position_written = pos;
if (!control) {
return;
- }
-
+ }
+
double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value());
-
+
if (force_update || pos != _last_pan_azi_position_written) {
-
+
if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
if (control == _fader) {
} else if (control == _vpot) {
_surface->write (_vpot->set (pos, true, Pot::spread));
}
-
+
queue_parameter_display (PanWidthAutomation, pos);
queue_display_reset (2000);
_last_pan_azi_position_written = pos;
Strip::select_event (Button&, ButtonState bs)
{
DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
-
+
if (bs == press) {
-
+
int ms = _surface->mcp().main_modifier_state();
if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
queue_display_reset (1000);
return;
}
-
+
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default */
boost::shared_ptr<AutomationControl> ac = _fader->control ();
}
return;
}
-
+
DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
- _surface->mcp().add_down_select_button (_surface->number(), _index);
+ _surface->mcp().add_down_select_button (_surface->number(), _index);
_surface->mcp().select_range ();
-
+
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
- _surface->mcp().remove_down_select_button (_surface->number(), _index);
+ _surface->mcp().remove_down_select_button (_surface->number(), _index);
}
}
if (bs == press) {
int ms = _surface->mcp().main_modifier_state();
-
+
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
boost::shared_ptr<AutomationControl> ac = _vpot->control ();
-
+
if (ac) {
-
+
/* reset to default/normal value */
ac->set_value (ac->normal());
}
Strip::fader_touch_event (Button&, ButtonState bs)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
-
+
if (bs == press) {
boost::shared_ptr<AutomationControl> ac = _fader->control ();
_fader->set_in_use (true);
_fader->start_touch (_surface->mcp().transport_frame());
-
+
if (ac) {
queue_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
queue_display_reset (2000);
}
}
-
+
} else {
-
+
_fader->set_in_use (false);
_fader->stop_touch (_surface->mcp().transport_frame(), true);
-
+
}
-}
+}
void
}
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
-
+
switch (button.bid()) {
case Button::Select:
select_event (button, bs);
break;
-
+
case Button::VSelect:
vselect_event (button, bs);
break;
if (bs == press) {
DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
_surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
-
+
float new_value;
int ms = _surface->mcp().main_modifier_state();
-
+
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default/normal value */
new_value = control->normal();
} else {
new_value = control->get_value() ? 0.0 : 1.0;
}
-
+
/* get all controls that either have their
* button down or are within a range of
* several down buttons
*/
-
+
MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
-
-
+
+
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
controls.size(), control->parameter().type(), new_value));
/* apply change */
-
+
for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
(*c)->set_value (new_value);
}
-
+
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
_surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
float dB = accurate_coefficient_to_dB (val);
snprintf (buf, sizeof (buf), "%6.1f", dB);
_surface->write (display (1, buf));
- }
+ }
break;
case PanAzimuthAutomation:
/* Pots only emit events when they move, not when they
stop moving. So to get a stop event, we need to use a timeout.
*/
-
+
boost::shared_ptr<AutomationControl> ac = pot.control();
double p = pot.get_value ();
p += delta;
// sysex header
retval << _surface->sysex_hdr();
-
+
// code for display
retval << 0x12;
// offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
retval << (_index * 7 + (line_number * 0x38));
-
+
// ascii data to display. @param line is UTF-8
string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
string::size_type len = ascii.length();
for (int i = len; i < 6; ++i) {
retval << ' ';
}
-
+
// column spacer, unless it's the right-hand column
if (_index < 7) {
retval << ' ';
// sysex trailer
retval << MIDI::eox;
-
+
return retval;
}
Strip::vpot_mode_string () const
{
boost::shared_ptr<AutomationControl> ac = _vpot->control();
-
+
if (!ac) {
return string();
}
struct timeval delta;
struct timeval when;
gettimeofday (&now, 0);
-
+
delta.tv_sec = msecs/1000;
delta.tv_usec = (msecs - ((msecs/1000) * 1000)) * 1000;
-
+
timeradd (&now, &delta, &when);
_reset_display_at = (when.tv_sec * 1000000) + when.tv_usec;
} else {
_surface->write (blank_display (1));
}
-
+
clear_display_reset ();
}
-
+
struct RouteCompareByName {
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
return a->name().compare (b->name()) < 0;
input_bundles.clear ();
/* give user bundles first chance at being in the menu */
-
+
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
maybe_add_to_bundle_map (input_bundles, *i, true, channels);
}
}
-
+
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
maybe_add_to_bundle_map (input_bundles, *i, true, channels);
}
}
-
+
boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
RouteList copy = *routes;
copy.sort (RouteCompareByName ());
output_bundles.clear ();
/* give user bundles first chance at being in the menu */
-
+
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
maybe_add_to_bundle_map (output_bundles, *i, false, channels);
}
}
-
+
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
maybe_add_to_bundle_map (output_bundles, *i, false, channels);
}
}
-
+
boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
RouteList copy = *routes;
copy.sort (RouteCompareByName ());
if (!_route || !_meter) {
return;
}
-
+
bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
bool metering_active = _surface->mcp().metering_active ();
-
+
if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
return;
}
-
+
_meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
-
+
if (!transport_is_rolling || !metering_active) {
notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
notify_panner_azi_changed (true);
}
-
+
_transport_is_rolling = transport_is_rolling;
_metering_active = metering_active;
}
void add (Control & control);
int index() const { return _index; } // zero based
-
+
void set_route (boost::shared_ptr<ARDOUR::Route>, bool with_messages = true);
// call all signal handlers manually
void notify_panner_width_changed (bool force_update = true);
void notify_active_changed ();
void notify_route_deleted ();
-
+
void update_automation ();
void update_meter ();
void do_parameter_display (ARDOUR::AutomationType, float val);
void queue_parameter_display (ARDOUR::AutomationType, float val);
-
+
typedef std::map<std::string,boost::shared_ptr<ARDOUR::Bundle> > BundleMap;
BundleMap input_bundles;
BundleMap output_bundles;
, _last_master_gain_written (-0.0f)
{
DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface init\n");
-
+
try {
_port = new SurfacePort (*this);
} catch (...) {
}
uint32_t n = _mcp.device_info().strip_cnt();
-
+
if (n) {
init_strips (n);
DEBUG_TRACE (DEBUG::MackieControl, "init_strips done\n");
}
-
+
connect_to_signals ();
DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface done\n");
for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
delete it->second;
}
-
+
// delete controls
for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
delete *it;
}
-
+
delete _jog_wheel;
delete _port;
Surface::init_controls()
{
Group* group;
-
+
DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating groups\n");
groups["assignment"] = new Group ("assignment");
groups["automation"] = new Group ("automation");
groups["transport"] = new Group ("transport");
groups["user"] = new Group ("user");
groups["utilities"] = new Group ("utilities");
-
+
DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating jog wheel\n");
if (_mcp.device_info().has_jog_wheel()) {
_jog_wheel = new Mackie::JogWheel (_mcp);
for (uint32_t i = 0; i < n; ++i) {
char name[32];
-
+
snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
Strip* strip = new Strip (*this, name, i, strip_buttons);
-
+
groups[name] = strip;
strips.push_back (strip);
}
Surface::setup_master ()
{
boost::shared_ptr<Route> m;
-
+
if ((m = _mcp.get_session().monitor_out()) == 0) {
m = _mcp.get_session().master_out();
}
-
+
if (!m) {
return;
}
_master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *groups["master"]));
-
+
_master_fader->set_control (m->gain_control());
m->gain_control()->Changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
}
// Master fader
p->channel_pitchbend[_mcp.device_info().strip_cnt()].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, _mcp.device_info().strip_cnt()));
-
+
_connected = true;
}
}
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2 (%4)\n",
fader_id, pb, _number, pb/16384.0));
-
+
if (_mcp.device_info().no_handshake()) {
turn_it_on ();
}
Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_note_on_message %1 = %2\n", (int) ev->note_number, (int) ev->velocity));
-
+
if (_mcp.device_info().no_handshake()) {
turn_it_on ();
}
if (_mcp.device_info().device_type() == DeviceInfo::HUI && ev->note_number == 0 && ev->velocity == 127) {
turn_it_on ();
}
-
+
/* fader touch sense is given by "buttons" 0xe..0xe7 and 0xe8 for the
* master.
*/
} else {
delta = sign * (ticks / (float) 0x3f);
}
-
+
if (!pot) {
if (ev->controller_number == Jog::ID && _jog_wheel) {
MidiByteArray l;
back_insert_iterator<MidiByteArray> back (l);
copy (begin, end, back);
-
+
MidiByteArray retval;
-
+
// this is how to calculate the response to the challenge.
// from the Logic docs.
retval << (0x7f & (l[0] + (l[1] ^ 0xa) - l[3]));
retval << (0x7f & ( (l[2] >> l[3]) ^ (l[0] + l[3])));
retval << (0x7f & ((l[3] - (l[2] << 2)) ^ (l[0] | l[1])));
retval << (0x7f & (l[1] - l[2] + (0xf0 ^ (l[3] << 4))));
-
+
return retval;
}
Surface::host_connection_query (MidiByteArray & bytes)
{
MidiByteArray response;
-
+
if (bytes[4] != 0x10 && bytes[4] != 0x11) {
/* not a Logic Control device - no response required */
return response;
// handle host connection query
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host connection query: %1\n", bytes));
-
+
if (bytes.size() != 18) {
cerr << "expecting 18 bytes, read " << bytes << " from " << _port->input_port().name() << endl;
return response;
Surface::host_connection_confirmation (const MidiByteArray & bytes)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host_connection_confirmation: %1\n", bytes));
-
+
// decode host connection confirmation
if (bytes.size() != 14) {
ostringstream os;
os << "expecting 14 bytes, read " << bytes << " from " << _port->input_port().name();
throw MackieControlException (os.str());
}
-
+
// send version request
return MidiByteArray (2, 0x13, 0x00);
}
if (_mcp.device_info().has_timecode_display ()) {
display_timecode (string (10, '0'), string (10, ' '));
}
-
+
if (_mcp.device_info().has_two_character_display()) {
show_two_char_display (string (2, '0'), string (2, ' '));
}
if (_stype != mcu || !_mcp.device_info().has_two_character_display() || msg.length() != 2 || dots.length() != 2) {
return;
}
-
+
MidiByteArray right (3, 0xb0, 0x4b, 0x00);
MidiByteArray left (3, 0xb0, 0x4a, 0x00);
-
+
right[2] = translate_seven_segment (msg[0]) + (dots[0] == '.' ? 0x40 : 0x00);
left[2] = translate_seven_segment (msg[1]) + (dots[1] == '.' ? 0x40 : 0x00);
-
+
_port->write (right);
_port->write (left);
}
}
// if there's no change, send nothing, not even sysex header
if (timecode == last_timecode) return;
-
+
// length sanity checking
string local_timecode = timecode;
while (local_timecode.length() < 10) {
local_timecode += " ";
}
-
+
// translate characters.
// Only the characters that actually changed are sent.
int position = 0x3f;
}
if (id >= 0) {
-
+
/* we are attempting to turn a global button/LED on */
map<int,Control*>::iterator x = controls_by_device_independent_id.find (id);
void
Surface::set_jog_mode (JogWheel::Mode)
{
-}
+}
bool
Surface::route_is_locked_to_strip (boost::shared_ptr<Route> r) const
msg[4] = 0x11; /* reset Logic Control XT */
_port->write (msg);
}
-}
+}
void
Surface::set_touch_sensitivity (int sensitivity)
{
/* NOTE: assumed called from GUI code, hence sleep() */
-
+
/* sensitivity already clamped by caller */
if (_port) {
std::map<int,Led*> leds;
std::map<int,Meter*> meters;
std::map<int,Control*> controls_by_device_independent_id;
-
+
Mackie::JogWheel* jog_wheel() const { return _jog_wheel; }
Fader* master_fader() const { return _master_fader; }
void periodic (uint64_t now_usecs);
void redisplay ();
void hui_heartbeat ();
-
+
void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t, uint32_t channel_id);
void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
/// display an indicator of the first switched-in Route. Do nothing by default.
void display_bank_start (uint32_t /*current_bank*/);
-
+
/// called from MackieControlProtocol::zero_all to turn things off
void zero_all ();
void zero_controls ();
void recalibrate_faders ();
void toggle_backlight ();
void set_touch_sensitivity (int);
-
+
/**
This is used to calculate the clicks per second that define
a transport speed of 1.0 for the jog wheel. 100.0 is 10 clicks
// be two characters
void show_two_char_display (const std::string & msg, const std::string & dots = " ");
void show_two_char_display (unsigned int value, const std::string & dots = " ");
-
+
void update_view_mode_display ();
void update_flip_mode_display ();
int set_state (const XMLNode&, int version);
protected:
-
+
private:
MackieControlProtocol& _mcp;
SurfacePort* _port;
_output_port = _input_port;
} else {
-
+
_async_in = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"), _surface->name()), true);
_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"), _surface->name()), true);
AudioEngine::instance()->unregister_port (_async_in);
_async_in.reset ((ARDOUR::Port*) 0);
}
-
+
if (_async_out) {
_output_port->drain (10000);
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("unregistering output port %1\n", _async_out->name()));
child = new XMLNode (X_("Input"));
child->add_child_nocopy (_async_in->get_state());
node->add_child_nocopy (*child);
-
+
child = new XMLNode (X_("Output"));
child->add_child_nocopy (_async_out->get_state());
char * msg = strerror (error_number);
return msg;
}
-
+
int
SurfacePort::write (const MidiByteArray & mba)
{
if (mba[0] != 0xf0 && mba.size() > 3) {
std::cerr << "TOO LONG WRITE: " << mba << std::endl;
}
-
+
/* this call relies on std::vector<T> using contiguous storage. not
* actually guaranteed by the standard, but way, way beyond likely.
*/
/// an easier way to output bytes via midi
int write (const MidiByteArray&);
-
+
MIDI::Port& input_port() const { return *_input_port; }
MIDI::Port& output_port() const { return *_output_port; }
MIDI::Port* _output_port;
boost::shared_ptr<ARDOUR::Port> _async_in;
boost::shared_ptr<ARDOUR::Port> _async_out;
-};
+};
std::ostream& operator << (std::ostream& , const SurfacePort& port);
class Timer
{
public:
-
+
/**
start the timer running if true, or just create the
object if false.
if ( shouldStart )
start();
}
-
+
/**
Start the timer running. Return the current timestamp, in milliseconds
*/
return (_stop - _start) / 1000;
}
}
-
+
/**
Call stop and then start. Return the value from stop.
*/
LedState (state_t state): _state (state) {}
LedState& operator= (state_t s) { _state = s; return *this; }
-
+
bool operator == (const LedState & other) const
{
return state() == other.state();
}
-
+
bool operator != (const LedState & other) const
{
return state() != other.state();
}
-
+
state_t state() const { return _state; }
-
+
private:
state_t _state;
};
struct ControlState
{
ControlState(): pos(0.0), sign(0), delta(0.0), ticks(0), led_state(off), button_state(neither) {}
-
+
ControlState (LedState ls): pos(0.0), delta(0.0), led_state(ls), button_state(neither) {}
-
+
// Note that this sets both pos and delta to the flt value
ControlState (LedState ls, float flt): pos(flt), delta(flt), ticks(0), led_state(ls), button_state(neither) {}
ControlState (float flt): pos(flt), delta(flt), ticks(0), led_state(none), button_state(neither) {}
ControlState (float flt, unsigned int tcks): pos(flt), delta(flt), ticks(tcks), led_state(none), button_state(neither) {}
ControlState (ButtonState bs): pos(0.0), delta(0.0), ticks(0), led_state(none), button_state(bs) {}
-
+
/// For faders. Between 0 and 1.
float pos;
-
+
/// For pots. Sign. Either -1 or 1;
int sign;
/// For pots. Signed value of total movement. Between 0 and 1
float delta;
-
+
/// For pots. Unsigned number of ticks. Usually between 1 and 16.
unsigned int ticks;
-
+
LedState led_state;
ButtonState button_state;
};
new_osc_protocol (ControlProtocolDescriptor* /*descriptor*/, Session* s)
{
OSC* osc = new OSC (*s, Config->get_osc_port());
-
+
osc->set_active (true);
return osc;
class Session;
class Route;
}
-
+
/* this is mostly a placeholder because I suspect that at some
point we will want to add more members to accomodate
certain types of requests to the OSC UI
GSource* local_server;
GSource* remote_server;
-
+
bool osc_input_handler (Glib::IOCondition, lo_server);
private:
void register_callbacks ();
void route_added (ARDOUR::RouteList&);
-
+
// Handlers for "Application Hook" signals
void session_loaded (ARDOUR::Session&);
void session_exported (std::string, std::string);
void send_current_value (const char* path, lo_arg** argv, int argc, lo_message msg);
void current_value_query (const char* path, size_t len, lo_arg **argv, int argc, lo_message msg);
-
+
int current_value (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
-
+
int catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data);
static int _catchall (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
name (data); \
return 0; \
}
-
+
PATH_CALLBACK_MSG(routes_list);
PATH_CALLBACK_MSG(transport_frame);
-
+
#define PATH_CALLBACK(name) \
static int _ ## name (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { \
return static_cast<OSC*>(user_data)->cb_ ## name (path, types, argv, argc, data); \
int route_set_send_gain_dB (int rid, int sid, float val);
int route_plugin_parameter (int rid, int piid,int par, float val);
int route_plugin_parameter_print (int rid, int piid,int par);
-
+
void listen_to_route (boost::shared_ptr<ARDOUR::Route>, lo_address);
void end_listen (boost::shared_ptr<ARDOUR::Route>, lo_address);
void drop_route (boost::weak_ptr<ARDOUR::Route>);
-
+
void route_name_changed (const PBD::PropertyChange&, boost::weak_ptr<ARDOUR::Route> r, lo_address addr);
-
+
void update_clock ();
typedef std::list<OSCRouteObserver*> RouteObservers;
-
+
RouteObservers route_observers;
static OSC* _instance;
OSCControllable::send_change_message ()
{
lo_message msg = lo_message_new ();
-
+
lo_message_add_float (msg, (float) controllable->get_value());
/* XXX thread issues */
lo_message_free (msg);
}
-/*------------------------------------------------------------*/
+/*------------------------------------------------------------*/
OSCRouteControllable::OSCRouteControllable (lo_address a, const std::string& p,
boost::shared_ptr<Controllable> c, boost::shared_ptr<Route> r)
: _route (r)
{
addr = lo_address_new (lo_address_get_hostname(a) , lo_address_get_port(a));
-
+
_route->PropertyChanged.connect (name_changed_connection, MISSING_INVALIDATOR, boost::bind (&OSCRouteObserver::name_changed, this, boost::lambda::_1), OSC::instance());
if (boost::dynamic_pointer_cast<AudioTrack>(_route) || boost::dynamic_pointer_cast<MidiTrack>(_route)) {
rec_controllable->Changed.connect (rec_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/rec"), track->rec_enable_control()), OSC::instance());
}
-
+
boost::shared_ptr<Controllable> mute_controllable = boost::dynamic_pointer_cast<Controllable>(_route->mute_control());
mute_controllable->Changed.connect (mute_changed_connection, MISSING_INVALIDATOR, bind (&OSCRouteObserver::send_change_message, this, X_("/route/mute"), _route->mute_control()), OSC::instance());
if (!what_changed.contains (ARDOUR::Properties::name)) {
return;
}
-
+
if (!_route) {
return;
}
-
+
lo_message msg = lo_message_new ();
lo_message_add_int32 (msg, _route->remote_control_id());
private:
boost::shared_ptr<ARDOUR::Route> _route;
//boost::shared_ptr<Controllable> _controllable;
-
+
PBD::ScopedConnection name_changed_connection;
PBD::ScopedConnection rec_changed_connection;
PBD::ScopedConnection mute_changed_connection;
PBD::ScopedConnection solo_changed_connection;
PBD::ScopedConnection gain_changed_connection;
-
+
lo_address addr;
std::string path;
// Based on the current bling mode, do whatever it is you are going to do
bling::run() {
-
+
}
// etc
this_button_mask |= buf[4] << 8;
this_button_mask |= buf[5];
_datawheel = buf[6];
-
+
#if DEBUG_TRANZPORT_STATE > 1
// Is the state machine incomplete?
const unsigned int knownstates = 0x00004000|0x00008000|
case BlingPairs: break; // Show pairs of lights
case BlingRows: break; // light each row in sequence
case BlingFlashAll: break; // Flash everything randomly
- case BlingEnter: lights_on(); // Show intro
+ case BlingEnter: lights_on(); // Show intro
case BlingExit:
lights_off();
break;
case BlingPairs: break; // Show pairs of lights
case BlingRows: break; // light each row in sequence
case BlingFlashAll: break; // Flash everything randomly
- case BlingEnter: // Show intro
+ case BlingEnter: // Show intro
print(0,0,"!!Welcome to Ardour!");
print(1,0,"Peace through Music!");
break;
TranzportControlProtocol::prev_marker ()
{
Location *location = session->locations()->first_location_before (session->transport_frame());
-
+
if (location) {
session->request_locate (location->start(), session->transport_rolling());
notify(location->name().c_str());
if (fabsf(gain_fraction) > 2.0) {
gain_fraction = 2.0*sign(gain_fraction);
}
-
+
route_set_gain (0, slider_position_to_gain (gain_fraction));
}
#endif
if (gain_fraction > 2.0) {
gain_fraction = 2.0;
}
-
+
route_set_gain (0, slider_position_to_gain (gain_fraction));
}
if (gain_fraction < 0.0) {
gain_fraction = 0.0;
}
-
+
route_set_gain (0, slider_position_to_gain (gain_fraction));
}
struct sched_param rtparam;
int err;
memset (&rtparam, 0, sizeof (rtparam));
- rtparam.sched_priority = priority;
+ rtparam.sched_priority = priority;
if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
PBD::info << string_compose (_("%1: can't stop realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
return 1;
case 3: val = read(buf,DEFAULT_USB_TIMEOUT*2); break; // Hoo, boy, we're in trouble
default: break; // not reached
}
-
+
#if DEBUG_TRANZPORT_BITS > 9
if(_device_status != STATUS_OFFLINE && _device_status != STATUS_ONLINE && _device_status != STATUS_OK) {
printf("The device has more status bits than off or online: %d\n",_device_status);
printf("OFFLINE : %02x %02x %02x %02x %02x %02x %02x %02x\n",
buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
}
-
+
if(_device_status == STATUS_OK) {
printf("OK : %02x %02x %02x %02x %02x %02x %02x %02x\n",
buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
}
return tcp;
-
+
}
static void
initialize : new_tranzport_protocol,
destroy : delete_tranzport_protocol
};
-
+
extern "C" ARDOURSURFACE_API ControlProtocolDescriptor* protocol_descriptor () { return &tranzport_descriptor; }
printf("LPEND : %s\n", lights_pending.to_string().c_str());
printf("LCURR : %s\n", lights_current.to_string().c_str());
#endif
-
+
// if ever we thread reads/writes STATUS_OK will have to move into the loop
int i;
-
+
if ( _device_status == STATUS_OK || _device_status == STATUS_ONLINE) {
for (i = 0; i<LIGHTS; i++) {
if(light_state[i]) {
#if DEBUG_TRANZPORT_LIGHTS > 2
printf("Did %d light writes, left: %d\n",i, light_state.count());
#endif
-
+
return light_state.count();
}
return last_read_error;
}
-
+
int
TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
{
return 0;
-}
+}
int
TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
{
return (write_noretry(cmd,timeout_override));
-}
+}
// FIXME - install poll semantics
#endif /* HAVE_TRANZPORT_KERNEL_DRIVER */
cerr << _("Tranzport: cannot open USB transport") << endmsg;
return -1;
}
-
+
if (usb_claim_interface (udev, 0) < 0) {
cerr << _("Tranzport: cannot claim USB interface") << endmsg;
usb_close (udev);
return last_read_error;
}
-
+
int
TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
{
return 0;
-}
+}
int
TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
int val;
int retry = 0;
if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
-
+
while((val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout))!=8 && retry++ < MAX_RETRY) {
printf("usb_interrupt_write failed, retrying: %d\n", val);
}
return (write_noretry(cmd,timeout_override));
#endif
-}
+}
#endif
bool TranzportControlProtocol::lcd_isdamaged ()
{
if(screen_invalid.any()) {
-#if DEBUG_TRANZPORT > 5
+#if DEBUG_TRANZPORT > 5
printf("LCD is damaged somewhere, should redraw it\n");
#endif
return true;
std::bitset<ROWS*COLUMNS> mask(mask1 << (row*COLUMNS+col));
mask &= screen_invalid;
if(mask.any()) {
-#if DEBUG_TRANZPORT > 5
+#if DEBUG_TRANZPORT > 5
printf("row: %d,col: %d is damaged, should redraw it\n", row,col);
#endif
return true;
}
last_meter_fill_l = fill_left; last_meter_fill_r = fill_right;
-
+
// give some feedback when overdriving - override yellow and red lights
if (fraction_l > 0.96 || fraction_r > 0.96) {
if (fraction_l == 1.0 || fraction_r == 1.0) {
light_on (LightTrackrec);
}
-
+
const uint8_t char_map[16] = { ' ', TRANZ_UL,
TRANZ_U, TRANZ_U,
TRANZ_BL, TRANZ_Q2,
((fill_right >=j) << 2) | ((fill_right >= j+1) << 3);
buf[i] = char_map[val];
}
-
+
/* print() requires this */
buf[meter_size/2] = '\0';
print (1, 0, buf);
/* Add a peak bar, someday do falloff */
-
+
// char peak[2]; peak[0] = ' '; peak[1] = '\0';
// if(fraction_l == 1.0 || fraction_r == 1.0) peak[0] = 'P';
// print (1,8,peak); // Put a peak meter - P in if we peaked.
-
+
}
void
for (i = 0; i < fill; ++i) {
buf[i] = 0x07; /* tranzport special code for 4 quadrant LCD block */
}
-
+
/* add a possible half-step */
if (i < 20 && add_single_level) {
TranzportControlProtocol::show_transport_time ()
{
show_bbt (session->transport_frame ());
-}
+}
void
TranzportControlProtocol::show_timecode (framepos_t where)
int retval = 0;
// I think I want to make these strings rather than numbers
-#if 0
+#if 0
// fetch current display mode
if ( node.property( X_("display_mode") ) != 0 )
{
WheelShiftMaster,
WheelShiftMarker
};
-
+
enum WheelMode {
WheelTimeline,
WheelScrub,
WheelIncrSecond,
WheelIncrMinute
};
-
+
enum DisplayMode {
DisplayNormal,
DisplayRecording,
void show_current_track ();
void show_track_gain ();
void show_transport_time ();
- void show_bbt (framepos_t where);
+ void show_bbt (framepos_t where);
void show_timecode (framepos_t where);
void show_wheel_mode ();
void show_gain ();
if ((buttonmask & ButtonTrackRight) || (buttonmask & ButtonTrackLeft)) {
/* track scrolling */
-
+
if (_datawheel < WheelDirectionThreshold) {
next_track ();
} else {
}
last_wheel_motion = 0;
-
+
} else if ((buttonmask & ButtonPrev) || (buttonmask & ButtonNext)) {
if (_datawheel < WheelDirectionThreshold) {
} else {
prev_marker ();
}
-
+
last_wheel_motion = 0;
-
+
} else if (buttonmask & ButtonShift) {
-
+
/* parameter control */
-
+
if (route_table[0]) {
switch (wheel_shift_mode) {
case WheelShiftGain:
step_pan_left ();
}
break;
-
+
case WheelShiftMarker:
break;
-
+
case WheelShiftMaster:
break;
-
+
}
}
-
+
last_wheel_motion = 0;
-
+
} else {
-
+
switch (wheel_mode) {
case WheelTimeline:
scroll ();
break;
-
+
case WheelScrub:
scrub ();
break;
-
+
case WheelShuttle:
shuttle ();
break;
float speed;
uint64_t now;
int dir;
-
+
now = g_get_monotonic_time();
-
+
if (_datawheel < WheelDirectionThreshold) {
dir = 1;
} else {
dir = -1;
}
-
+
if (dir != last_wheel_dir) {
/* changed direction, start over */
speed = 0.1f;
} else {
if (last_wheel_motion != 0) {
/* 10 clicks per second => speed == 1.0 */
-
+
speed = 100000.0f / (float) (now - last_wheel_motion)
-
+
} else {
-
+
/* start at half-speed and see where we go from there */
-
+
speed = 0.5f;
}
}
-
+
last_wheel_motion = now;
last_wheel_dir = dir;
-
+
set_transport_speed (speed * dir);
}
if(session->transport_speed() != 0) {
show_mini_meter();
} else {
-
+
switch (wheel_mode) {
case WheelTimeline:
text = "Time";
text = "Shtl";
break;
}
-
+
switch (wheel_shift_mode) {
case WheelShiftGain:
text += ":Gain";
break;
-
+
case WheelShiftPan:
text += ":Pan ";
break;
-
+
case WheelShiftMaster:
text += ":Mstr";
break;
-
+
case WheelShiftMarker:
text += ":Mrkr";
break;
}
-
+
print (1, 0, text.c_str());
}
}
/*
Copyright (C) 2006-2010 Paul Davis
-
+
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
timecode.frames = 29;
wrap = SECONDS;
}
-
+
} else {
if (timecode.frames == 0) {
timecode.frames = 29;
uint32_t bars;
uint32_t beats;
uint32_t ticks;
-
+
BBT_Time ()
: bars (1), beats (1), ticks (0) {}
-
+
BBT_Time (uint32_t ba, uint32_t be, uint32_t t)
: bars (ba), beats (be), ticks (t) {}
BBT_Time (double beats);
-
+
bool operator< (const BBT_Time& other) const {
return bars < other.bars ||
(bars == other.bars && beats < other.beats) ||
(bars >= other.bars && beats >= other.beats) ||
(bars >= other.bars && beats >= other.beats && ticks >= other.ticks);
}
-
+
bool operator== (const BBT_Time& other) const {
return bars == other.bars && beats == other.beats && ticks == other.ticks;
}
return bars != other.bars || beats != other.beats || ticks != other.ticks;
}
};
-
+
}
inline std::ostream&
/*
Copyright (C) 2006-2010 Paul Davis
-
+
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser 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.
rate = a_rate;
drop = (lrintf(100.f * (float)a_rate) == (long)2997);
}
-
+
bool operator== (const Time& other) const {
return negative == other.negative && hours == other.hours &&
minutes == other.minutes && seconds == other.seconds &&
channels > getMaxChannelCount()) return false;
m_stepSize = std::min(stepSize, blockSize);
-
+
// Translate the coefficients
// from their "convenient" 60dB convergence-time values
// to real coefficients
AmplitudeFollower::getParameterDescriptors() const
{
ParameterList list;
-
+
ParameterDescriptor att;
att.identifier = "attack";
att.name = "Attack time";
float previn = m_previn;
FeatureSet returnFeatures;
-
+
float val;
float peak = 0.0f;
for (size_t i = 0; i < m_stepSize; ++i) {
val = fabs(inputBuffers[0][i]);
-
+
if (val < previn) {
val = val + (previn - val) * m_relaxcoef;
} else {
std::string getMaker() const;
int getPluginVersion() const;
std::string getCopyright() const;
-
+
OutputList getOutputDescriptors() const;
-
+
ParameterList getParameterDescriptors() const;
float getParameter(std::string paramid) const;
void setParameter(std::string paramid, float newval);
out = jack_port_get_buffer (output_port, nframes);
memcpy (out, in, sizeof (jack_default_audio_sample_t) * nframes);
-
+
for (i = 0; i < loopsize; ++i) {
fooey (nframes);
}
-
+
last_load = jack_cpu_load (client);
if ((at_loop += nframes) >= at_loop_size) {
}
free (ports);
-
+
ports = jack_get_ports (client, NULL, NULL,
JackPortIsPhysical|JackPortIsInput);
if (ports == NULL) {
sqlite3_exec(db, "INSERT INTO lookup VALUES (40, '(Type 40)')", 0, 0, 0);
sqlite3_exec(db, "INSERT INTO lookup VALUES (41, '(Type 41)')", 0, 0, 0);
sqlite3_exec(db, "INSERT INTO lookup VALUES (42, '(Type 42)')", 0, 0, 0);
-
+
/* Assign type and property values to names */
sqlite3_exec(db, "UPDATE data SET property = (SELECT name FROM lookup WHERE property = key), type = (SELECT name FROM lookup WHERE type = key)", 0, 0, 0);
sqlite3_exec(db, "DROP TABLE lookup", 0, 0, 0);
}
DEBUG(" offset: %d\n", dataOffset);
DEBUG(" length: %d\n", dataLength);
-
+
if (currentType == 21) {
char* string = (char*) malloc((uint32_t) dataLength);
fseek(file, dataOffset, SEEK_SET);
options = new XMLNode ("RouteGroups");
/* add master, default 2in/2out */
-
+
XMLNode* master = new_route_node ();
master->add_property ("name", "master");
set_route_node_channels (master, 2, 2, false);
-
+
XMLNode* tempo_map = new XMLNode ("TempoMap");
XMLNode* tempo = new XMLNode ("Tempo");
tempo->add_property ("start", "1|1|0");
connection = new XMLNode ("Connection");
connection->add_property ("other", "system:playback_2");
port->add_child_nocopy (*connection);
-
+
session->add_child_nocopy (*options);
session->add_child_nocopy (*sources);
session->add_child_nocopy (*regions);
audiofile_path_vector.push_back ("interchange");
audiofile_path_vector.push_back (session_name);
audiofile_path_vector.push_back ("audiofiles");
-
+
dir = Glib::build_filename (audiofile_path_vector);
g_mkdir_with_parents (dir.c_str(), 0775);
add_id (playlist);
playlist->add_property ("type", "audio");
playlist->add_property ("frozen", "no");
-
+
return playlist;
}
diskstream->add_property ("flags", "Recordable");
diskstream->add_property ("speed", "1");
diskstream->add_property ("channels", "1");
-
+
return diskstream;
}
void
XMLNode* output_io;
char sbuf[256];
string name = route->property ("name")->value();
-
+
legalize_name (name);
output_io = new XMLNode ("IO");
add_id (output_io);
output_io->add_property ("direction", "Output");
output_io->add_property ("default-type", "audio");
-
+
input_io = new XMLNode ("IO");
route->add_child_nocopy (*input_io);
input_io->add_property ("name", name);
XMLNode* port = new XMLNode ("Port");
output_io->add_child_nocopy (*port);
port->add_property ("type", "audio");
-
+
snprintf (sbuf, sizeof (sbuf), "%s/audio_out %d", name.c_str(), i+1);
-
+
port->add_property ("name", sbuf);
XMLNode* connection = new XMLNode ("Connection");
snprintf (sbuf, sizeof (sbuf), "system:playback_1");
}
}
-
+
connection->add_property ("other", sbuf);
port->add_child_nocopy (*connection);
}
XMLNode* port = new XMLNode ("Port");
input_io->add_child_nocopy (*port);
port->add_property ("type", "audio");
-
+
snprintf (sbuf, sizeof (sbuf), "%s/audio_out %d", name.c_str(), i+1);
-
+
port->add_property ("name", sbuf);
XMLNode* connection = new XMLNode ("Connection");
outs->add_property ("output", name);
outs->add_property ("type", "main-outs");
outs->add_property ("role", "Main");
-
+
/* Panner setup */
XMLNode* panner = new XMLNode ("Panner");
outs->add_child_nocopy (*panner);
-
+
panner->add_property ("linked", "no");
panner->add_property ("link-direction", "SameDirection");
panner->add_property ("bypassed", "no");
spanner->add_property ("type", "Equal Power Stereo");
spanner->add_property ("muted", "no");
spanner->add_property ("mono", "no");
-
+
XMLNode* spc = new XMLNode ("Controllable");
spanner->add_child_nocopy (*spc);
add_id (spc);
region_extra->add_child_nocopy (*gui_extra);
region->add_child_nocopy (*region_extra);
-
+
/* boilerplate */
-
+
region->add_property ("ancestral-start", "0");
region->add_property ("ancestral-start", "0");
region->add_property ("ancestral-length", "0");
add_id (source);
source->add_property ("type", "audio");
source->add_property ("flags", "CanRename");
-
+
sources->add_child_nocopy (*source);
-
+
return source;
}
int major;
int minor;
int micro;
-
+
major = version / 1000;
minor = version - (major * 1000);
micro = version - (major * 1000) - (minor * 100);
session->add_property ("version", sbuf);
session->add_property ("name", session_name);
-
+
char **tracks;
int numtracks;
sqlite3_get_table(db, "SELECT value FROM data WHERE object IN (SELECT value FROM data WHERE object IN (SELECT object FROM data WHERE property = 'OMFI:OOBJ:ObjClass' AND value = 'CMOB' LIMIT 1) AND property = 'OMFI:MOBJ:Slots')", &tracks, &numtracks, 0, 0);
}
sqlite3_free_table(rate);
-
+
char **items;
int itemCount;
//sqlite3_get_table(db, sqlite3_mprintf("SELECT d3.value FROM data d1, data d2, data d3 WHERE d1.object LIKE '%s' AND d1.property LIKE 'OMFI:MSLT:Segment' AND d2.object LIKE d1.value AND d2.property LIKE 'OMFI:SEQU:Components' AND d3.object LIKE d2.value", tracks[i]), &items, &itemCount, 0, 0);
int lenCount;
double length = 0.0;
int lenFrames = 0;
-
+
region = 0;
sqlite3_get_table(db, sqlite3_mprintf("SELECT value FROM data WHERE object = %s AND property = 'OMFI:CPNT:Length' LIMIT 1", items[j]), &len, &lenCount, 0, 0);
lenFrames = atoi(len[1]);
length = lenFrames * frame_rate;
-
+
if (!strcmp(type[1], "TRAN")) {
position -= length;
if (sourceFileCount > 0) {
uint32_t sfOffs;
uint32_t sfLen;
-
+
if (get_offset_and_length (sourceFile[2], sourceFile[3], sfOffs, sfLen)) {
char *sfBuf = read_name (sfOffs, sfLen);
-
+
if ((sinfo = get_known_source (sfBuf)) == 0) {
cerr << "Reference to unknown source [" << sfBuf << "]1" << endl;
return -1;
}
-
+
free (sfBuf);
} else {
cerr << "offs/len illegal\n";
cerr << "Reference to unknown source [" << fallbackFile[1] << "]2" << endl;
return -1;
}
-
+
} else {
cerr << "no fallback file\n";
}
sqlite3_free_table(fallbackFile);
}
-
+
if (sinfo) {
-
+
region = new_region_node ();
playlist->add_child_nocopy (*region);
-
+
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (position * sample_rate));
region->add_property ("position", sbuf);
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (length * sample_rate));
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (start * frame_rate * sample_rate));
region->add_property ("start", sbuf);
set_region_sources (region, sinfo);
-
+
route_max_channels = max (route_max_channels, sinfo->channels);
}
if (get_offset_and_length (sourceFile[2], sourceFile[3], sfOffs, sfLen)) {
cerr << "get source file from " << sfOffs << " + " << sfLen << endl;
char *sfBuf = read_name (sfOffs, sfLen);
-
+
if ((sinfo = get_known_source (sfBuf)) == 0) {
cerr << "Reference to unknown source [" << sfBuf << ']' << endl;
return -1;
region = new_region_node ();
playlist->add_child_nocopy (*region);
-
+
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (position * sample_rate));
region->add_property ("position", sbuf);
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (length * sample_rate));
snprintf (sbuf, sizeof (sbuf), "%" PRId64, llrintf (start * frame_rate * sample_rate));
region->add_property ("start", sbuf);
set_region_sources (region, sinfo);
-
+
route_max_channels = max (route_max_channels, sinfo->channels);
}
}
/* finalize route information */
-
+
cerr << "Set up track with " << route_max_channels << " channels" << endl;
- set_route_node_channels (route, route_max_channels, route_max_channels, true);
+ set_route_node_channels (route, route_max_channels, route_max_channels, true);
sqlite3_free_table(items);
}
{ "version", 1, 0, 'v' },
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
- };
+ };
int option_index = 0;
print_help (execname);
/*NOTREACHED*/
}
-
+
OMF omf;
if (version) {
XMLNode* diskstreams;
XMLNode* locations;
XMLNode* options;
-
+
XMLNode* new_region_node ();
XMLNode* new_source_node ();
XMLNode* new_route_node ();
XMLNode* new_playlist_node ();
XMLNode* new_diskstream_node ();
-
+
typedef std::map<std::string,SourceInfo*> KnownSources;
KnownSources known_sources;
-
+
SourceInfo* get_known_source (const char*);
char* read_name (size_t offset, size_t length);
bool get_offset_and_length (const char* offstr, const char* lenstr, uint32_t& offset, uint32_t& len);
else
return x;
}
-
+
uint32_t e32(uint32_t x)
{
if (bigEndian)
else
return x;
}
-
+
uint64_t e64(uint64_t x)
{
if (bigEndian)
else
return x;
}
-
+
};
#endif /* __ardour_omftool__ */
int n = 0;
int nfiles = 0;
int quiet = 0;
-
+
while (1) {
if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
break;
return 0;
}
}
-
+
if (optind < argc) {
name_template = argv[optind];
} else {
if (!quiet) {
printf ("# Discovered %d files using %s\n", n, name_template);
}
-
+
nfiles = n;
files = (int *) malloc (sizeof (int) * nfiles);
#ifdef HAVE_MMAP
if (!quiet) {
printf ("# BW @ %lu %.3f seconds bandwidth %.4f MB/sec\n", (long unsigned int)_read, elapsed/1000000.0, bandwidth);
}
-
+
total_time += elapsed;
++cnt;
} testRecord;
static vector<testRecord> gTestSet;
-
+
static vector<string> gValidSwitchList;
static vector<string> gSwitchDescriptionList;
}
OK &= !(system_memlock_amount() == 0);
-
+
return OK;
}
printf(" Options are as follows:\n");
printf("\n");
printf("\n");
-
+
vector<testRecord>::iterator itr;
-
+
for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
printf("%20s %s :\t%s\n", (*itr).switchText.c_str(), (*itr).swOptionText.c_str(), (*itr).descriptionText.c_str());
}
printf("\n");
-
+
return true;
}
DefineSwitches()
{
testRecord rec;
-
+
// Global switches
rec.switchText = "-a";
rec.swOptionText = "";
vector<testRecord>::iterator itr;
bool OK = true;
int i;
-
+
if (argc == 1) {
gSwitchesReceived.push_back("-a");
}
break;
}
}
-
+
if (OK && itr != gTestSet.end()) {
// Known option switch found
gSwitchesReceived.push_back(tmp);
if (OK) {
// All switches are at least valid, now check to make sure they are all valid to
// be used together.
-
+
if (gSwitchesReceived.size() > 1) {
// make sure help is not mixed with other options
vector<string>::iterator swItr;
bool OK = true;
vector<string>::iterator itr;
vector<testRecord>::iterator testItr;
-
+
for (itr = gSwitchesReceived.begin(); itr != gSwitchesReceived.end(); ++itr) {
for (testItr = gTestSet.begin(); testItr != gTestSet.end(); ++testItr) {
if ((*itr) == (*testItr).switchText) {
break;
}
}
-
+
bool result;
if ((*testItr).hasOption) {
result = ((*testItr).opFunctionPtr((*testItr).optionArg) != 0);
OK &= result;
}
-
+
return OK;
}
char **argv)
{
int status = 0;
-
+
DefineSwitches();
if (ParseSwitches(argc, argv)) {
int c = 0;
char const * name_template = 0;
int samplerate;
-
+
while (1) {
if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
break;
if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
break;
}
-
+
int flags = O_RDONLY;
int fd = open (path, flags, 0644);
}
samplerate = format_info.samplerate;
-
+
sndfiles.push_back (sf);
}
cout << "Discovered " << sndfiles.size() << " files using " << name_template << endl;
-
+
data = new float[block_size];
uint64_t read = 0;
-
+
while (true) {
gint64 before;
before = g_get_monotonic_time();
read += block_size;
gint64 elapsed = g_get_monotonic_time() - before;
double bandwidth = ((sndfiles.size() * block_size * sample_size)/1048576.0) / (elapsed/1000000.0);
-
+
printf ("BW @ %Lu %.3f seconds bandwidth %.4f MB/sec\n", read, elapsed/1000000.0, bandwidth);
}
int option_index = 0;
int c = 0;
-
+
while (1) {
if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
break;
format_info.samplerate = samplerate;
format_info.channels = channels;
-
+
if (strcasecmp (header_format, "wav") == 0) {
format_info.format |= SF_FORMAT_WAV;
suffix = ".wav";
usage ();
return 0;
}
-
+
string tmpdirname = Glib::build_filename (dirname, "sftest");
if (g_mkdir_with_parents (tmpdirname.c_str(), 0755)) {
cerr << "Cannot create output directory\n";
ss << "sf-";
ss << n;
ss << suffix;
-
+
path = Glib::build_filename (tmpdirname, ss.str());
int flags = O_RDWR|O_CREAT|O_TRUNC;
cout << endl;
cout << "Format is " << suffix << ' ' << channels << " channel" << (channels > 1 ? "s" : "") << " written in chunks of " << block_size << " frames, synced ? " << (with_sync ? "yes" : "no") << endl;
}
-
+
data = new float[block_size*channels];
uint64_t written = 0;
max_bandwidth = max (max_bandwidth, bandwidth);
min_bandwidth = min (min_bandwidth, bandwidth);
-
+
if (!quiet) {
cout << "BW @ " << written << " frames (" << ds.str() << " minutes) = " << (bandwidth/1048576.0) << " MB/sec " << bandwidth / data_rate << " x faster than necessary " << endl;
}
}
cout << "Done.\n";
}
-
+
return 0;
}