2 Copyright (C) 2010 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include "pbd/error.h"
20 #include "pbd/convert.h"
21 #include "pbd/locale_guard.h"
23 #include "ardour/speaker.h"
24 #include "ardour/speakers.h"
28 using namespace ARDOUR
;
32 Speaker::Speaker (int i
, const AngularVector
& position
)
38 Speaker::Speaker (Speaker
const & o
)
47 Speaker::operator= (Speaker
const & o
)
61 Speaker::move (const AngularVector
& new_position
)
63 _angles
= new_position
;
64 _angles
.cartesian (_coords
);
66 PositionChanged (); /* EMIT SIGNAL */
73 Speakers::Speakers (const Speakers
& s
)
75 _speakers
= s
._speakers
;
78 Speakers::~Speakers ()
83 Speakers::operator= (const Speakers
& s
)
86 _speakers
= s
._speakers
;
92 Speakers::dump_speakers (ostream
& o
)
94 for (vector
<Speaker
>::iterator i
= _speakers
.begin(); i
!= _speakers
.end(); ++i
) {
95 o
<< "Speaker " << (*i
).id
<< " @ "
96 << (*i
).coords().x
<< ", " << (*i
).coords().y
<< ", " << (*i
).coords().z
97 << " azimuth " << (*i
).angles().azi
98 << " elevation " << (*i
).angles().ele
99 << " distance " << (*i
).angles().length
105 Speakers::clear_speakers ()
112 Speakers::add_speaker (const AngularVector
& position
)
114 int id
= _speakers
.size();
116 _speakers
.push_back (Speaker (id
, position
));
125 Speakers::remove_speaker (int id
)
127 for (vector
<Speaker
>::iterator i
= _speakers
.begin(); i
!= _speakers
.end(); ++i
) {
129 i
= _speakers
.erase (i
);
137 Speakers::move_speaker (int id
, const AngularVector
& new_position
)
139 for (vector
<Speaker
>::iterator i
= _speakers
.begin(); i
!= _speakers
.end(); ++i
) {
141 (*i
).move (new_position
);
149 Speakers::setup_default_speakers (uint32_t n
)
151 /* default assignment of speaker position for n speakers */
157 add_speaker (AngularVector (0.0, 0.0));
161 add_speaker (AngularVector (0.0, 0.0));
162 add_speaker (AngularVector (180.0, 0,0));
166 /* top, bottom kind-of-left & bottom kind-of-right */
167 add_speaker (AngularVector (90.0, 0.0));
168 add_speaker (AngularVector (215.0, 0,0));
169 add_speaker (AngularVector (335.0, 0,0));
172 /* clockwise from top left */
173 add_speaker (AngularVector (135.0, 0.0));
174 add_speaker (AngularVector (45.0, 0.0));
175 add_speaker (AngularVector (335.0, 0.0));
176 add_speaker (AngularVector (215.0, 0.0));
181 double degree_step
= 360.0 / n
;
185 /* even number of speakers? make sure the top two are either side of "top".
186 otherwise, just start at the "top" (90.0 degrees) and rotate around
190 deg
= 90.0 - degree_step
;
194 for (i
= 0; i
< n
; ++i
, deg
+= degree_step
) {
195 add_speaker (AngularVector (deg
, 0.0));
202 Speakers::get_state ()
204 XMLNode
* node
= new XMLNode (X_("Speakers"));
206 LocaleGuard
lg (X_("POSIX"));
208 for (vector
<Speaker
>::const_iterator i
= _speakers
.begin(); i
!= _speakers
.end(); ++i
) {
209 XMLNode
* speaker
= new XMLNode (X_("Speaker"));
211 snprintf (buf
, sizeof (buf
), "%.12g", (*i
).angles().azi
);
212 speaker
->add_property (X_("azimuth"), buf
);
213 snprintf (buf
, sizeof (buf
), "%.12g", (*i
).angles().ele
);
214 speaker
->add_property (X_("elevation"), buf
);
215 snprintf (buf
, sizeof (buf
), "%.12g", (*i
).angles().length
);
216 speaker
->add_property (X_("distance"), buf
);
218 node
->add_child_nocopy (*speaker
);
225 Speakers::set_state (const XMLNode
& node
, int /*version*/)
227 XMLNodeConstIterator i
;
228 const XMLProperty
* prop
;
230 LocaleGuard
lg (X_("POSIX"));
235 for (i
= node
.children().begin(); i
!= node
.children().end(); ++i
, ++n
) {
236 if ((*i
)->name() == X_("Speaker")) {
237 if ((prop
= (*i
)->property (X_("azimuth"))) == 0) {
238 warning
<< _("Speaker information is missing azimuth - speaker ignored") << endmsg
;
241 a
= atof (prop
->value());
243 if ((prop
= (*i
)->property (X_("elevation"))) == 0) {
244 warning
<< _("Speaker information is missing elevation - speaker ignored") << endmsg
;
247 e
= atof (prop
->value());
249 if ((prop
= (*i
)->property (X_("distance"))) == 0) {
250 warning
<< _("Speaker information is missing distance - speaker ignored") << endmsg
;
253 d
= atof (prop
->value());
255 add_speaker (AngularVector (a
, e
, d
));