take reverse width into account when labelling signals in panner2d ; better way to...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 25 Feb 2011 03:20:47 +0000 (03:20 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 25 Feb 2011 03:20:47 +0000 (03:20 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@8956 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/panner2d.cc
gtk2_ardour/panner2d.h
libs/ardour/lv2_plugin.cc
libs/ardour/route.cc
libs/panners/vbap/vbap.cc

index 51c42160ced220b9303cfcbc7ebb3dd02299f3d7..688ce93068cc6fc9934f8bcf59ddd40dca61df9e 100644 (file)
@@ -68,6 +68,7 @@ Panner2d::Panner2d (boost::shared_ptr<Panner> p, int32_t h)
         , position (AngularVector (0.0, 0.0), "")
         , width (0)
         , height (h)
+        , last_width (0)
 {
        panner->StateChanged.connect (connections, invalidator (*this), boost::bind (&Panner2d::handle_state_change, this), gui_context());
 
@@ -106,27 +107,7 @@ Panner2d::reset (uint32_t n_inputs)
                pucks.resize (n_inputs);
        }
                                                
-       switch (n_inputs) {
-       case 0:
-               break;
-
-       case 1:
-               pucks[0]->set_text ("");
-               break;
-
-       case 2:
-               pucks[0]->set_text ("R");
-               pucks[1]->set_text ("L");
-               break;
-
-       default:
-               for (uint32_t i = 0; i < n_inputs; ++i) {
-                       char buf[64];
-                       snprintf (buf, sizeof (buf), "%" PRIu32, i + 1);
-                       pucks[i]->set_text (buf);
-               }
-               break;
-       }
+        label_pucks ();
 
         for (uint32_t i = 0; i < n_inputs; ++i) {
                 pucks[i]->position = panner->signal_position (i);
@@ -210,10 +191,49 @@ Panner2d::handle_state_change ()
        queue_draw ();
 }
 
+void
+Panner2d::label_pucks ()
+{
+        double w = panner->pannable()->pan_width_control->get_value();
+        uint32_t sz = pucks.size();
+
+       switch (sz) {
+       case 0:
+               break;
+
+       case 1:
+               pucks[0]->set_text ("");
+               break;
+
+       case 2:
+                if (w  >= 0.0) {
+                        pucks[0]->set_text ("R");
+                        pucks[1]->set_text ("L");
+                } else {
+                        pucks[0]->set_text ("L");
+                        pucks[1]->set_text ("R");
+                }
+               break;
+
+       default:
+               for (uint32_t i = 0; i < sz; ++i) {
+                       char buf[64];
+                        if (w >= 0.0) {
+                                snprintf (buf, sizeof (buf), "%" PRIu32, i + 1);
+                        } else {
+                                snprintf (buf, sizeof (buf), "%" PRIu32, sz - i);
+                        }
+                       pucks[i]->set_text (buf);
+               }
+               break;
+       }
+}
+
 void
 Panner2d::handle_position_change ()
 {
        uint32_t n;
+        double w = panner->pannable()->pan_width_control->get_value();
 
         position.position = AngularVector (panner->pannable()->pan_azimuth_control->get_value() * 360.0, 0.0);
 
@@ -221,6 +241,13 @@ Panner2d::handle_position_change ()
                 pucks[i]->position = panner->signal_position (i);
         }
 
+        if (w * last_width <= 0) {
+                /* changed sign */
+                label_pucks ();
+        }
+
+        last_width = w;
+
         vector<Speaker>& speakers (panner->get_speakers()->speakers());
 
        for (n = 0; n < targets.size(); ++n) {
@@ -274,9 +301,17 @@ Panner2d::find_closest_object (gdouble x, gdouble y)
                }
        }
 
-       if (best_distance > 20) { // arbitrary 
-               return 0;
-       }
+        if (height > 100) {
+                /* "big" */
+                if (best_distance > 30) { // arbitrary 
+                        return 0;
+                }
+        } else {
+                /* "small" */
+                if (best_distance > 10) { // arbitrary 
+                        return 0;
+                }
+        }
 
        return closest;
 }
@@ -326,7 +361,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
 
        /* horizontal line of "crosshairs" */
 
-       cairo_set_source_rgb (cr, 0.0, 0.1, 0.7);
+        cairo_set_source_rgba (cr, 0.282, 0.517, 0.662, 1.0);
        cairo_move_to (cr, 0.5, height/2.0+0.5);
        cairo_line_to (cr, width+0.5, height/2+0.5);
        cairo_stroke (cr);
@@ -359,54 +394,18 @@ Panner2d::on_expose_event (GdkEventExpose *event)
         if (pucks.size() > 1) {
                 /* arc to show "diffusion" */
 
-                cairo_move_to (cr, width/2, height/2);
-
-                double max_angle = 0.0;
-                double min_angle = DBL_MAX;
-
-                for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) {
-                        max_angle = max ((*i)->position.azi, max_angle);
-                        min_angle = min ((*i)->position.azi, min_angle);
-                }
-                
-                /* if the angle between the max & min is bigger than 180, flip
-                   them to use the opposite angle for the display. this
-                   matches the psycho-acoustic perception of this condition
-                   too, in almost all conditions that VBAP will handle.
-                */
-                
-                if (fabs (max_angle - min_angle) > 180.0) {
-                        swap (max_angle, min_angle);
-                }
-
-                /* convert to radians */
-
-                min_angle = (min_angle / 360.0) * 2.0 * M_PI;
-                max_angle = (max_angle / 360.0) * 2.0 * M_PI;
-
-                /* cairo has coordinates increasing in a clockwise direction */
-
-                max_angle = (2 * M_PI) - max_angle;
-                min_angle = (2 * M_PI) - min_angle;
-
-                /* the above transformation will have reversed the min/max relationship */
-
-                swap (min_angle, max_angle);
-
-                if (min_angle > max_angle) {
-                        /* swapped because they span the zero position: draw two arc segments to span zero.
-                           XXX there must be a way to get cairo to do this in a single call
-                        */
-                        cairo_arc_negative (cr, width/2, height/2, dimen/2.0, max_angle, 0.0);
-                        cairo_arc_negative (cr, width/2, height/2, dimen/2.0, 0.0, min_angle);
-                } else {
-                        cairo_arc (cr, width/2, height/2, dimen/2.0, min_angle, max_angle);
-                }
-
+                double width_angle = fabs (panner->pannable()->pan_width_control->get_value()) * 2 * M_PI;
+                double position_angle = (2 * M_PI) - panner->pannable()->pan_azimuth_control->get_value() * 2 * M_PI;
 
+                cairo_save (cr);
+                cairo_translate (cr, width/2, height/2);
+                cairo_rotate (cr, position_angle - width_angle);
+                cairo_move_to (cr, 0, 0);
+                cairo_arc_negative (cr, 0, 0, dimen/2.0, width_angle * 2.0, 0.0);
                 cairo_close_path (cr);
                 cairo_set_source_rgba (cr, 1.0, 0.419, 0.419, 0.45);
                 cairo_fill (cr);
+                cairo_restore (cr);
         }
 
        if (!panner->bypassed()) {
@@ -426,7 +425,6 @@ Panner2d::on_expose_event (GdkEventExpose *event)
 
                 if (pucks.size() > 1) {
                         for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) {
-                                
                                 Target* puck = *i;
                                 
                                 if (puck->visible) {
index 4fbf0e131fd5f06e50aae5ff6e5816f9b296e1b3..609840bbfe02ee6cab3c7c761ac71432f1691c7e 100644 (file)
@@ -117,6 +117,7 @@ class Panner2d : public Gtk::DrawingArea
        int     width;
        int     height;
         int     dimen; 
+        double  last_width;
 
        bool bypassflag;
 
@@ -130,6 +131,7 @@ class Panner2d : public Gtk::DrawingArea
        void toggle_bypass ();
        void handle_state_change ();
        void handle_position_change ();
+        void label_pucks ();
 
        PBD::ScopedConnectionList connections;
 
index b8fa27dc2f2a5c9ec252336264a2c4566ef5af8a..9ee0fe61d926692259a0615222a2fe408b0d2236 100644 (file)
@@ -119,7 +119,7 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, framecnt_t rate)
 
        if (_instance == 0) {
                error << _("LV2: Failed to instantiate plugin ")
-                     << slv2_plugin_get_uri(plugin) << endl;
+                     << slv2_value_as_string (slv2_plugin_get_uri(plugin)) << endmsg;
                throw failed_constructor();
        }
 
@@ -130,7 +130,7 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, framecnt_t rate)
        if (slv2_plugin_has_feature(plugin, world.in_place_broken)) {
                error << string_compose(
                                _("LV2: \"%1\" cannot be used, since it cannot do inplace processing"),
-                               slv2_value_as_string(_name));
+                               slv2_value_as_string(_name)) << endmsg;
                slv2_value_free(_name);
                slv2_value_free(_author);
                throw failed_constructor();
index 5550bb3f9bf41f05d1ff2ca6d168b9fdf9ae9519..33e392345406bc2696afe382b2936c68b84eb7aa 100644 (file)
@@ -870,6 +870,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
 {
        assert (processor != _meter);
        assert (processor != _main_outs);
+
+        DEBUG_TRACE (DEBUG::Processors, string_compose ("%1 adding processor %2\n", name(), processor->name()));
        
        ChanCount old_pms = processor_max_streams;
 
@@ -916,7 +918,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
                                configure_processors_unlocked (0); // it worked before we tried to add it ...
-                               cerr << "configure failed\n";
                                return -1;
                        }
                }
index eff8a5ee43d40cc03c05db3e097e5fadeb3ba3ab..b053b670f92f2e5e39b4eb5163acaffeab306d02 100644 (file)
@@ -99,7 +99,8 @@ VBAPanner::update ()
 
                 /* panner width control is [-1.0 .. 1.0]; we ignore sign, and map to [0 .. 360] degrees
                    so that a width of 1 corresponds to a signal equally present from all directions, 
-                   and a width of zero corresponds to a point source from the "center" (above)
+                   and a width of zero corresponds to a point source from the "center" (above) point
+                   on the perimeter of the speaker array.
                 */
 
                 double w = fabs (_pannable->pan_width_control->get_value()) * 360.0;
@@ -123,13 +124,24 @@ VBAPanner::update ()
                 double degree_step_per_signal = (max_dir - min_dir) / (_signals.size() - 1);
                 double signal_direction = min_dir;
 
-                for (vector<Signal*>::iterator s = _signals.begin(); s != _signals.end(); ++s) {
+                if (w >= 0.0) {
+                        for (vector<Signal*>::iterator s = _signals.begin(); s != _signals.end(); ++s) {
                         
-                        Signal* signal = *s;
+                                Signal* signal = *s;
+                                
+                                signal->direction = AngularVector (signal_direction, 0.0);
+                                compute_gains (signal->desired_gains, signal->desired_outputs, signal->direction.azi, signal->direction.ele);
+                                signal_direction += degree_step_per_signal;
+                        }
+                } else {
+                        for (vector<Signal*>::reverse_iterator s = _signals.rbegin(); s != _signals.rend(); ++s) {
                         
-                        signal->direction = AngularVector (signal_direction, 0.0);
-                        compute_gains (signal->desired_gains, signal->desired_outputs, signal->direction.azi, signal->direction.ele);
-                        signal_direction += degree_step_per_signal;
+                                Signal* signal = *s;
+                                
+                                signal->direction = AngularVector (signal_direction, 0.0);
+                                compute_gains (signal->desired_gains, signal->desired_outputs, signal->direction.azi, signal->direction.ele);
+                                signal_direction += degree_step_per_signal;
+                        }
                 }
 
         } else if (_signals.size() == 1) {