Merge branch 'master' into ardour-merge

Conflicts:
	gtk2_ardour/time_axis_view_item.cc
	libs/backends/wavesaudio/waves_audiobackend.h
	libs/backends/wavesaudio/wavesapi/devicemanager/WCMRPortAudioDeviceManager.cpp
This commit is contained in:
Paul Davis 2014-09-02 10:28:52 -04:00
commit c7af2444a7
42 changed files with 617 additions and 493 deletions

View file

@ -211,14 +211,15 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, _feedback_exists (false) , _feedback_exists (false)
, _dsp_load_adjustment (0) , _dsp_load_adjustment (0)
, _hd_load_adjustment (0) , _hd_load_adjustment (0)
, _dsp_load_label(0) , _dsp_load_label (0)
, _hd_load_label(0) , _hd_load_label (0)
, _hd_remained_time_label(0) , _hd_remained_time_label (0)
, editor (0) , editor (0)
, mixer (0) , mixer (0)
, _bit_depth_button(0) , _tracks_button (0)
, _sample_rate_button(0) , _bit_depth_button (0)
, _frame_rate_button(0) , _sample_rate_button (0)
, _frame_rate_button (0)
, splash (0) , splash (0)
{ {
Gtkmm2ext::init(localedir); Gtkmm2ext::init(localedir);
@ -4026,15 +4027,17 @@ ARDOUR_UI::sr_mismatch_dialog (framecnt_t desired, framecnt_t actual)
ArdourDialog dialog (_("Sample Rate Mismatch"), true); ArdourDialog dialog (_("Sample Rate Mismatch"), true);
Label message (string_compose (_("\ Label message (string_compose (_("\
This session was created with a sample rate of %1 Hz, but\n\ This session was created with a sample rate of %1 Hz, but\n\
%2 is currently running at %3 Hz. If you load this session,\n\ %2 is currently running at %3 Hz. If you load this session,\n\
device will be switched to the session sample rate value. \n\
If an attemp to switch the device is unsuccessful\n\
audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual)); audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
image->set_alignment(ALIGN_CENTER, ALIGN_TOP); image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12); hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
hbox->pack_end (message, PACK_EXPAND_PADDING, 12); hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6); dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
dialog.add_button (_("Do not load session"), RESPONSE_REJECT); dialog.add_button (_("Cancel"), RESPONSE_REJECT);
dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT); dialog.add_button (_("Accept"), RESPONSE_ACCEPT);
dialog.set_default_response (RESPONSE_ACCEPT); dialog.set_default_response (RESPONSE_ACCEPT);
dialog.set_position (WIN_POS_CENTER); dialog.set_position (WIN_POS_CENTER);
message.show(); message.show();

View file

@ -227,6 +227,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void focus_on_clock (); void focus_on_clock ();
AudioClock* big_clock; AudioClock* big_clock;
WavesButton* _tracks_button;
void on_tracks_button (WavesButton*);
WavesButton* _bit_depth_button; WavesButton* _bit_depth_button;
WavesButton* _sample_rate_button; WavesButton* _sample_rate_button;
WavesButton* _frame_rate_button; WavesButton* _frame_rate_button;

View file

@ -90,6 +90,8 @@ ARDOUR_UI::create_editor ()
_bit_depth_button = &editor->get_waves_button("bit_depth_button"); _bit_depth_button = &editor->get_waves_button("bit_depth_button");
_sample_rate_button = &editor->get_waves_button("sample_rate_button"); _sample_rate_button = &editor->get_waves_button("sample_rate_button");
_frame_rate_button = &editor->get_waves_button("frame_rate_button"); _frame_rate_button = &editor->get_waves_button("frame_rate_button");
_tracks_button = &editor->get_waves_button("tracks_button");
} }
catch (failed_constructor& err) { catch (failed_constructor& err) {
@ -99,6 +101,7 @@ ARDOUR_UI::create_editor ()
_bit_depth_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_bit_depth_button)); _bit_depth_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_bit_depth_button));
_sample_rate_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_sample_rate_button)); _sample_rate_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_sample_rate_button));
_frame_rate_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_frame_rate_button)); _frame_rate_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_frame_rate_button));
_tracks_button->signal_clicked.connect(sigc::mem_fun (*this, &ARDOUR_UI::on_tracks_button));
editor->Realized.connect (sigc::mem_fun (*this, &ARDOUR_UI::editor_realized)); editor->Realized.connect (sigc::mem_fun (*this, &ARDOUR_UI::editor_realized));
editor->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), true)); editor->signal_window_state_event().connect (sigc::bind (sigc::mem_fun (*this, &ARDOUR_UI::main_window_state_event_handler), true));
@ -106,6 +109,12 @@ ARDOUR_UI::create_editor ()
return 0; return 0;
} }
void
ARDOUR_UI::on_tracks_button (WavesButton*)
{
about->show ();
}
void void
ARDOUR_UI::on_bit_depth_button (WavesButton*) ARDOUR_UI::on_bit_depth_button (WavesButton*)
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

View file

@ -59,8 +59,14 @@ using namespace ARDOUR;
using namespace ARDOUR_UI_UTILS; using namespace ARDOUR_UI_UTILS;
using namespace Gtkmm2ext; using namespace Gtkmm2ext;
Pango::FontDescription TimeAxisViewItem::NAME_FONT; // GZ: Should be moved to config
const double TimeAxisViewItem::NAME_HIGHLIGHT_Y_IDENT = 3.0; #ifdef _WIN32
Pango::FontDescription TimeAxisViewItem::NAME_FONT("Helvetica 8");
#else
Pango::FontDescription TimeAxisViewItem::NAME_FONT("Arial 8");
#endif
const double TimeAxisViewItem::NAME_HIGHLIGHT_Y_INDENT = 1.0;
const double TimeAxisViewItem::NAME_HIGHLIGHT_X_OFFSET = 10.0; const double TimeAxisViewItem::NAME_HIGHLIGHT_X_OFFSET = 10.0;
const double TimeAxisViewItem::NAME_HIGHLIGHT_Y_OFFSET = 5.0; const double TimeAxisViewItem::NAME_HIGHLIGHT_Y_OFFSET = 5.0;
const double TimeAxisViewItem::GRAB_HANDLE_TOP = 2.0; const double TimeAxisViewItem::GRAB_HANDLE_TOP = 2.0;
@ -71,20 +77,19 @@ const double TimeAxisViewItem::REGION_TOP_OFFSET = 2.0;
const double TimeAxisViewItem::REGION_BOTTOM_OFFSET = 3.0; const double TimeAxisViewItem::REGION_BOTTOM_OFFSET = 3.0;
int TimeAxisViewItem::NAME_HEIGHT; int TimeAxisViewItem::NAME_HEIGHT;
double TimeAxisViewItem::NAME_HIGHLIGHT_X_IDENT; double TimeAxisViewItem::NAME_HIGHLIGHT_X_INDENT;
double TimeAxisViewItem::NAME_Y_OFFSET;
double TimeAxisViewItem::NAME_HIGHLIGHT_HEIGHT; double TimeAxisViewItem::NAME_HIGHLIGHT_HEIGHT;
double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH; double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
void void
TimeAxisViewItem::set_constant_heights () TimeAxisViewItem::set_constant_heights ()
{ {
NAME_FONT = Pango::FontDescription (ARDOUR_UI::config()->get_canvasvar_SmallFont()); // GZ: FONT IS DEFINED AT THE BEGINNING OF THE FILE
//NAME_FONT = get_font_for_style (X_("TimeAxisViewItemName"));
Gtk::Window win; Gtk::Window win;
Gtk::Label foo; Gtk::Label foo;
win.add (foo); win.add (foo);
int width = 0; int width = 0;
int height = 0; int height = 0;
@ -92,17 +97,17 @@ TimeAxisViewItem::set_constant_heights ()
layout->set_font_description (NAME_FONT); layout->set_font_description (NAME_FONT);
get_pixel_size (layout, width, height); get_pixel_size (layout, width, height);
NAME_HEIGHT = height + 2; NAME_HEIGHT = height;
NAME_HIGHLIGHT_X_IDENT = width + 2; NAME_HIGHLIGHT_X_INDENT = width;
/* Config->get_show_name_highlight) == true: /* Config->get_show_name_highlight) == true:
Y_OFFSET is measured from bottom of the time axis view item. Y_OFFSET is measured from bottom of the time axis view item.
Config->get_show_name_highlight) == false: Config->get_show_name_highlight) == false:
Y_OFFSET is measured from the top of the time axis view item. Y_OFFSET is measured from the top of the time axis view item.
*/ */
NAME_HIGHLIGHT_HEIGHT = NAME_HEIGHT + NAME_HIGHLIGHT_Y_IDENT*2; NAME_HIGHLIGHT_HEIGHT = NAME_HEIGHT + NAME_HIGHLIGHT_Y_INDENT*2;
NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_HEIGHT * 1.5; NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_HEIGHT + 2;
} }
/** /**
@ -226,27 +231,28 @@ TimeAxisViewItem::init (ArdourCanvas::Item* parent, double fpp, uint32_t base_co
{ // always show name highlight { // always show name highlight
double width; double width;
width = trackview.editor().sample_to_pixel(item_duration) - 2.0 + RIGHT_EDGE_SHIFT; width = trackview.editor().sample_to_pixel(item_duration) - 2.0 + RIGHT_EDGE_SHIFT;
name_highlight = new ArdourCanvas::Rectangle (group, name_highlight = new ArdourCanvas::Rectangle (group,
ArdourCanvas::Rect (NAME_HIGHLIGHT_X_OFFSET, ArdourCanvas::Rect (NAME_HIGHLIGHT_X_OFFSET,
NAME_HIGHLIGHT_Y_OFFSET, NAME_HIGHLIGHT_Y_OFFSET,
NAME_HIGHLIGHT_X_OFFSET + 2*NAME_HIGHLIGHT_X_IDENT, NAME_HIGHLIGHT_X_OFFSET + 2*NAME_HIGHLIGHT_X_INDENT,
NAME_HIGHLIGHT_HEIGHT) ); NAME_HIGHLIGHT_HEIGHT + NAME_HIGHLIGHT_Y_OFFSET) );
CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name())); CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name()));
name_highlight->set_data ("timeaxisviewitem", this); name_highlight->set_data ("timeaxisviewitem", this);
name_highlight->set_outline_what (ArdourCanvas::Rectangle::What (0) ); name_highlight->set_outline_what (ArdourCanvas::Rectangle::What (0) );
name_highlight->set_outline_color (RGBA_TO_UINT (0,0,0,255)); name_highlight->set_outline_color (RGBA_TO_UINT (0,0,0,255));
} }
{ {
name_text = new ArdourCanvas::Text (group); name_text = new ArdourCanvas::Text (group);
CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name())); CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name()));
name_text->set_position (ArdourCanvas::Duple (NAME_HIGHLIGHT_X_OFFSET + NAME_HIGHLIGHT_X_IDENT, NAME_HIGHLIGHT_Y_OFFSET + NAME_HIGHLIGHT_Y_IDENT) ); name_text->set_position (ArdourCanvas::Duple (NAME_HIGHLIGHT_X_OFFSET + NAME_HIGHLIGHT_X_IDENT, NAME_HIGHLIGHT_Y_OFFSET + NAME_HIGHLIGHT_Y_IDENT) );
name_text->set(""); name_text->set("");
name_text->set_font_description (NAME_FONT); name_text->set_font_description (NAME_FONT);
if (name_text->text().empty() ) { if (name_text->text().empty()) {
name_highlight->hide(); name_highlight->hide();
} }
} }
@ -558,8 +564,9 @@ TimeAxisViewItem::set_name_text(const string& new_name)
if (!name_text) { if (!name_text) {
return; return;
} }
// This is a workaround.
name_text_width = pixel_width (new_name, NAME_FONT); // Pango returns incorrect width values 1.5*NAME_HIGHLIGHT_X_INDENT
name_text_width = pixel_width (new_name, NAME_FONT) + 1.5*NAME_HIGHLIGHT_X_INDENT;
name_text->set (new_name); name_text->set (new_name);
} }
@ -601,12 +608,12 @@ TimeAxisViewItem::manage_name_highlight ()
high_enough_for_name = true; high_enough_for_name = true;
} }
double highlite_y1 = name_text_width + 2*NAME_HIGHLIGHT_X_IDENT + NAME_HIGHLIGHT_X_OFFSET; double highlite_x1 = name_text_width + 2*NAME_HIGHLIGHT_X_INDENT + NAME_HIGHLIGHT_X_OFFSET;
if (_width < highlite_y1) { if (_width < highlite_x1) {
highlite_y1 = _width; highlite_x1 = _width;
} }
if (highlite_y1 < NAME_HIGHLIGHT_X_OFFSET) { if (highlite_x1 < NAME_HIGHLIGHT_X_OFFSET) {
wide_enough_for_name = false; wide_enough_for_name = false;
} else { } else {
wide_enough_for_name = true; wide_enough_for_name = true;
@ -615,10 +622,10 @@ TimeAxisViewItem::manage_name_highlight ()
if (wide_enough_for_name && high_enough_for_name && !name_text->text().empty() ) { if (wide_enough_for_name && high_enough_for_name && !name_text->text().empty() ) {
name_highlight->set (ArdourCanvas::Rect (NAME_HIGHLIGHT_X_OFFSET, name_highlight->set (ArdourCanvas::Rect (NAME_HIGHLIGHT_X_OFFSET,
NAME_HIGHLIGHT_Y_OFFSET, NAME_HIGHLIGHT_Y_OFFSET,
highlite_y1, highlite_x1,
NAME_HIGHLIGHT_HEIGHT) ); NAME_HIGHLIGHT_HEIGHT + NAME_HIGHLIGHT_Y_OFFSET) );
name_highlight->show(); name_highlight->show();
name_highlight->raise_to_top();
} else { } else {
name_highlight->hide(); name_highlight->hide();
} }
@ -948,8 +955,8 @@ TimeAxisViewItem::manage_name_text ()
visible_name_width = name_text_width; visible_name_width = name_text_width;
if (visible_name_width > _width - NAME_HIGHLIGHT_X_OFFSET - NAME_HIGHLIGHT_X_IDENT) { if (visible_name_width > _width - NAME_HIGHLIGHT_X_OFFSET - NAME_HIGHLIGHT_X_INDENT) {
visible_name_width = _width - NAME_HIGHLIGHT_X_OFFSET - NAME_HIGHLIGHT_X_IDENT; visible_name_width = _width - NAME_HIGHLIGHT_X_OFFSET - NAME_HIGHLIGHT_X_INDENT;
} }
if (visible_name_width < 1) { if (visible_name_width < 1) {
@ -957,6 +964,7 @@ TimeAxisViewItem::manage_name_text ()
} else { } else {
name_text->clamp_width (visible_name_width); name_text->clamp_width (visible_name_width);
name_text->show (); name_text->show ();
name_text->raise_to_top ();
} }
} }

View file

@ -104,7 +104,7 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
// Default sizes, font and spacing // Default sizes, font and spacing
static Pango::FontDescription NAME_FONT; static Pango::FontDescription NAME_FONT;
static void set_constant_heights (); static void set_constant_heights ();
static const double NAME_HIGHLIGHT_Y_IDENT; static const double NAME_HIGHLIGHT_Y_INDENT;
static const double NAME_HIGHLIGHT_X_OFFSET; static const double NAME_HIGHLIGHT_X_OFFSET;
static const double NAME_HIGHLIGHT_Y_OFFSET; static const double NAME_HIGHLIGHT_Y_OFFSET;
static const double GRAB_HANDLE_TOP; static const double GRAB_HANDLE_TOP;
@ -117,9 +117,8 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
of the font used to display the item name. of the font used to display the item name.
*/ */
static int NAME_HEIGHT; static int NAME_HEIGHT;
static double NAME_HIGHLIGHT_X_IDENT; static double NAME_HIGHLIGHT_X_INDENT;
static double NAME_X_OFFSET; static double NAME_X_OFFSET;
static double NAME_Y_OFFSET;
static double NAME_HIGHLIGHT_HEIGHT; static double NAME_HIGHLIGHT_HEIGHT;
static double NAME_HIGHLIGHT_THRESH; static double NAME_HIGHLIGHT_THRESH;

View file

@ -116,7 +116,8 @@ TracksControlPanel::init ()
EngineStateController::instance()->OutputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_audio_output_configuration_changed, this), gui_context()); EngineStateController::instance()->OutputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_audio_output_configuration_changed, this), gui_context());
EngineStateController::instance()->MIDIInputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_midi_input_configuration_changed, this), gui_context()); EngineStateController::instance()->MIDIInputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_midi_input_configuration_changed, this), gui_context());
EngineStateController::instance()->MIDIOutputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_midi_output_configuration_changed, this), gui_context()); EngineStateController::instance()->MIDIOutputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_midi_output_configuration_changed, this), gui_context());
EngineStateController::instance()->DeviceError.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_device_error, this), gui_context());
/* Global configuration parameters update */ /* Global configuration parameters update */
Config->ParameterChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_parameter_changed, this, _1), gui_context()); Config->ParameterChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_parameter_changed, this, _1), gui_context());
@ -1243,6 +1244,21 @@ TracksControlPanel::on_session_settings (WavesButton*)
_session_settings_tab_button.set_active(true); _session_settings_tab_button.set_active(true);
} }
void
TracksControlPanel::on_device_error ()
{
std::string message = _("Device cannot operate properly. Switched to None device.");
MessageDialog msg (message,
false,
Gtk::MESSAGE_WARNING,
Gtk::BUTTONS_OK,
true);
msg.set_position (Gtk::WIN_POS_MOUSE);
msg.set_keep_above (true);
msg.run ();
}
void void
TracksControlPanel::on_multi_out (WavesButton*) TracksControlPanel::on_multi_out (WavesButton*)

View file

@ -115,6 +115,7 @@
void on_audio_output_configuration_changed (); void on_audio_output_configuration_changed ();
void on_midi_input_configuration_changed (); void on_midi_input_configuration_changed ();
void on_midi_output_configuration_changed (); void on_midi_output_configuration_changed ();
void on_device_error ();
void cleanup_input_channels_list(); void cleanup_input_channels_list();
void cleanup_output_channels_list(); void cleanup_output_channels_list();

View file

@ -1,145 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<RouteUI bgnormal="#383838" bgactive="#545454"> <RouteUI bgnormal="#383838" bgactive="#545454">
<Vbox> <Vbox>
<EventBox id="upper_drop_indicator" visible="false" noshowall="true" height="2" bgnormal="#1CA3B3" bgactive="#1CA3B3"/> <EventBox height="1" bgnormal="#494949" bgactive="#494949"/>
<HBox> <EventBox id="upper_drop_indicator" visible="false" noshowall="true" height="2" bgnormal="#1CA3B3" bgactive="#1CA3B3"/>
<VBox> <HBox box.fill="true" box.expand="true">
<EventBox height="1" bgnormal="#494949" bgactive="#494949"/> <VBox>
<HBox box.expand="true" box.fill="true"> <HBox box.expand="true" box.fill="true">
<EventBox id="selected_track_color_box" width="29" bgactive="#5BA55C"> <EventBox id="selected_track_color_box" width="29" bgactive="#5BA55C">
<HBox> <HBox>
<!--<Igor! width="2" below is the shift from RIGHT side of the space>--> <!--<Igor! width="2" below is the shift from RIGHT side of the space>-->
<VBox width="2" box.pack="end"/> <VBox width="2" box.pack="end"/>
<VBox box.pack="end"> <VBox box.pack="end">
<!--<Igor! height="4" below is the shift from TOP side of the space>--> <!--<Igor! height="4" below is the shift from TOP side of the space>-->
<HBox height="4"/> <HBox height="4"/>
<Label id="number_label" <Label id="number_label"
text="32" text="32"
fgnormal="#ffffff" fgnormal="#ffffff"
fgactive="#ffffff" fgactive="#ffffff"
winfont ="Arial Bold 13" winfont ="Arial Bold 13"
macfont ="Helvetica Bold 13"/> macfont ="Helvetica Bold 13"/>
</VBox> </VBox>
</HBox> </HBox>
</EventBox> </EventBox>
<EventBox id="track_color_box" width="6" bgnormal="#5BA55C" bgactive="#5BA55C"/> <EventBox id="track_color_box" width="6" bgnormal="#5BA55C" bgactive="#5BA55C"/>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/> <EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
</HBox> </HBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000" box.pack="end"/> </VBox>
</VBox> <VBox>
<VBox> <!--<Igor! About the track name: height="5" below is the shift from TOP side of the space>-->
<EventBox height="1" bgnormal="#494949" bgactive="#494949"/> <HBox height="5"/>
<!--<Igor! About the track name: height="5" below is the shift from TOP side of the space>--> <HBox width="80"
<HBox height="5"/> id="name_label_home">
<HBox width="80" <HBox width="5"/>
id="name_label_home"> <Label id="name_label"
<HBox width="5"/> winfont ="Arial 10"
<Label id="name_label" macfont ="Helvetica 10"
winfont ="Arial 10" fgnormal="#ffffff"
macfont ="Helvetica 10" fgactive="#ffffff"/>
fgnormal="#ffffff" <FocusEntry id="name_entry"
fgactive="#ffffff"/> width="80"
<FocusEntry id="name_entry" height="20"
width="80" fgnormal="#ffffff"
height="20" winfont ="Arial 10"
fgnormal="#ffffff" macfont ="Helvetica 10"
winfont ="Arial 10" cssname="EditorTrackNameDisplay"
macfont ="Helvetica 10" textcolornormal="#ffffff"
cssname="EditorTrackNameDisplay" textcoloractive="#ffffff"
textcolornormal="#ffffff" textcolorselected="#ffffff"
textcoloractive="#ffffff" noshowall="true"
textcolorselected="#ffffff" visible="false"/>
noshowall="true" </HBox>
visible="false"/> </VBox>
</HBox> <VBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000" box.pack="end"/>
</VBox>
<VBox>
<EventBox height="1" bgnormal="#494949" bgactive="#494949"/>
<HBox>
<iconbutton id="playlist_button"
width="21"
height="20"
normalicon="time_axis_playlist"
activeicon="time_axis_playlist"
prelighticon="time_axis_playlist"/>
<HBox width="3"/>
<HBox> <HBox>
<iconbutton id="playlist_button"
width="21"
height="20"
normalicon="time_axis_playlist"
activeicon="time_axis_playlist"
prelighticon="time_axis_playlist"/>
<HBox width="3"/>
<HBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
<iconbutton id="rec_enable_button"
width="41"
height="20"
normalicon="time_axis_record"
activeicon="time_axis_record_active"
prelighticon="time_axis_record_prelight"
tooltip="Record Enable"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
<iconbutton id="solo_button"
width="41"
height="20"
normalicon="time_axis_solo"
activeicon="time_axis_solo_active"
implicitactiveicon="time_axis_solo_safe"
prelighticon="time_axis_solo_prelight"
tooltip="Solo"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
</HBox>
</HBox>
<HBox>
<VBox width="24"/>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/> <EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox> <VBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/> <iconbutton id="monitor_input_button"
<iconbutton id="rec_enable_button"
width="41" width="41"
height="20" height="20"
normalicon="time_axis_record" normalicon="time_axis_monitor_input"
activeicon="time_axis_record_active" activeicon="time_axis_monitor_input_active"
prelighticon="time_axis_record_prelight" prelighticon="time_axis_monitor_input_prelight"
tooltip="Record Enable"/> tooltip="Input Monitoring"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/> <EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox> </VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/> <EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox> <VBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/> <iconbutton id="mute_button"
<iconbutton id="solo_button"
width="41" width="41"
height="20" height="20"
normalicon="time_axis_solo" normalicon="time_axis_mute"
activeicon="time_axis_solo_active" activeicon="time_axis_mute_active"
implicitactiveicon="time_axis_solo_safe" implicitactiveicon="time_axis_mute_implicit"
prelighticon="time_axis_solo_prelight" prelighticon="time_axis_mute_prelight"
tooltip="Solo"/> tooltip="Mute"/>
<Button id="master_mute_button" ui.orphan="true"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/> <EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox> </VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/> <EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
</HBox> </HBox>
</VBox>
<HBox visible="false" noshowall="true">
<Button id="show_sends_button"/>
<Button id="monitor_disk_button"/>
<Button id="comment_button"/>
<Button id="midi_input_enable_button"/>
<Button id="group_button" text="Grp"/>
<Button id="route_group_button"/>
<Button id="automation_button"/>
</HBox> </HBox>
<HBox> <VBox width="1"/>
<VBox width="24"/> <VBox id="gain_meter_home" width="7" />
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/> <EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox>
<iconbutton id="monitor_input_button"
width="41"
height="20"
normalicon="time_axis_monitor_input"
activeicon="time_axis_monitor_input_active"
prelighticon="time_axis_monitor_input_prelight"
tooltip="Input Monitoring"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
<VBox>
<iconbutton id="mute_button"
width="41"
height="20"
normalicon="time_axis_mute"
activeicon="time_axis_mute_active"
implicitactiveicon="time_axis_mute_implicit"
prelighticon="time_axis_mute_prelight"
tooltip="Mute"/>
<Button id="master_mute_button" ui.orphan="true"/>
<EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
</VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
</HBox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000" box.pack="end"/>
</VBox>
<HBox visible="false" noshowall="true">
<Button id="show_sends_button"/>
<Button id="monitor_disk_button"/>
<Button id="comment_button"/>
<Button id="midi_input_enable_button"/>
<Button id="group_button" text="Grp"/>
<Button id="route_group_button"/>
<Button id="automation_button"/>
</HBox> </HBox>
<!--<HBox id="gain_meter_home" box.pack="end"/>--> <EventBox id="lower_drop_indicator" visible="false" noshowall="true" height="2" bgnormal="#1CA3B3" bgactive="#1CA3B3"/>
<VBox id="gain_meter_home" width="7"> <EventBox height="1" bgnormal="#000000" bgactive="#000000"/>
<EventBox height="1" bgnormal="#494949" bgactive="#494949"/> </Vbox>
<EventBox height="1" bgnormal="#000000" bgactive="#000000" box.pack="end"/>
</VBox>
<EventBox width="1" bgnormal="#000000" bgactive="#000000"/>
</HBox>
<EventBox id="lower_drop_indicator" visible="false" noshowall="true" height="2" bgnormal="#1CA3B3" bgactive="#1CA3B3" box.pack="end"/>
</Vbox>
</RouteUI> </RouteUI>

View file

@ -40,8 +40,7 @@
y="4"/> y="4"/>
<HBox id="primary_clock_home" <HBox id="primary_clock_home"
x="132" x="132"
y="6"/> y="6"/>
<Button id="bit_depth_button" <Button id="bit_depth_button"
text="bit depth" text="bit depth"
fgnormal="#ffffff" fgnormal="#ffffff"
@ -78,8 +77,26 @@
activeicon="top_bar_button" activeicon="top_bar_button"
prelighticon="top_bar_button"/> prelighticon="top_bar_button"/>
</Layout> </Layout>
<Layout box.pack="end" width="114" height="51"> <EventBox bgnormal="#383838"
<icon source="metrics_display.png"/> width="17"
box.padding="1"
box.fill="true"
box.expand="true">
<HBox>
<icon source="infobar_left.png"/>
<icon source="infobar_center.png"
box.fill="true"
box.expand="true"/>
<icon source="infobar_right.png"
box.pack="end"/>
</HBox>
</EventBox>
<Layout bgnormal="#282828"
width="115"
height="51"
box.pack="end">
<icon source="metrics_display.png"
x="1"/>
<Adjustment id="dsp_load_adjustment" <Adjustment id="dsp_load_adjustment"
minvalue="1" minvalue="1"
maxvalue="100" maxvalue="100"
@ -93,7 +110,7 @@
maxposx="56" maxposx="56"
maxposy="3" maxposy="3"
readonly="true" readonly="true"
x="28" x="29"
y="8" y="8"
width="56" width="56"
height="5"/> height="5"/>
@ -103,7 +120,7 @@
fgnormal="#ffffff" fgnormal="#ffffff"
winfont ="Arial 8" winfont ="Arial 8"
macfont ="Helvetica 8" macfont ="Helvetica 8"
x="87" x="88"
y="8"/> y="8"/>
<Adjustment id="hd_load_adjustment" <Adjustment id="hd_load_adjustment"
minvalue="1" minvalue="1"
@ -118,7 +135,7 @@
maxposx="56" maxposx="56"
maxposy="3" maxposy="3"
readonly="true" readonly="true"
x="28" x="29"
y="18" y="18"
width="56" width="56"
height="5"/> height="5"/>
@ -128,7 +145,7 @@
fgnormal="#ffffff" fgnormal="#ffffff"
winfont ="Arial 8" winfont ="Arial 8"
macfont ="Helvetica 8" macfont ="Helvetica 8"
x="87" x="88"
y="18"/> y="18"/>
<Label id="hd_remained_time" <Label id="hd_remained_time"
@ -136,16 +153,11 @@
fgnormal="#ffffff" fgnormal="#ffffff"
winfont ="Arial 9" winfont ="Arial 9"
macfont ="Helvetica 9" macfont ="Helvetica 9"
x="58" x="59"
y="33"/> y="33"/>
</Layout> </Layout>
<EventBox bgnormal="#383838" <VBox spacing ="1"
width="420" box.pack="end">
box.padding="4">
<EventBox bgnormal="#474747"
borderwidth="1"/>
</EventBox>
<VBox spacing ="1" box.pack="end">
<iconbutton id="mode_stereo_out_button" <iconbutton id="mode_stereo_out_button"
tooltip="Stereo Out Mode" tooltip="Stereo Out Mode"
width="79" height="25" width="79" height="25"
@ -183,7 +195,9 @@
normalicon="meter_bridge_on" normalicon="meter_bridge_on"
activeicon="meter_bridge_on_active" activeicon="meter_bridge_on_active"
prelighticon="meter_bridge_on_prelight"/> prelighticon="meter_bridge_on_prelight"/>
<layout width="54" height="26" bgnormal="#3E3E3E"/> <Layout width="54"
height="26"
bgnormal="#3E3E3E"/>
<iconbutton id="transport_start_button" <iconbutton id="transport_start_button"
tooltip="Rewind" tooltip="Rewind"
width="34" height="26" width="34" height="26"
@ -226,7 +240,9 @@
normalicon="lock_session" normalicon="lock_session"
activeicon="lock_session_active" activeicon="lock_session_active"
prelighticon="lock_session_prelight"/> prelighticon="lock_session_prelight"/>
<layout width="60" height="26" bgnormal="#3E3E3E"/> <Layout width="60"
height="26"
bgnormal="#3E3E3E"/>
<iconbutton id="tool_marker_button" <iconbutton id="tool_marker_button"
tooltip="Range Select Tool" tooltip="Range Select Tool"
width="34" height="26" width="34" height="26"

View file

@ -81,6 +81,8 @@ WavesUI::create_widget (const XMLNode& definition, const XMLNodeMap& styles)
child = manage (new WavesButton(text)); child = manage (new WavesButton(text));
} else if (widget_type == "ICONBUTTON") { } else if (widget_type == "ICONBUTTON") {
child = manage (new WavesIconButton); child = manage (new WavesIconButton);
} else if (widget_type == "DROPDOWN") {
child = manage (new WavesDropdown);
} else if (widget_type == "ICON") { } else if (widget_type == "ICON") {
std::string image_path; std::string image_path;
Searchpath spath(ARDOUR::ardour_data_search_path()); Searchpath spath(ARDOUR::ardour_data_search_path());
@ -679,6 +681,11 @@ WavesUI::set_attributes (Gtk::Widget& widget, const XMLNode& definition, const X
} }
} }
WavesDropdown* dropdown = dynamic_cast<WavesDropdown*> (&widget);
if (dropdown) {
set_attributes (dropdown->get_menu (), definition, styles);
}
Gtk::Table* table = dynamic_cast<Gtk::Table*> (&widget); Gtk::Table* table = dynamic_cast<Gtk::Table*> (&widget);
if (table) { if (table) {
table->set_col_spacings (xml_property (definition, "columnspacing", styles, 0)); table->set_col_spacings (xml_property (definition, "columnspacing", styles, 0));
@ -813,6 +820,16 @@ WavesUI::get_waves_grid (const char* id)
return *child; return *child;
} }
WavesDropdown&
WavesUI::get_waves_dropdown (const char* id)
{
WavesDropdown* child = dynamic_cast<WavesDropdown*> (get_object(id));
if (child == NULL ) {
dbg_msg (std::string("WavesDropdown ") + id + " not found in " + _scrip_file_name + "!");
abort ();
}
return *child;
}
Gtk::Paned& Gtk::Paned&
WavesUI::get_paned (const char* id) WavesUI::get_paned (const char* id)
{ {

View file

@ -37,6 +37,7 @@
#include "waves_grid.h" #include "waves_grid.h"
#include "waves_button.h" #include "waves_button.h"
#include "waves_icon_button.h" #include "waves_icon_button.h"
#include "waves_dropdown.h"
using namespace ArdourCanvas::XMLUI; using namespace ArdourCanvas::XMLUI;
@ -54,6 +55,7 @@ class WavesUI : public std::map<std::string, Gtk::Object*> {
Gtk::HBox& get_h_box (const char* id); Gtk::HBox& get_h_box (const char* id);
Gtk::Fixed& get_fixed (const char* id); Gtk::Fixed& get_fixed (const char* id);
WavesGrid& get_waves_grid (const char* id); WavesGrid& get_waves_grid (const char* id);
WavesDropdown& get_waves_dropdown (const char* id);
Gtk::Paned& get_paned (const char* id); Gtk::Paned& get_paned (const char* id);
Gtk::HPaned& get_h_paned (const char* id); Gtk::HPaned& get_h_paned (const char* id);
Gtk::VPaned& get_v_paned (const char* id); Gtk::VPaned& get_v_paned (const char* id);

View file

@ -28,6 +28,7 @@ path_prefix = 'gtk2_ardour/'
gtk2_ardour_sources = [ gtk2_ardour_sources = [
'mixer_bridge_view.cc', 'mixer_bridge_view.cc',
'waves_dropdown.cc',
'waves_zoom_control.cc', 'waves_zoom_control.cc',
'waves_ui.cc', 'waves_ui.cc',
'waves_grid.cc', 'waves_grid.cc',

View file

@ -386,6 +386,12 @@ class LIBARDOUR_API AudioBackend : public PortEngine {
*/ */
virtual int stop () = 0; virtual int stop () = 0;
/** Reset device.
*
* Return zero if successful, negative values on error
*/
virtual int reset_device() = 0;
/** While remaining connected to the device, and without changing its /** While remaining connected to the device, and without changing its
* configuration, start (or stop) calling the process_callback() of @param engine * configuration, start (or stop) calling the process_callback() of @param engine
* without waiting for the device. Once process_callback() has returned, it * without waiting for the device. Once process_callback() has returned, it

View file

@ -114,6 +114,9 @@ public:
bool is_realtime() const; bool is_realtime() const;
bool connected() const; bool connected() const;
// for the user which hold state_lock to check if reset operation is pending
bool is_reset_requested() const { return g_atomic_int_get(&_hw_reset_request_count); }
int set_device_name (const std::string&); int set_device_name (const std::string&);
int set_sample_rate (float); int set_sample_rate (float);
int set_buffer_size (uint32_t); int set_buffer_size (uint32_t);
@ -129,6 +132,7 @@ public:
bool running() const { return _running; } bool running() const { return _running; }
Glib::Threads::Mutex& process_lock() { return _process_lock; } Glib::Threads::Mutex& process_lock() { return _process_lock; }
Glib::Threads::RecMutex& state_lock() { return _state_lock; }
int request_buffer_size (pframes_t samples) { int request_buffer_size (pframes_t samples) {
return set_buffer_size (samples); return set_buffer_size (samples);
@ -169,6 +173,10 @@ public:
PBD::Signal1<void, pframes_t> BufferSizeChanged; PBD::Signal1<void, pframes_t> BufferSizeChanged;
/* this signal is emitted if the device cannot operate properly */
PBD::Signal0<void> DeviceError;
/* this signal is emitted if the device list changed */ /* this signal is emitted if the device list changed */
PBD::Signal0<void> DeviceListChanged; PBD::Signal0<void> DeviceListChanged;
@ -228,7 +236,8 @@ public:
static AudioEngine* _instance; static AudioEngine* _instance;
Glib::Threads::Mutex _process_lock; Glib::Threads::Mutex _process_lock;
Glib::Threads::RecMutex _state_lock;
Glib::Threads::Cond session_removed; Glib::Threads::Cond session_removed;
bool session_remove_pending; bool session_remove_pending;
frameoffset_t session_removal_countdown; frameoffset_t session_removal_countdown;

View file

@ -48,6 +48,9 @@ public:
static EngineStateController* instance(); static EngineStateController* instance();
void set_session(Session* session);
void remove_session ();
//Interfaces //Interfaces
void available_backends(std::vector<const AudioBackendInfo*>&); void available_backends(std::vector<const AudioBackendInfo*>&);
@ -128,7 +131,9 @@ public:
PBD::Signal0<void> BufferSizeChanged; PBD::Signal0<void> BufferSizeChanged;
/* this signal is emitted if the device list changes */ /* this signal is emitted if the device list changes */
PBD::Signal1<void, bool> DeviceListChanged; PBD::Signal1<void, bool> DeviceListChanged;
/* this signal is emitted if the device cannot operate properly */
PBD::Signal0<void> DeviceError;
//ENGINE STATE SIGNALS //ENGINE STATE SIGNALS
/* this signal is emitted when the engine is started */ /* this signal is emitted when the engine is started */
PBD::Signal0<void> EngineRunning; PBD::Signal0<void> EngineRunning;
@ -260,11 +265,13 @@ private:
void _on_engine_running(); void _on_engine_running();
void _on_engine_halted(); void _on_engine_halted();
void _on_engine_stopped(); void _on_engine_stopped();
void _on_device_error();
void _on_sample_rate_change(ARDOUR::framecnt_t); void _on_sample_rate_change(ARDOUR::framecnt_t);
void _on_buffer_size_change(ARDOUR::pframes_t); void _on_buffer_size_change(ARDOUR::pframes_t);
void _on_device_list_change(); void _on_device_list_change();
void _on_parameter_changed (const std::string&); void _on_parameter_changed (const std::string&);
void _on_ports_registration_update (); void _on_ports_registration_update ();
void _on_session_loaded();
//////////////////////////////////////// ////////////////////////////////////////
//////////////////////////////////////// ////////////////////////////////////////
@ -282,12 +289,14 @@ private:
ARDOUR::framecnt_t _desired_sample_rate; ARDOUR::framecnt_t _desired_sample_rate;
bool _have_control; bool _have_control;
Session* _session;
// Engine connections stuff // Engine connections stuff
PBD::ScopedConnectionList update_connections; PBD::ScopedConnectionList update_connections;
PBD::ScopedConnectionList session_connections;
PBD::ScopedConnection running_connection; PBD::ScopedConnection running_connection;
PBD::ScopedConnection halt_connection; PBD::ScopedConnection halt_connection;
PBD::ScopedConnection stopped_connection; PBD::ScopedConnection stopped_connection;
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -301,6 +301,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
PBD::Signal0<void> RecordStateChanged; PBD::Signal0<void> RecordStateChanged;
/* Emited when session is loaded */
PBD::Signal0<void> SessionLoaded;
/* Transport mechanism signals */ /* Transport mechanism signals */
/** Emitted on the following changes in transport state: /** Emitted on the following changes in transport state:

View file

@ -405,31 +405,42 @@ AudioEngine::do_reset_backend()
while (!_stop_hw_reset_processing) { while (!_stop_hw_reset_processing) {
if (_hw_reset_request_count && _backend) { if (_hw_reset_request_count && _backend) {
_reset_request_lock.unlock();
_reset_request_lock.unlock(); Glib::Threads::RecMutex::Lock pl (_state_lock);
g_atomic_int_dec_and_test (&_hw_reset_request_count); g_atomic_int_dec_and_test (&_hw_reset_request_count);
std::cout << "AudioEngine::RESET::Reset request processing" << std::endl;
// backup the device name // backup the device name
std::string name = _backend->device_name (); std::string name = _backend->device_name ();
std::cout << "AudioEngine::RESET::Halting session processing..." << std::endl;
if (_session && _running) {
// it's not a halt, but should be handled the same way:
// disable record, stop transport and I/O processign but save the data.
_session->engine_halted ();
}
stop(); std::cout << "AudioEngine::RESET::Stoping engine..." << std::endl;
if (_session) { stop();
// it's not a halt, but should be handled the same way:
// disable record, stop transport and I/O processign but save the data. std::cout << "AudioEngine::RESET::Reseting device..." << std::endl;
_session->engine_halted (); if ( 0 == _backend->reset_device () ) {
}
std::cout << "AudioEngine::RESET::Starting engine..." << std::endl;
// "hard reset" the device start ();
_backend->drop_device ();
_backend->set_device_name (name); // inform about possible changes
BufferSizeChanged (_backend->buffer_size() );
start (); } else {
DeviceError();
// inform about possible changes }
SampleRateChanged (_backend->sample_rate() );
BufferSizeChanged (_backend->buffer_size() );
std::cout << "AudioEngine::RESET::Done." << std::endl;
_reset_request_lock.lock(); _reset_request_lock.lock();
} else { } else {
@ -460,7 +471,7 @@ AudioEngine::do_devicelist_update()
while (!_stop_hw_devicelist_processing) { while (!_stop_hw_devicelist_processing) {
if (_hw_devicelist_update_count) { if (_hw_devicelist_update_count) {
_devicelist_update_lock.unlock(); _devicelist_update_lock.unlock();
g_atomic_int_dec_and_test (&_hw_devicelist_update_count); g_atomic_int_dec_and_test (&_hw_devicelist_update_count);
@ -611,7 +622,7 @@ AudioEngine::died ()
stop_metering_thread (); stop_metering_thread ();
_running = false; _running = false;
} }
int int
@ -1177,7 +1188,7 @@ AudioEngine::halted_callback (const char* why)
return; return;
} }
stop_metering_thread (); stop_metering_thread ();
_running = false; _running = false;
Port::PortDrop (); /* EMIT SIGNAL */ Port::PortDrop (); /* EMIT SIGNAL */

View file

@ -9,9 +9,11 @@
#include "ardour/engine_state_controller.h" #include "ardour/engine_state_controller.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/session.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"
#include "ardour/data_type.h" #include "ardour/data_type.h"
#include "pbd/pthread_utils.h"
#include "pbd/error.h" #include "pbd/error.h"
#include "i18n.h" #include "i18n.h"
@ -61,6 +63,7 @@ EngineStateController::EngineStateController()
AudioEngine::instance()->SampleRateChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_sample_rate_change, this, _1) ); AudioEngine::instance()->SampleRateChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_sample_rate_change, this, _1) );
AudioEngine::instance()->BufferSizeChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_buffer_size_change, this, _1) ); AudioEngine::instance()->BufferSizeChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_buffer_size_change, this, _1) );
AudioEngine::instance()->DeviceListChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_list_change, this) ); AudioEngine::instance()->DeviceListChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_list_change, this) );
AudioEngine::instance()->DeviceError.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_error, this) );
/* Global configuration parameters update */ /* Global configuration parameters update */
Config->ParameterChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_parameter_changed, this, _1) ); Config->ParameterChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_parameter_changed, this, _1) );
@ -79,8 +82,25 @@ EngineStateController::~EngineStateController()
} }
void
EngineStateController::set_session(Session* session)
{
_session = session;
_session->SessionLoaded.connect_same_thread (session_connections, boost::bind (&EngineStateController::_on_session_loaded, this) );
}
void
EngineStateController::remove_session ()
{
session_connections.drop_connections ();
_session = 0;
}
XMLNode& XMLNode&
EngineStateController::serialize_audio_midi_settings() { EngineStateController::serialize_audio_midi_settings()
{
XMLNode* root = new XMLNode ("AudioMidiSettings"); XMLNode* root = new XMLNode ("AudioMidiSettings");
@ -92,7 +112,8 @@ EngineStateController::serialize_audio_midi_settings() {
void void
EngineStateController::save_audio_midi_settings() { EngineStateController::save_audio_midi_settings()
{
Config->add_extra_xml (serialize_audio_midi_settings() ); Config->add_extra_xml (serialize_audio_midi_settings() );
Config->save_state (); Config->save_state ();
} }
@ -1172,6 +1193,17 @@ EngineStateController::get_physical_midi_output_states (std::vector<PortState>&
} }
void
EngineStateController::_on_session_loaded ()
{
if (_session && _desired_sample_rate && set_new_sample_rate_in_controller(_desired_sample_rate) )
{
push_current_state_to_backend(false);
SampleRateChanged(); // emit a signal
}
}
void void
EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate) EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
{ {
@ -1181,7 +1213,7 @@ EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
framecnt_t sample_rate_to_set = new_sample_rate; framecnt_t sample_rate_to_set = new_sample_rate;
if (AudioEngine::instance()->session() ) { if (AudioEngine::instance()->session() ) {
// and we have current session we should restore it back to the one tracks uses // and we have current session we should restore it back to the one tracks uses
framecnt_t sample_rate_to_set = _current_state->sample_rate; sample_rate_to_set = _current_state->sample_rate;
} }
if ( set_new_sample_rate_in_controller (sample_rate_to_set) ) { if ( set_new_sample_rate_in_controller (sample_rate_to_set) ) {
@ -1191,7 +1223,8 @@ EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
// if sample rate can't be set // if sample rate can't be set
// switch to NONE device // switch to NONE device
set_new_device_as_current ("None"); set_new_device_as_current ("None");
DeviceListChanged(true); DeviceListChanged(false);
DeviceError();
} }
} }
} }
@ -1466,6 +1499,16 @@ EngineStateController::_on_engine_halted ()
} }
void
EngineStateController::_on_device_error()
{
set_new_device_as_current ("None");
push_current_state_to_backend(true);
DeviceListChanged(false);
DeviceError();
}
void void
EngineStateController::_on_parameter_changed (const std::string& parameter_name) EngineStateController::_on_parameter_changed (const std::string& parameter_name)
{ {
@ -1503,26 +1546,41 @@ EngineStateController::push_current_state_to_backend(bool start)
bool was_running = AudioEngine::instance()->running(); bool was_running = AudioEngine::instance()->running();
Glib::Threads::RecMutex::Lock sl (AudioEngine::instance()->state_lock() );
if (state_changed) { if (state_changed) {
if (was_running) { if (was_running) {
if (AudioEngine::instance()->stop () ) { if (AudioEngine::instance()->stop () ) {
return false; return false;
} }
} }
int result = 0;
{
std::cout << "EngineStateController::Setting device: " << _current_state->device_name << std::endl;
if ((_current_state->device_name != backend->device_name()) && (result = backend->set_device_name (_current_state->device_name)) ) {
error << string_compose (_("Cannot set device name to %1"), get_current_device_name()) << endmsg;
}
if ((_current_state->device_name != backend->device_name()) && backend->set_device_name (_current_state->device_name)) { std::cout << "EngineStateController::Setting device sample rate " << _current_state->sample_rate << std::endl;
error << string_compose (_("Cannot set device name to %1"), get_current_device_name()) << endmsg; if (!result && (result = backend->set_sample_rate (_current_state->sample_rate)) ) {
} error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate()) << endmsg;
}
if (backend->set_sample_rate (_current_state->sample_rate )) { std::cout << "EngineStateController::Setting device buffer size " << _current_state->buffer_size << std::endl;
error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate()) << endmsg; if (!result && (result = backend->set_buffer_size (_current_state->buffer_size)) ) {
} error << string_compose (_("Cannot set buffer size to %1"), get_current_buffer_size()) << endmsg;
}
if (backend->set_buffer_size (_current_state->buffer_size )) { }
error << string_compose (_("Cannot set buffer size to %1"), get_current_buffer_size()) << endmsg;
}
if (result) // error during device setup
{
//switch to None device and notify about the issue
set_new_device_as_current ("None");
DeviceListChanged(false);
DeviceError();
}
//if (backend->set_input_channels (get_input_channels())) { //if (backend->set_input_channels (get_input_channels())) {
// error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg; // error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
// return -1; // return -1;
@ -1545,7 +1603,12 @@ EngineStateController::push_current_state_to_backend(bool start)
} }
if(start || (was_running && state_changed) ) { if(start || (was_running && state_changed) ) {
if (AudioEngine::instance()->start () ) { if (AudioEngine::instance()->start () && !AudioEngine::instance()->is_reset_requested() ) {
//switch to None device and notify about the issue
set_new_device_as_current ("None");
AudioEngine::instance()->start ();
DeviceListChanged(false);
DeviceError();
return false; return false;
} }
} }
@ -1562,12 +1625,7 @@ EngineStateController::set_desired_sample_rate(framecnt_t session_desired_sr)
if (session_desired_sr == 0 || session_desired_sr == _desired_sample_rate) { if (session_desired_sr == 0 || session_desired_sr == _desired_sample_rate) {
return; return;
} }
_desired_sample_rate = session_desired_sr; _desired_sample_rate = session_desired_sr;
// if we swithced to new desired sample rate successfuly - push the new state to the backend
if (set_new_sample_rate_in_controller (session_desired_sr) ) {
push_current_state_to_backend(false);
}
} }

View file

@ -135,7 +135,12 @@ Port::get_connections (std::vector<std::string> & c) const
return c.size(); return c.size();
} }
return port_engine.get_connections (_port_handle, c); if (_port_handle) {
port_engine.get_connections (_port_handle, c);
return c.size();
}
return 0;
} }
int int

View file

@ -369,6 +369,8 @@ Session::Session (AudioEngine &eng,
_engine.set_session (this); _engine.set_session (this);
_engine.reset_timebase (); _engine.reset_timebase ();
EngineStateController::instance()->set_session(this);
// Waves Tracks: always create master track // Waves Tracks: always create master track
if ( ARDOUR::Profile->get_trx () ) { if ( ARDOUR::Profile->get_trx () ) {
create_master_track(); create_master_track();
@ -419,6 +421,7 @@ Session::Session (AudioEngine &eng,
_is_new = false; _is_new = false;
SessionLoaded();
BootMessage (_("Session loading complete")); BootMessage (_("Session loading complete"));
} }
@ -524,6 +527,7 @@ Session::destroy ()
drop_connections (); drop_connections ();
_engine.remove_session (); _engine.remove_session ();
EngineStateController::instance()->remove_session();
/* deregister all ports - there will be no process or any other /* deregister all ports - there will be no process or any other
* callbacks from the engine any more. * callbacks from the engine any more.

View file

@ -446,6 +446,10 @@ WavesAudioBackend::set_buffer_size (uint32_t buffer_size)
return -1; return -1;
} }
// if call to set buffer is successful but device buffer size differs from the value we tried to set
// this means we are driven by device for buffer size
buffer_size = _device->CurrentBufferSize ();
_buffer_size_change(buffer_size); _buffer_size_change(buffer_size);
if (device_needs_restart) { if (device_needs_restart) {
@ -472,9 +476,9 @@ WavesAudioBackend::set_sample_format (SampleFormat sample_format)
} }
int int
WavesAudioBackend::_reset_device (uint32_t buffer_size, float sample_rate) WavesAudioBackend::reset_device ()
{ {
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device (" << buffer_size <<", " << sample_rate << "):" << std::endl; // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::_reset_device ():" << std::endl;
WTErr retVal = eNoErr; WTErr retVal = eNoErr;
@ -483,95 +487,7 @@ WavesAudioBackend::_reset_device (uint32_t buffer_size, float sample_rate)
return -1; return -1;
} }
bool device_needs_restart = _device->Streaming (); return _device->ResetDevice();
if (device_needs_restart) {
retVal = _device->SetStreaming (false);
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (false);"<< std::endl;
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (false) failed (" << retVal << ") !" << std::endl;
return -1;
}
retVal = _device->SetActive (false);
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (false);"<< std::endl;
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (false) failed (" << retVal << ") !" << std::endl;
return -1;
}
}
retVal = _device->UpdateDeviceInfo ();
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->UpdateDeviceInfo () failed (" << retVal << ") !" << std::endl;
return -1;
}
if (buffer_size != 0)
{
retVal = _device->SetCurrentBufferSize (buffer_size);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName() << "]->SetCurrentBufferSize (" << buffer_size << ") failed (" << retVal << ") !" << std::endl;
return -1;
}
_buffer_size = buffer_size;
}
else
{
uint32_t current_buffer_size = _device->CurrentBufferSize();
// COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_buffer_size: " << current_buffer_size << std::endl;
// COMMENTED DBG LOGS */ std::cout << "\t\t _buffer_size: " << _buffer_size << std::endl;
if(_buffer_size != current_buffer_size)
{
_buffer_size = current_buffer_size;
engine.buffer_size_change (_buffer_size);
// COMMENTED DBG LOGS */ std::cout << "\t\tengine.buffer_size_change (" << buffer_size <<")" << std::endl;
}
}
if(sample_rate > 0.0)
{
retVal = _device->SetCurrentSamplingRate ((int)sample_rate);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::set_sample_rate (): [" << _device->DeviceName() << "]->SetCurrentSamplingRate ((int)" << sample_rate << ") failed (" << retVal << ") !" << std::endl;
return -1;
}
_sample_rate = sample_rate;
}
else
{
float current_sample_rate = _device->CurrentSamplingRate();
// COMMENTED DBG LOGS */ std::cout << "\t\tcurrent_sample_rate: " << current_sample_rate << std::endl;
// COMMENTED DBG LOGS */ std::cout << "\t\t _sample_rate: " << _sample_rate << std::endl;
if(_sample_rate != current_sample_rate)
{
_sample_rate = current_sample_rate;
engine.sample_rate_change (_sample_rate);
// COMMENTED DBG LOGS */ std::cout << "\t\tengine.sample_rate_change (" << _sample_rate <<")" << std::endl;
}
}
_init_dsp_load_history();
if (device_needs_restart) {
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetActive (true);"<< std::endl;
retVal = _device->SetActive (true);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetActive (true) failed (" << retVal << ") !" << std::endl;
return -1;
}
// COMMENTED DBG LOGS */ std::cout << "\t\t[" << _device->DeviceName() << "]->SetStreaming (true);"<< std::endl;
_call_thread_init_callback = true;
retVal = _device->SetStreaming (true);
if (retVal != eNoErr) {
std::cerr << "WavesAudioBackend::_reset_device (): [" << _device->DeviceName () << "]->SetStreaming (true) failed (" << retVal << ") !" << std::endl;
return -1;
}
}
return 0;
} }

View file

@ -122,9 +122,10 @@ class WavesMidiPort;
virtual int set_systemic_output_latency (uint32_t); virtual int set_systemic_output_latency (uint32_t);
int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; } int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; } int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
virtual int reset_device ();
virtual std::string device_name () const; virtual std::string device_name () const;
virtual float sample_rate () const; virtual float sample_rate () const;
@ -345,7 +346,6 @@ class WavesMidiPort;
pframes_t sample_time, pframes_t sample_time,
uint64_t cycle_start_time_nanos); uint64_t cycle_start_time_nanos);
int _reset_device (uint32_t buffer_size, float sample_rate);
void _changed_midi_devices (); void _changed_midi_devices ();
// DO change sample rate and buffer size // DO change sample rate and buffer size

View file

@ -425,7 +425,7 @@ WavesAudioBackend::physically_connected (PortHandle port_handle, bool process_ca
int int
WavesAudioBackend::get_connections (PortHandle port_handle, std::vector<std::string>& names, bool process_callback_safe) WavesAudioBackend::get_connections (PortHandle port_handle, std::vector<std::string>& names, bool process_callback_safe)
{ {
// COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_connections ()" << std::endl; // COMMENTED DBG LOGS */ std::cout << "WavesAudioBackend::get_connections ()" << std::endl;
if (!_registered (port_handle)) { if (!_registered (port_handle)) {
std::cerr << "WavesAudioBackend::get_connections (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl; std::cerr << "WavesAudioBackend::get_connections (): Failed to find port [" << std::hex << port_handle << std::dec << "]!" << std::endl;

View file

@ -345,6 +345,28 @@ WTErr WCMRAudioDevice::SetStreaming (bool newState)
return (eNoErr); return (eNoErr);
} }
WTErr WCMRAudioDevice::ResetDevice ()
{
// Keep device sates
bool wasStreaming = Streaming();
bool wasActive = Active();
WTErr err = SetStreaming(false);
if (err == eNoErr)
SetActive(false);
if (err == eNoErr && wasActive)
SetActive(true);
if (err == eNoErr && wasStreaming)
SetStreaming(true);
return err;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////
// IsProcessActive - returns true if process code is running. // IsProcessActive - returns true if process code is running.
// A normal audio device should return the Streaming() value // A normal audio device should return the Streaming() value

View file

@ -151,6 +151,8 @@ public:
virtual bool Streaming();///<Streaming Status? virtual bool Streaming();///<Streaming Status?
virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts! virtual WTErr SetStreaming (bool newState);///<Start/Stop Streaming - should reconnect connections when streaming starts!
virtual WTErr ResetDevice ();
virtual bool IsProcessActive(); virtual bool IsProcessActive();
virtual WTErr DoIdle();///<Do Idle Processing virtual WTErr DoIdle();///<Do Idle Processing

View file

@ -13,14 +13,16 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <list>
using namespace wvNS; using namespace wvNS;
#include "IncludeWindows.h" #include "IncludeWindows.h"
#include <MMSystem.h> #include <MMSystem.h>
#include "pa_asio.h" #include "pa_asio.h"
#include "asio.h" #include "asio.h"
#define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 200 #define PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS 500
#define PROPERTY_CHANGE_TIMEOUT_SECONDS 2 #define PROPERTY_CHANGE_TIMEOUT_SECONDS 2
#define PROPERTY_CHANGE_RETRIES 3
///< Supported Sample rates ///< Supported Sample rates
static const double gAllSampleRates[] = static const double gAllSampleRates[] =
@ -308,14 +310,12 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
//update name. //update name.
m_DeviceName = pDeviceInfo->name; m_DeviceName = pDeviceInfo->name;
std::cout << "API::Device " << m_DeviceName << " Getting device info " << std::endl;
//following parameters are needed opening test stream and for sample rates validation //following parameters are needed opening test stream and for sample rates validation
PaStreamParameters inputParameters, outputParameters; PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL; PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID; inputParameters.device = m_DeviceID;
inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels); inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
inputParameters.hostApiSpecificStreamInfo = 0; inputParameters.hostApiSpecificStreamInfo = 0;
@ -324,7 +324,7 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
pInS = &inputParameters; pInS = &inputParameters;
outputParameters.device = m_DeviceID; outputParameters.device = m_DeviceID;
outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels); outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32; outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
outputParameters.hostApiSpecificStreamInfo = 0; outputParameters.hostApiSpecificStreamInfo = 0;
@ -332,7 +332,6 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount) if (outputParameters.channelCount)
pOutS = &outputParameters; pOutS = &outputParameters;
std::cout << "API::Device" << m_DeviceName << " Updating sample rates " << std::endl;
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
//update list of supported SRs... //update list of supported SRs...
m_SamplingRates.clear(); m_SamplingRates.clear();
@ -348,54 +347,27 @@ void WCMRPortAudioDevice::updateDeviceInfo (bool callerIsWaiting/*=false*/)
} }
} }
std::cout << "API::Device" << m_DeviceName << " Updating buffer sizes" << std::endl;
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
//update buffer sizes //update buffer sizes
m_BufferSizes.clear(); m_BufferSizes.clear();
bool useDefaultBuffers = true; bool useDefaultBuffers = true;
PaError paErr = paNoError;
//sometimes devices change buffer size if sample rate changes // In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
//it updates buffer size during stream opening long minSize, maxSize, preferredSize, granularity;
//we need to find out how device would behave with current sample rate PaError err = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
//try opening test stream to load device driver for current sample rate and buffer size
//(skip this step if the device is Active)
if ( !Active() )
{
if (paNoError != testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize) )
{
//buffer size did change
Pa_Terminate();
Pa_Initialize();
// test validness with current sample rate and device prefered buffer size
paErr = testStateValidness(m_CurrentSamplingRate, 0);
}
}
if (paErr == paNoError)
{
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel
long minSize, maxSize, preferredSize, granularity;
paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError) if (err == paNoError)
{ {
std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl; std::cout << "API::Device " << m_DeviceName << " Buffers: " << minSize << " " << maxSize << " " << preferredSize << std::endl;
m_BufferSizes.push_back (preferredSize); m_BufferSizes.push_back (preferredSize);
useDefaultBuffers = false; useDefaultBuffers = false;
}
else
{
std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
}
} }
else else
{ {
std::cout << "API::Device" << m_DeviceName << " Device does not start with sample rate: "<< m_CurrentSamplingRate << " and default buffer size" << std::endl; std::cout << "API::Device" << m_DeviceName << " Preffered buffer size is not supported" << std::endl;
} }
if (useDefaultBuffers) if (useDefaultBuffers)
{ {
std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl; std::cout << "API::Device" << m_DeviceName << " Using default buffer sizes " <<std::endl;
@ -476,18 +448,18 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
PaStreamParameters *pInS = NULL, *pOutS = NULL; PaStreamParameters *pInS = NULL, *pOutS = NULL;
inputParameters.device = m_DeviceID; inputParameters.device = m_DeviceID;
inputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxInputChannels); inputParameters.channelCount = pDeviceInfo->maxInputChannels;
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; inputParameters.sampleFormat = paFloat32 | paNonInterleaved;
inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ inputParameters.suggestedLatency = 0;
inputParameters.hostApiSpecificStreamInfo = 0; inputParameters.hostApiSpecificStreamInfo = 0;
if (inputParameters.channelCount) if (inputParameters.channelCount)
pInS = &inputParameters; pInS = &inputParameters;
outputParameters.device = m_DeviceID; outputParameters.device = m_DeviceID;
outputParameters.channelCount = std::min<int>(2, pDeviceInfo->maxOutputChannels); outputParameters.channelCount = pDeviceInfo->maxOutputChannels;
outputParameters.sampleFormat = paFloat32; outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ outputParameters.suggestedLatency = 0;
outputParameters.hostApiSpecificStreamInfo = 0; outputParameters.hostApiSpecificStreamInfo = 0;
if (outputParameters.channelCount) if (outputParameters.channelCount)
@ -499,7 +471,7 @@ PaError WCMRPortAudioDevice::testStateValidness(int sampleRate, int bufferSize)
//it updates buffer size during stream opening //it updates buffer size during stream opening
//we need to find out how device would behave with current sample rate //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 //try opening test stream to load device driver for current sample rate and buffer size
paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, m_CurrentSamplingRate, m_CurrentBufferSize, paDitherOff, NULL, NULL); paErr = Pa_OpenStream (&portAudioStream, pInS, pOutS, sampleRate, bufferSize, paDitherOff, NULL, NULL);
if (portAudioStream) if (portAudioStream)
{ {
@ -628,35 +600,17 @@ WTErr WCMRPortAudioDevice::SetCurrentSamplingRate (int newRate)
return (retVal); return (retVal);
} }
if (oldActive)
{
//Deactivate it for the change...
SetActive (false);
}
//make the change... //make the change...
m_CurrentSamplingRate = newRate; m_CurrentSamplingRate = newRate;
PaError paErr = PaAsio_SetStreamSampleRate (m_PortAudioStream, m_CurrentSamplingRate);
// Before reactivating the device: opening stream we should try getting buffer size update from the device if (paErr != paNoError)
// because for new sampling rate some devices may change buffer size as well
int oldBufferSize = m_CurrentBufferSize;
retVal = ResetDevice();
//reactivate it.
if (oldActive && retVal == eNoErr)
{ {
retVal = SetActive (true); std::cout << "Sample rate change failed, cannot start with error: " << Pa_GetErrorText (paErr) << std::endl;
} if (paErr == paUnanticipatedHostError)
std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
if (retVal != eNoErr) retVal = eWrongObjectState;
{
//revert changes if the device was not activated
m_CurrentSamplingRate = oldRate;
m_CurrentBufferSize = oldBufferSize;
int bufferSize = m_CurrentBufferSize;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
retVal = eCommandLineParameter;
} }
return (retVal); return (retVal);
@ -705,6 +659,15 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
if (oldSize == newSize) if (oldSize == newSize)
return (retVal); return (retVal);
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
return (retVal);
}
std::cout << "Setting buffer: " << newSize << std::endl;
//see if this is one of our supported rates... //see if this is one of our supported rates...
intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize); intIter = find(m_BufferSizes.begin(), m_BufferSizes.end(), newSize);
if (intIter == m_BufferSizes.end()) if (intIter == m_BufferSizes.end())
@ -714,10 +677,12 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
{ {
// we have only one aloved buffer size which is preffered by PA // we have only one aloved buffer size which is preffered by PA
// this is the only value which could be set // this is the only value which could be set
m_CurrentBufferSize = m_BufferSizes[0]; newSize = m_BufferSizes[0];
int bufferSize = m_CurrentBufferSize; int bufferSize = newSize;
// notify client to update sample rate after us // notify client to update sample rate after us
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize); m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
return retVal;
} else { } else {
// more then one buffer size value is available // more then one buffer size value is available
//Can't change, perhaps use an "invalid param" type of error //Can't change, perhaps use an "invalid param" type of error
@ -726,13 +691,6 @@ WTErr WCMRPortAudioDevice::SetCurrentBufferSize (int newSize)
} }
} }
if (Streaming())
{
//Can't change, perhaps use an "in use" type of error
retVal = eGenericErr;
return (retVal);
}
if (oldActive) if (oldActive)
{ {
//Deactivate it for the change... //Deactivate it for the change...
@ -789,6 +747,17 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
// if device is not active activate it // if device is not active activate it
if (!Active() ) if (!Active() )
{ {
std::list<long> buffersSizes;
buffersSizes.push_back(m_CurrentBufferSize);
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError)
{
buffersSizes.push_front(preferredSize);
}
PaStreamParameters inputParameters, outputParameters; PaStreamParameters inputParameters, outputParameters;
PaStreamParameters *pInS = NULL, *pOutS = NULL; PaStreamParameters *pInS = NULL, *pOutS = NULL;
@ -812,12 +781,13 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
if (outputParameters.channelCount) if (outputParameters.channelCount)
pOutS = &outputParameters; pOutS = &outputParameters;
std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl; // try opening stream with current buffer and the rest if not successful
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << m_CurrentBufferSize << std::endl; std::list<long>::const_iterator bufferIter = buffersSizes.begin();
for (; bufferIter != buffersSizes.end(); ++bufferIter) {
int tryAgain = ((PROPERTY_CHANGE_TIMEOUT_SECONDS * 1000) / PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS) ;
while (tryAgain) { std::cout << "API::Device" << m_DeviceName << " Opening device stream " << std::endl;
std::cout << "Sample rate: " << m_CurrentSamplingRate << " buffer size: " << *bufferIter << std::endl;
paErr = Pa_OpenStream(&m_PortAudioStream, paErr = Pa_OpenStream(&m_PortAudioStream,
pInS, pInS,
pOutS, pOutS,
@ -826,20 +796,31 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
paDitherOff, paDitherOff,
WCMRPortAudioDevice::TheCallback, WCMRPortAudioDevice::TheCallback,
this); this);
if(paErr == paNoError) if(paErr == paNoError)
{ {
break; break;
} }
std::cout << "Cannot open streamm sleeping for "<< PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS << "msec and trying again" << std::endl; std::cout << "Cannot open streamm with buffer: "<< *bufferIter << " Error: " << Pa_GetErrorText (paErr) << std::endl;
// sleep and try again if (paErr == paUnanticipatedHostError)
wvThread::sleep_milliseconds (PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS); std::cout << "Error details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
--tryAgain;
} }
if(paErr == paNoError) if(paErr == paNoError)
{ {
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr == paNoError && m_CurrentBufferSize != preferredSize)
{
m_CurrentBufferSize = preferredSize;
m_BufferSizes.clear();
m_BufferSizes.push_back(preferredSize);
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&preferredSize);
}
m_DropsDetected = 0; m_DropsDetected = 0;
m_DropsReported = 0; m_DropsReported = 0;
m_IgnoreThisDrop = true; m_IgnoreThisDrop = true;
@ -861,8 +842,8 @@ void WCMRPortAudioDevice::activateDevice (bool callerIsWaiting/*=false*/)
else else
{ {
//failed, do not update device state //failed, do not update device state
std::cout << "Failed to open pa stream " << paErr << std::endl; std::cout << "Failed to open pa stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to open pa stream " << paErr ); DEBUG_MSG( "Failed to open pa stream: " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors; m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed; m_lastErr = eAsioFailed;
} }
@ -922,8 +903,8 @@ void WCMRPortAudioDevice::deactivateDevice (bool callerIsWaiting/*=false*/)
else else
{ {
//failed, do not update device state //failed, do not update device state
std::cout << "Failed to close pa stream stream " << paErr << std::endl; std::cout << "Failed to close pa stream stream " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to open pa stream stream " << paErr ); DEBUG_MSG( "Failed to open pa stream stream " << Pa_GetErrorText (paErr) );
m_ConnectionStatus = DeviceErrors; m_ConnectionStatus = DeviceErrors;
m_lastErr = eAsioFailed; m_lastErr = eAsioFailed;
} }
@ -954,17 +935,25 @@ void WCMRPortAudioDevice::startStreaming (bool callerIsWaiting/*=false*/)
m_SampleCounter = 0; m_SampleCounter = 0;
std::cout << "API::Device" << m_DeviceName << " Starting device stream" << std::endl; 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;
paErr = Pa_StartStream( m_PortAudioStream ); paErr = Pa_StartStream( m_PortAudioStream );
if(paErr == paNoError) if(paErr == paNoError)
{ {
// if the stream was started successfully // if the stream was started successfully
m_IsStreaming = true; m_IsStreaming = true;
std::cout << "API::Device" << m_DeviceName << " Device is streaming" << std::endl;
} }
else else
{ {
std::cout << "Failed to start PA stream: " << paErr << std::endl; std::cout << "Failed to start PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to start PA stream: " << paErr ); DEBUG_MSG( "Failed to start PA stream: " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr; m_lastErr = eGenericErr;
} }
} }
@ -1002,8 +991,8 @@ void WCMRPortAudioDevice::stopStreaming (bool callerIsWaiting/*=false*/)
} }
else else
{ {
std::cout << "Failed to stop PA stream: " << paErr << std::endl; std::cout << "Failed to stop PA stream: " << Pa_GetErrorText (paErr) << std::endl;
DEBUG_MSG( "Failed to stop PA stream " << paErr ); DEBUG_MSG( "Failed to stop PA stream " << Pa_GetErrorText (paErr) );
m_lastErr = eGenericErr; m_lastErr = eGenericErr;
} }
} }
@ -1028,6 +1017,8 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
{ {
std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl; std::cout << "API::Device" << m_DeviceName << "Reseting device" << std::endl;
PaError paErr = paNoError;
// Keep device sates // Keep device sates
bool wasStreaming = Streaming(); bool wasStreaming = Streaming();
bool wasActive = Active(); bool wasActive = Active();
@ -1036,49 +1027,72 @@ void WCMRPortAudioDevice::resetDevice (bool callerIsWaiting /*=false*/ )
stopStreaming(); stopStreaming();
deactivateDevice(); deactivateDevice();
// Reinitialize PA
Pa_Terminate();
Pa_Initialize();
updateDeviceInfo();
// Cache device buffer size as it might be changed during reset // Cache device buffer size as it might be changed during reset
int oldBufferSize = m_CurrentBufferSize; int oldBufferSize = m_CurrentBufferSize;
// In ASIO Windows, the buffer size is set from the sound device manufacturer's control panel // Now, validate the state and update device info if required
// Backend should always use preffered buffer size value in this case unsigned int retry = PROPERTY_CHANGE_RETRIES;
long minSize, maxSize, preferredSize, granularity; while (retry-- )
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity); {
// Reinitialize PA
Pa_Terminate();
Pa_Initialize();
std::cout << "Updating device state... " << std::endl;
// update device info
updateDeviceInfo();
// take up buffers
long minSize, maxSize, preferredSize, granularity;
PaError paErr = PaAsio_GetAvailableBufferSizes(m_DeviceID, &minSize, &maxSize, &preferredSize, &granularity);
if (paErr != paNoError)
{
continue;
}
m_CurrentBufferSize = preferredSize;
paErr = testStateValidness(m_CurrentSamplingRate, m_CurrentBufferSize);
if (paNoError == paErr)
{
std::cout << "Device state is valid" << std::endl;
break;
}
std::cout << "Cannot start with current state: sr: " << m_CurrentSamplingRate << " bs:" << m_CurrentBufferSize \
<< "\nReason: " << Pa_GetErrorText (paErr) << std::endl;
if (paErr == paUnanticipatedHostError)
std::cout << "Details: "<< Pa_GetLastHostErrorInfo ()->errorText << "; code: " << Pa_GetLastHostErrorInfo ()->errorCode << std::endl;
std::cout << "Will try again in " << PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS << "msec" << std::endl;
Pa_Sleep(PROPERTY_CHANGE_SLEEP_TIME_MILLISECONDS);
}
if (paErr == paNoError) if (paErr == paNoError)
{ {
m_CurrentBufferSize = preferredSize; // Notify the Application about device setting changes
} if (oldBufferSize != m_CurrentBufferSize)
else {
{ std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
// if we can't get device buffer sizes, use the first one among supported int bufferSize = m_CurrentBufferSize;
if (m_BufferSizes.size() != 0) m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
m_CurrentBufferSize = m_BufferSizes.front(); }
}
// Notify the Application about device setting changes // Activate the device if it was active before
if (oldBufferSize != m_CurrentBufferSize) if (wasActive)
{ activateDevice();
std::cout << "API::Device" << m_DeviceName << " buffer size changed" << std::endl;
int bufferSize = m_CurrentBufferSize;
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::BufferSizeChanged, (void *)&bufferSize);
}
// Activate the device if it was active before // Resume streaming if the device was streaming before
if (wasActive) if(wasStreaming && m_lastErr == eNoErr && m_ConnectionStatus == DeviceAvailable)
activateDevice(); {
// Notify the Application to prepare for the stream start
// Resume streaming if the device was streaming before m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming);
if(wasStreaming) startStreaming();
{ }
// Notify the Application to prepare for the stream start } else {
m_pMyManager->NotifyClient (WCMRAudioDeviceManagerClient::DeviceStartsStreaming); m_ConnectionStatus = DeviceErrors;
startStreaming(); m_lastErr = eWrongObjectState;
} }
if (callerIsWaiting) if (callerIsWaiting)
@ -1557,7 +1571,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceAvailableSampleRates(DeviceID deviceI
} }
} }
return retVal; return eNoErr;
} }
@ -1700,6 +1714,12 @@ WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & d
WTErr retVal = eNoErr; WTErr retVal = eNoErr;
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
sampleRates.assign(m_CurrentDevice->SamplingRates().begin(), m_CurrentDevice->SamplingRates().end() );
return retVal;
}
DeviceInfo devInfo; DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo); retVal = GetDeviceInfoByName(deviceName, devInfo);
@ -1719,29 +1739,23 @@ WTErr WCMRPortAudioDeviceManager::getDeviceSampleRatesImpl(const std::string & d
WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & deviceName, std::vector<int>& buffers) const
{ {
WTErr retVal = eNoErr; WTErr retVal = eNoErr;
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: getting buffer size for device: "<< deviceName << std::endl;
buffers.clear();
//first check if the request has been made for None device //first check if the request has been made for None device
if (deviceName == m_NoneDevice->DeviceName() ) if (deviceName == m_NoneDevice->DeviceName() )
{ {
buffers = m_NoneDevice->BufferSizes(); buffers.assign(m_NoneDevice->BufferSizes().begin(), m_NoneDevice->BufferSizes().end() );
return retVal;
}
if (m_CurrentDevice && deviceName == m_CurrentDevice->DeviceName() )
{
buffers.assign(m_CurrentDevice->BufferSizes().begin(), m_CurrentDevice->BufferSizes().end() );
return retVal; return retVal;
} }
//if we have current device initialized and it's PA device, reset it Pa_Initialize();
//this procedure will reset PA corrently and update info for all PA devices as well
bool paLocalInit = false;
WCMRPortAudioDevice* portaudioDevice = dynamic_cast<WCMRPortAudioDevice*>(m_CurrentDevice);
if (portaudioDevice)
{
portaudioDevice->ResetDevice();
}
else
{
//initialize PA to get buffers for the device
Pa_Initialize();
paLocalInit = true;
}
DeviceInfo devInfo; DeviceInfo devInfo;
retVal = GetDeviceInfoByName(deviceName, devInfo); retVal = GetDeviceInfoByName(deviceName, devInfo);
@ -1760,7 +1774,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
else else
{ {
retVal = eAsioFailed; retVal = eAsioFailed;
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << paErr << " getting buffer size fo device: "<< deviceName << std::endl; std::cout << "API::PortAudioDeviceManager::GetBufferSizes: error: " << Pa_GetErrorText (paErr) << " getting buffer size fo device: "<< deviceName << std::endl;
} }
} }
else else
@ -1768,9 +1782,7 @@ WTErr WCMRPortAudioDeviceManager::getDeviceBufferSizesImpl(const std::string & d
std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl; std::cout << "API::PortAudioDeviceManager::GetBufferSizes: Device not found: "<< deviceName << std::endl;
} }
//deinitialize PA now Pa_Terminate();
if (paLocalInit)
Pa_Terminate();
return retVal; return retVal;
} }