312 lines
8.2 KiB
C++
312 lines
8.2 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
MidiIOPrefs.cpp
|
|
|
|
Joshua Haberman
|
|
Dominic Mazzoni
|
|
James Crook
|
|
|
|
*******************************************************************//**
|
|
|
|
\class MidiIOPrefs
|
|
\brief A PrefsPanel used to select recording and playback devices and
|
|
other settings.
|
|
|
|
Presents interface for user to select the recording device and
|
|
playback device, from the list of choices that PortMidi
|
|
makes available.
|
|
|
|
Also lets user decide whether or not to record in stereo, and
|
|
whether or not to play other tracks while recording one (duplex).
|
|
|
|
*//********************************************************************/
|
|
|
|
#include "../Audacity.h"
|
|
#include "MidiIOPrefs.h"
|
|
|
|
#include "../Experimental.h"
|
|
|
|
#ifdef EXPERIMENTAL_MIDI_OUT
|
|
|
|
#include <wx/defs.h>
|
|
|
|
#include <wx/choice.h>
|
|
#include <wx/intl.h>
|
|
#include <wx/textctrl.h>
|
|
|
|
#include "../../lib-src/portmidi/pm_common/portmidi.h"
|
|
|
|
#include "../Prefs.h"
|
|
#include "../ShuttleGui.h"
|
|
#include "../widgets/AudacityMessageBox.h"
|
|
|
|
#define DEFAULT_SYNTH_LATENCY 5
|
|
|
|
enum {
|
|
HostID = 10000,
|
|
PlayID,
|
|
RecordID,
|
|
ChannelsID
|
|
};
|
|
|
|
BEGIN_EVENT_TABLE(MidiIOPrefs, PrefsPanel)
|
|
EVT_CHOICE(HostID, MidiIOPrefs::OnHost)
|
|
// EVT_CHOICE(RecordID, MidiIOPrefs::OnDevice)
|
|
END_EVENT_TABLE()
|
|
|
|
MidiIOPrefs::MidiIOPrefs(wxWindow * parent, wxWindowID winid)
|
|
/* i18n-hint: untranslatable acronym for "Musical Instrument Device Interface" */
|
|
: PrefsPanel(parent, winid, XO("MIDI Devices"))
|
|
{
|
|
Populate();
|
|
}
|
|
|
|
MidiIOPrefs::~MidiIOPrefs()
|
|
{
|
|
}
|
|
|
|
ComponentInterfaceSymbol MidiIOPrefs::GetSymbol()
|
|
{
|
|
return MIDI_IO_PREFS_PLUGIN_SYMBOL;
|
|
}
|
|
|
|
TranslatableString MidiIOPrefs::GetDescription()
|
|
{
|
|
return XO("Preferences for MidiIO");
|
|
}
|
|
|
|
wxString MidiIOPrefs::HelpPageName()
|
|
{
|
|
return "MIDI_Devices_Preferences";
|
|
}
|
|
|
|
void MidiIOPrefs::Populate()
|
|
{
|
|
// First any pre-processing for constructing the GUI.
|
|
GetNamesAndLabels();
|
|
|
|
// Get current setting for devices
|
|
mPlayDevice = gPrefs->Read(wxT("/MidiIO/PlaybackDevice"), wxT(""));
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
mRecordDevice = gPrefs->Read(wxT("/MidiIO/RecordingDevice"), wxT(""));
|
|
#endif
|
|
// mRecordChannels = gPrefs->Read(wxT("/MidiIO/RecordChannels"), 2L);
|
|
|
|
//------------------------- Main section --------------------
|
|
// Now construct the GUI itself.
|
|
// Use 'eIsCreatingFromPrefs' so that the GUI is
|
|
// initialised with values from gPrefs.
|
|
ShuttleGui S(this, eIsCreatingFromPrefs);
|
|
PopulateOrExchange(S);
|
|
// ----------------------- End of main section --------------
|
|
|
|
wxCommandEvent e;
|
|
OnHost(e);
|
|
}
|
|
|
|
/// Gets the lists of names and lists of labels which are
|
|
/// used in the choice controls.
|
|
/// The names are what the user sees in the wxChoice.
|
|
/// The corresponding labels are what gets stored.
|
|
void MidiIOPrefs::GetNamesAndLabels() {
|
|
// Gather list of hosts. Only added hosts that have devices attached.
|
|
Pm_Terminate(); // close and open to refresh device lists
|
|
Pm_Initialize();
|
|
int nDevices = Pm_CountDevices();
|
|
for (int i = 0; i < nDevices; i++) {
|
|
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
|
|
if (info->output || info->input) { //should always happen
|
|
wxString name = wxSafeConvertMB2WX(info->interf);
|
|
if (!make_iterator_range(mHostNames)
|
|
.contains( Verbatim( name ) )) {
|
|
mHostNames.push_back( Verbatim( name ) );
|
|
mHostLabels.push_back(name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MidiIOPrefs::PopulateOrExchange( ShuttleGui & S ) {
|
|
|
|
S.SetBorder(2);
|
|
S.StartScroller();
|
|
|
|
S.StartStatic(XO("Interface"));
|
|
{
|
|
S.StartMultiColumn(2);
|
|
{
|
|
S.Id(HostID);
|
|
/* i18n-hint: (noun) */
|
|
mHost = S.TieChoice( XO("&Host:"),
|
|
{
|
|
wxT("/MidiIO/Host"),
|
|
{ ByColumns, mHostNames, mHostLabels }
|
|
}
|
|
);
|
|
|
|
S.AddPrompt(XO("Using: PortMidi"));
|
|
}
|
|
S.EndMultiColumn();
|
|
}
|
|
S.EndStatic();
|
|
|
|
S.StartStatic(XO("Playback"));
|
|
{
|
|
S.StartMultiColumn(2);
|
|
{
|
|
S.Id(PlayID);
|
|
mPlay = S.AddChoice(XO("&Device:"),
|
|
{} );
|
|
mLatency = S.TieIntegerTextBox(XO("MIDI Synth L&atency (ms):"),
|
|
{wxT("/MidiIO/SynthLatency"),
|
|
DEFAULT_SYNTH_LATENCY}, 3);
|
|
}
|
|
S.EndMultiColumn();
|
|
}
|
|
S.EndStatic();
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
S.StartStatic(XO("Recording"));
|
|
{
|
|
S.StartMultiColumn(2);
|
|
{
|
|
S.Id(RecordID);
|
|
mRecord = S.AddChoice(XO("De&vice:"),
|
|
{} );
|
|
|
|
S.Id(ChannelsID);
|
|
/*
|
|
mChannels = S.AddChoice(XO("&Channels:"),
|
|
wxEmptyString,
|
|
{} );
|
|
*/
|
|
}
|
|
S.EndMultiColumn();
|
|
}
|
|
S.EndStatic();
|
|
#endif
|
|
S.EndScroller();
|
|
|
|
}
|
|
|
|
void MidiIOPrefs::OnHost(wxCommandEvent & WXUNUSED(e))
|
|
{
|
|
wxString itemAtIndex;
|
|
int index = mHost->GetCurrentSelection();
|
|
if (index >= 0 && index < (int)mHostNames.size())
|
|
itemAtIndex = mHostLabels[index];
|
|
int nDevices = Pm_CountDevices();
|
|
|
|
if (nDevices == 0) {
|
|
mHost->Clear();
|
|
mHost->Append(_("No MIDI interfaces"), (void *) NULL);
|
|
mHost->SetSelection(0);
|
|
}
|
|
|
|
mPlay->Clear();
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
mRecord->Clear();
|
|
#endif
|
|
|
|
wxArrayStringEx playnames;
|
|
wxArrayStringEx recordnames;
|
|
|
|
for (int i = 0; i < nDevices; i++) {
|
|
const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
|
|
wxString interf = wxSafeConvertMB2WX(info->interf);
|
|
if (itemAtIndex == interf) {
|
|
wxString name = wxSafeConvertMB2WX(info->name);
|
|
wxString device = wxString::Format(wxT("%s: %s"),
|
|
interf,
|
|
name);
|
|
if (info->output) {
|
|
playnames.push_back(name);
|
|
index = mPlay->Append(name, (void *) info);
|
|
if (device == mPlayDevice) {
|
|
mPlay->SetSelection(index);
|
|
}
|
|
}
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
if (info->input) {
|
|
recordnames.push_back(name);
|
|
index = mRecord->Append(name, (void *) info);
|
|
if (device == mRecordDevice) {
|
|
mRecord->SetSelection(index);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (mPlay->GetCount() == 0) {
|
|
playnames.push_back(_("No devices found"));
|
|
mPlay->Append(playnames[0], (void *) NULL);
|
|
}
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
if (mRecord->GetCount() == 0) {
|
|
recordnames.push_back(_("No devices found"));
|
|
mRecord->Append(recordnames[0], (void *) NULL);
|
|
}
|
|
#endif
|
|
if (mPlay->GetCount() && mPlay->GetSelection() == wxNOT_FOUND) {
|
|
mPlay->SetSelection(0);
|
|
}
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
if (mRecord->GetCount() && mRecord->GetSelection() == wxNOT_FOUND) {
|
|
mRecord->SetSelection(0);
|
|
}
|
|
#endif
|
|
ShuttleGui::SetMinSize(mPlay, playnames);
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
ShuttleGui::SetMinSize(mRecord, recordnames);
|
|
#endif
|
|
// OnDevice(e);
|
|
}
|
|
|
|
bool MidiIOPrefs::Commit()
|
|
{
|
|
ShuttleGui S(this, eIsSavingToPrefs);
|
|
PopulateOrExchange(S);
|
|
|
|
const PmDeviceInfo *info;
|
|
|
|
info = (const PmDeviceInfo *) mPlay->GetClientData(mPlay->GetSelection());
|
|
if (info) {
|
|
gPrefs->Write(wxT("/MidiIO/PlaybackDevice"),
|
|
wxString::Format(wxT("%s: %s"),
|
|
wxString(wxSafeConvertMB2WX(info->interf)),
|
|
wxString(wxSafeConvertMB2WX(info->name))));
|
|
}
|
|
#ifdef EXPERIMENTAL_MIDI_IN
|
|
info = (const PmDeviceInfo *) mRecord->GetClientData(mRecord->GetSelection());
|
|
if (info) {
|
|
gPrefs->Write(wxT("/MidiIO/RecordingDevice"),
|
|
wxString::Format(wxT("%s: %s"),
|
|
wxString(wxSafeConvertMB2WX(info->interf)),
|
|
wxString(wxSafeConvertMB2WX(info->name))));
|
|
}
|
|
#endif
|
|
return gPrefs->Flush();
|
|
}
|
|
|
|
bool MidiIOPrefs::Validate()
|
|
{
|
|
long latency;
|
|
if (!mLatency->GetValue().ToLong(&latency)) {
|
|
AudacityMessageBox( XO(
|
|
"The MIDI Synthesizer Latency must be an integer") );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
PrefsPanel::Factory
|
|
MidiIOPrefsFactory = [](wxWindow *parent, wxWindowID winid)
|
|
{
|
|
wxASSERT(parent); // to justify safenew
|
|
return safenew MidiIOPrefs(parent, winid);
|
|
};
|
|
|
|
#endif
|