diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMic.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMic.cpp
index bf73dbc002..b2bb38d504 100644
--- a/Source/Core/Core/Src/HW/EXI_DeviceMic.cpp
+++ b/Source/Core/Core/Src/HW/EXI_DeviceMic.cpp
@@ -59,7 +59,7 @@ void CEXIMic::StreamInit()
void CEXIMic::StreamTerminate()
{
- if (pa_init && --mic_count <= 0)
+ if (--mic_count <= 0 && pa_init)
pa_error = Pa_Terminate();
if (pa_error != paNoError)
@@ -98,15 +98,17 @@ void CEXIMic::StreamReadOne()
{
pa_error = Pa_ReadStream(pa_stream, ring_buffer, buff_size_samples);
- if (pa_error != paNoError)
+ if (pa_error == paInputOverflowed)
{
status.buff_ovrflw = 1;
// Input overflowed - is re-setting the stream the only to recover?
- StreamLog("Pa_ReadStream");
-
StreamStop();
StreamStart();
}
+ else if (pa_error != paNoError)
+ {
+ StreamLog("Pa_ReadStream");
+ }
}
}
@@ -125,10 +127,17 @@ int CEXIMic::mic_count = 0;
CEXIMic::CEXIMic()
{
- status.U16 = 0;
- command = 0;
m_position = 0;
+ command = 0;
+ status.U16 = 0;
+
+ sample_rate = rate_base;
+ buff_size = ring_base;
+ buff_size_samples = buff_size / sample_size;
+
ring_pos = 0;
+ memset(ring_buffer, 0, sizeof(ring_buffer));
+
next_int_ticks = 0;
StreamInit();
@@ -194,7 +203,11 @@ void CEXIMic::TransferByte(u8 &byte)
break;
case cmdGetStatus:
+ if (pos == 0)
+ status.button = 0;// TODO
+
byte = status.U8[pos ^ 1];
+
if (pos == 1 && status.buff_ovrflw)
status.buff_ovrflw = 0;
break;
diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMic.h b/Source/Core/Core/Src/HW/EXI_DeviceMic.h
index e87d39f1a5..7631395100 100644
--- a/Source/Core/Core/Src/HW/EXI_DeviceMic.h
+++ b/Source/Core/Core/Src/HW/EXI_DeviceMic.h
@@ -55,7 +55,9 @@ private:
struct
{
u16 out :4; // MICSet/GetOut...???
- u16 button :5; // Buttons. Top bit is mic button. Lowest bit is used for MICGetDeviceID (always 0)
+ u16 id :1; // Used for MICGetDeviceID (always 0)
+ u16 button_unk :3; // Button bits which appear unused
+ u16 button :1; // The actual button on the mic
u16 buff_ovrflw :1; // Ring buffer wrote over bytes which weren't read by console
u16 gain :1; // Gain: 0dB or 15dB
u16 sample_rate :2; // Sample rate, 00-11025, 01-22050, 10-44100, 11-??
diff --git a/Source/Core/DolphinWX/Dolphin.vcxproj b/Source/Core/DolphinWX/Dolphin.vcxproj
index fc232ea77f..d6b854d075 100644
--- a/Source/Core/DolphinWX/Dolphin.vcxproj
+++ b/Source/Core/DolphinWX/Dolphin.vcxproj
@@ -236,6 +236,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
+
@@ -298,6 +299,7 @@ xcopy "$(SolutionDir)..\Externals\SDL\$(PlatformName)\*.dll" "$(TargetDir)" /e /
+
diff --git a/Source/Core/DolphinWX/Dolphin.vcxproj.filters b/Source/Core/DolphinWX/Dolphin.vcxproj.filters
index 3c14226fc0..d3ab073527 100644
--- a/Source/Core/DolphinWX/Dolphin.vcxproj.filters
+++ b/Source/Core/DolphinWX/Dolphin.vcxproj.filters
@@ -135,6 +135,9 @@
GUI
+
+ GUI
+
@@ -264,6 +267,9 @@
GUI
+
+ GUI
+
diff --git a/Source/Core/DolphinWX/Src/GCMicDlg.cpp b/Source/Core/DolphinWX/Src/GCMicDlg.cpp
new file mode 100644
index 0000000000..1cdd166cf5
--- /dev/null
+++ b/Source/Core/DolphinWX/Src/GCMicDlg.cpp
@@ -0,0 +1,290 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include
+
+#include "GCMicDlg.h"
+#include "ConfigManager.h"
+
+BEGIN_EVENT_TABLE(GCMicDialog,wxDialog)
+ EVT_COMMAND_RANGE(0, NUM_HOTKEYS - 1,
+ wxEVT_COMMAND_BUTTON_CLICKED, GCMicDialog::OnButtonClick)
+ EVT_TIMER(wxID_ANY, GCMicDialog::OnButtonTimer)
+END_EVENT_TABLE()
+
+GCMicDialog::GCMicDialog(wxWindow *parent, wxWindowID id, const wxString &title,
+ const wxPoint &position, const wxSize& size, long style)
+: wxDialog(parent, id, title, position, size, style)
+{
+ CreateHotkeyGUIControls();
+
+#if wxUSE_TIMER
+ m_ButtonMappingTimer = new wxTimer(this, wxID_ANY);
+ g_Pressed = 0;
+ g_Modkey = 0;
+ ClickedButton = NULL;
+ GetButtonWaitingID = 0;
+ GetButtonWaitingTimer = 0;
+#endif
+}
+
+GCMicDialog::~GCMicDialog()
+{
+ delete m_ButtonMappingTimer;
+}
+
+// Save keyboard key mapping
+void GCMicDialog::SaveButtonMapping(int Id, int Key, int Modkey)
+{
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[Id] = Key;
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id] = Modkey;
+}
+
+void GCMicDialog::EndGetButtons(void)
+{
+ wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
+ wxKeyEventHandler(GCMicDialog::OnKeyDown),
+ (wxObject*)0, this);
+ m_ButtonMappingTimer->Stop();
+ GetButtonWaitingTimer = 0;
+ GetButtonWaitingID = 0;
+ ClickedButton = NULL;
+ SetEscapeId(wxID_ANY);
+}
+
+void GCMicDialog::OnKeyDown(wxKeyEvent& event)
+{
+ if(ClickedButton != NULL)
+ {
+ // Save the key
+ g_Pressed = event.GetKeyCode();
+ g_Modkey = event.GetModifiers();
+
+ // Don't allow modifier keys
+ if (g_Pressed == WXK_CONTROL || g_Pressed == WXK_ALT ||
+ g_Pressed == WXK_SHIFT || g_Pressed == WXK_COMMAND)
+ return;
+
+ // Use the space key to set a blank key
+ if (g_Pressed == WXK_SPACE)
+ {
+ SaveButtonMapping(ClickedButton->GetId(), -1, 0);
+ SetButtonText(ClickedButton->GetId(), wxString());
+ }
+ else
+ {
+ SetButtonText(ClickedButton->GetId(),
+ InputCommon::WXKeyToString(g_Pressed),
+ InputCommon::WXKeymodToString(g_Modkey));
+ SaveButtonMapping(ClickedButton->GetId(), g_Pressed, g_Modkey);
+ }
+ EndGetButtons();
+ }
+}
+
+// Update the textbox for the buttons
+void GCMicDialog::SetButtonText(int id, const wxString &keystr, const wxString &modkeystr)
+{
+ m_Button_Hotkeys[id]->SetLabel(modkeystr + keystr);
+}
+
+void GCMicDialog::DoGetButtons(int _GetId)
+{
+ // Values used in this function
+ const int Seconds = 4; // Seconds to wait for
+ const int TimesPerSecond = 40; // How often to run the check
+
+ // If the Id has changed or the timer is not running we should start one
+ if( GetButtonWaitingID != _GetId || !m_ButtonMappingTimer->IsRunning() )
+ {
+ if(m_ButtonMappingTimer->IsRunning())
+ m_ButtonMappingTimer->Stop();
+
+ // Save the button Id
+ GetButtonWaitingID = _GetId;
+ GetButtonWaitingTimer = 0;
+
+ // Start the timer
+ #if wxUSE_TIMER
+ m_ButtonMappingTimer->Start(1000 / TimesPerSecond);
+ #endif
+ }
+
+ // Process results
+ // Count each time
+ GetButtonWaitingTimer++;
+
+ // This is run every second
+ if (GetButtonWaitingTimer % TimesPerSecond == 0)
+ {
+ // Current time
+ int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond);
+ // Update text
+ SetButtonText(_GetId, wxString::Format(wxT("[ %d ]"), TmpTime));
+ }
+
+ // Time's up
+ if (GetButtonWaitingTimer / TimesPerSecond >= Seconds)
+ {
+ // Revert back to old label
+ SetButtonText(_GetId, OldLabel);
+ EndGetButtons();
+ }
+}
+
+// Input button clicked
+void GCMicDialog::OnButtonClick(wxCommandEvent& event)
+{
+ event.Skip();
+
+ if (m_ButtonMappingTimer->IsRunning()) return;
+
+ wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard
+ wxKeyEventHandler(GCMicDialog::OnKeyDown),
+ (wxObject*)0, this);
+
+ // Get the button
+ ClickedButton = (wxButton *)event.GetEventObject();
+ SetEscapeId(wxID_CANCEL);
+ // Save old label so we can revert back
+ OldLabel = ClickedButton->GetLabel();
+ ClickedButton->SetWindowStyle(wxWANTS_CHARS);
+ ClickedButton->SetLabel(_(""));
+ DoGetButtons(ClickedButton->GetId());
+}
+
+#define HOTKEY_NUM_COLUMNS 2
+
+void GCMicDialog::CreateHotkeyGUIControls(void)
+{
+ const wxString pageNames[] =
+ {
+ _("General"),
+ _("State Saves")
+ };
+
+ const wxString hkText[] =
+ {
+ _("Open"),
+ _("Change Disc"),
+ _("Refresh List"),
+
+ _("Play/Pause"),
+ _("Stop"),
+ _("Reset"),
+ _("Frame Advance"),
+
+ _("Start Recording"),
+ _("Play Recording"),
+ _("Export Recording"),
+ _("Read-only mode"),
+
+ _("Toggle Fullscreen"),
+ _("Take Screenshot"),
+
+ _("Connect Wiimote 1"),
+ _("Connect Wiimote 2"),
+ _("Connect Wiimote 3"),
+ _("Connect Wiimote 4"),
+
+ _("Load State Slot 1"),
+ _("Load State Slot 2"),
+ _("Load State Slot 3"),
+ _("Load State Slot 4"),
+ _("Load State Slot 5"),
+ _("Load State Slot 6"),
+ _("Load State Slot 7"),
+ _("Load State Slot 8"),
+
+ _("Save State Slot 1"),
+ _("Save State Slot 2"),
+ _("Save State Slot 3"),
+ _("Save State Slot 4"),
+ _("Save State Slot 5"),
+ _("Save State Slot 6"),
+ _("Save State Slot 7"),
+ _("Save State Slot 8")
+ };
+
+ const int page_breaks[3] = {HK_OPEN, HK_LOAD_STATE_SLOT_1, NUM_HOTKEYS};
+
+ // Configuration controls sizes
+ wxSize size(100,20);
+ // A small type font
+ wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+
+ wxNotebook *Notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
+
+ for (int j = 0; j < 2; j++)
+ {
+ wxPanel *Page = new wxPanel(Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize);
+ Notebook->AddPage(Page, pageNames[j]);
+
+ wxGridBagSizer *sHotkeys = new wxGridBagSizer();
+
+ // Header line
+ for (int i = 0; i < HOTKEY_NUM_COLUMNS; i++)
+ {
+ wxBoxSizer *HeaderSizer = new wxBoxSizer(wxHORIZONTAL);
+ wxStaticText *StaticTextHeader = new wxStaticText(Page, wxID_ANY, _("Action"));
+ HeaderSizer->Add(StaticTextHeader, 1, wxALL, 2);
+ StaticTextHeader = new wxStaticText(Page, wxID_ANY, _("Key"), wxDefaultPosition, size);
+ HeaderSizer->Add(StaticTextHeader, 0, wxALL, 2);
+ sHotkeys->Add(HeaderSizer, wxGBPosition(0, i), wxDefaultSpan, wxEXPAND | wxLEFT, (i > 0) ? 30 : 1);
+ }
+
+ int column_break = (page_breaks[j+1] + page_breaks[j] + 1) / 2;
+
+ for (int i = page_breaks[j]; i < page_breaks[j+1]; i++)
+ {
+ // Text for the action
+ wxStaticText *stHotkeys = new wxStaticText(Page, wxID_ANY, hkText[i]);
+
+ // Key selection button
+ m_Button_Hotkeys[i] = new wxButton(Page, i, wxEmptyString,
+ wxDefaultPosition, size);
+ m_Button_Hotkeys[i]->SetFont(m_SmallFont);
+ m_Button_Hotkeys[i]->SetToolTip(_("Left click to detect hotkeys.\nEnter space to clear."));
+ SetButtonText(i,
+ InputCommon::WXKeyToString(SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[i]),
+ InputCommon::WXKeymodToString(
+ SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[i]));
+
+ wxBoxSizer *sHotkey = new wxBoxSizer(wxHORIZONTAL);
+ sHotkey->Add(stHotkeys, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 2);
+ sHotkey->Add(m_Button_Hotkeys[i], 0, wxALL, 2);
+ sHotkeys->Add(sHotkey,
+ wxGBPosition((i < column_break) ? i - page_breaks[j] + 1 : i - column_break + 1,
+ (i < column_break) ? 0 : 1),
+ wxDefaultSpan, wxEXPAND | wxLEFT, (i < column_break) ? 1 : 30);
+ }
+
+ wxStaticBoxSizer *sHotkeyBox = new wxStaticBoxSizer(wxVERTICAL, Page, _("Hotkeys"));
+ sHotkeyBox->Add(sHotkeys);
+
+ wxBoxSizer* const sPage = new wxBoxSizer(wxVERTICAL);
+ sPage->Add(sHotkeyBox, 0, wxEXPAND | wxALL, 5);
+ Page->SetSizer(sPage);
+ }
+
+ wxBoxSizer *sMainSizer = new wxBoxSizer(wxVERTICAL);
+ sMainSizer->Add(Notebook, 0, wxEXPAND | wxALL, 5);
+ sMainSizer->Add(CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT | wxDOWN, 5);
+ SetSizerAndFit(sMainSizer);
+ SetFocus();
+}
+
diff --git a/Source/Core/DolphinWX/Src/GCMicDlg.h b/Source/Core/DolphinWX/Src/GCMicDlg.h
new file mode 100644
index 0000000000..c817a67254
--- /dev/null
+++ b/Source/Core/DolphinWX/Src/GCMicDlg.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef __HOTKEYDIALOG_h__
+#define __HOTKEYDIALOG_h__
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Common.h"
+#include "CoreParameter.h"
+#include "WXInputBase.h"
+
+#if defined(HAVE_X11) && HAVE_X11
+#include "X11InputBase.h"
+#include
+#include
+#endif
+
+class GCMicDialog : public wxDialog
+{
+ public:
+ GCMicDialog(wxWindow *parent,
+ wxWindowID id = 1,
+ const wxString &title = _("GCMic Configuration"),
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_DIALOG_STYLE);
+ virtual ~GCMicDialog();
+
+ private:
+ DECLARE_EVENT_TABLE();
+
+ wxString OldLabel;
+
+ wxButton *ClickedButton,
+ *m_Button_Hotkeys[NUM_HOTKEYS];
+
+ wxTimer *m_ButtonMappingTimer;
+
+ void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); }
+ void OnButtonClick(wxCommandEvent& event);
+ void OnKeyDown(wxKeyEvent& event);
+ void SaveButtonMapping(int Id, int Key, int Modkey);
+ void CreateHotkeyGUIControls(void);
+
+ void SetButtonText(int id, const wxString &keystr, const wxString &modkeystr = wxString());
+
+ void DoGetButtons(int id);
+ void EndGetButtons(void);
+
+ int GetButtonWaitingID, GetButtonWaitingTimer, g_Pressed, g_Modkey;
+};
+#endif
+