Files
t7/XT7Main.cpp
2022-10-12 09:03:25 +02:00

661 lines
26 KiB
C++

/*
* File: XT7Main.cpp
* Author: SET - nmset@yandex.com
* Licence : LGPL 2.1
* Copyright SET, M.D. - © 2014
*
* Created on 1 mars 2014, 15:00
*/
#include "XT7Main.h"
#include <wx/msgdlg.h>
#include <wx/notifmsg.h>
#include <wx/stdpaths.h>
#include <iostream>
using namespace std;
int wxCALLBACK
CompareFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr WXUNUSED(sortData))
{
// Borrowed from wxListCtrl sample app, mostly verbatim.
if (item1 < item2)
return -1;
if (item1 > item2)
return 1;
return 0;
}
XT7Main::XT7Main() {
}
XT7Main::XT7Main( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
: T7Main(parent, id, caption, pos, size, style ){
wxConfigBase::DontCreateOnDemand();
config = static_cast<wxConfig*> (wxConfigBase::Get(false));
if (!config) {
config = new wxConfig(_APPNAME_T7_, _T("NMSET"), _APPNAME_T7_, wxEmptyString, wxCONFIG_USE_SUBDIR);
wxConfigBase::Set(config);
}
Init();
configError = !ArePedalsFullyConfigured();
if (!configError) {
ListenToPedal();
Bind(wxEVT_IDLE, &XT7Main::OnIdle, this);
m_keyHandler = new KeyboardSimulation(pedalEVH);
} else {
MessageBox(_(L"Configuration du pédalier incomplète."), true);
}
UpdateTitle();
}
XT7Main::~XT7Main() {
#ifdef T7_EMBEDDED
// In case it's embedded in some other application
if (!streamError && !configError) {
if (pedMonitor && pedMonitor->GetThread()->IsRunning()) pedMonitor->GetThread()->Delete();
if (mediaProgress && mediaProgress->GetThread()->IsRunning()) mediaProgress->GetThread()->Delete();
if (pedCodeIdentifier && pedCodeIdentifier->GetThread()->IsRunning()) pedCodeIdentifier->GetThread()->Delete();
}
#endif
delete m_keyHandler;
}
void XT7Main::UpdateTitle() {
wxString title(_APPNAME_T7_ + _T(" - ")+ _APPVERSION_T7_);
if (lvMediaList->IsEmpty() || lvMediaList->GetFocusedItem() == -1) {
SetTitle(title);
return;
}
// Get the file name
wxListItem it;
it.SetId(lvMediaList->GetFocusedItem());
it.SetColumn(2);
it.SetMask(wxLIST_MASK_TEXT);
if (lvMediaList->GetItem(it)) {
title += _T(" : ") + it.GetText();
SetTitle(title);
}
}
void XT7Main::MessageBox(const wxString& msg, const bool notify){
if (!notify) {
wxMessageBox(msg, _APPNAME_T7_, wxOK, this);
} else {
wxNotificationMessage notifMsg(_APPNAME_T7_, msg, this);
notifMsg.Show();
}
}
void XT7Main::CollapsiblePaneChanged(wxCollapsiblePaneEvent& evt) {
if (evt.GetEventObject() == panePedalIDs || evt.GetEventObject() == panePedalHardware) {
szPedalHardware->Layout();
szPedalMain->Layout();
szMediaInfo->Layout();
panPedals->GetSizer()->Layout();
}
}
void XT7Main::Init() {
pedMonitor = NULL; pedalEVH = NULL; pedCodeIdentifier = NULL; mediaProgress = NULL;
streamError = false;
if (!wxDir::Exists(wxStandardPaths::Get().GetUserDataDir()))
wxDir::Make(wxStandardPaths::Get().GetUserDataDir());
// UI doesn't provide a direct way to insert a wxListView
lvMediaList = new wxListView(panPedals);
szMediaTop->Add(lvMediaList, 1, wxGROW|wxALL, 5);
medMain->Show(false);
// cmb = wxComboBox
HIDTool::GetHIDDevices(cmbHIDDevices, hidPaths);
wxString device = config->Read(_T("/PEDALES/Dispositif"));
cmbHIDDevices->SetSelection(cmbHIDDevices->FindString(device, true));
cmbPedals->Append(_(L"de gauche"));
cmbPedals->Append(_(L"du milieu"));
cmbPedals->Append(_(L"de droite"));
cmbPedalActionLeft->Append(_(L"Retour rapide"));
cmbPedalActionLeft->Append(_(L"Avance rapide"));
cmbPedalActionLeft->Append(_(L"Lecture"));
cmbPedalActionMiddle->Append(_(L"Retour rapide"));
cmbPedalActionMiddle->Append(_(L"Avance rapide"));
cmbPedalActionMiddle->Append(_(L"Lecture"));
cmbPedalActionRight->Append(_(L"Retour rapide"));
cmbPedalActionRight->Append(_(L"Avance rapide"));
cmbPedalActionRight->Append(_(L"Lecture"));
// Automatic rewind on pause
// txt = wxTextCtrl
txtMediaAutoRewind->SetValidator(wxTextValidator(wxFILTER_DIGITS));
long autoRw = 1500;
config->Read(_T("/PEDALES/DIVERS/RetourAuto"), &autoRw);
txtMediaAutoRewind->SetValue(wxVariant(autoRw).GetString());
/*
* We provide default usual pedal actions :
* Left pedal : rewind
* Middle pedal : fast forward
* Right pedal : play
*/
long actionIndex = wxNOT_FOUND;
if (!config->Read(_T("/PEDALES/ACTIONS/Gauche"), &actionIndex)
&& !config->Read(_T("/PEDALES/ACTIONS/Milieu"), &actionIndex)
&& !config->Read(_T("/PEDALES/ACTIONS/Droit"), &actionIndex)) {
config->Write(_T("/PEDALES/ACTIONS/Gauche"), 0);
config->Write(_T("/PEDALES/ACTIONS/Milieu"), 1);
config->Write(_T("/PEDALES/ACTIONS/Droit"), 2);
config->Flush();
}
actionIndex = wxNOT_FOUND;
config->Read(_T("/PEDALES/ACTIONS/Gauche"), &actionIndex);
cmbPedalActionLeft->SetSelection(actionIndex);
actionIndex = wxNOT_FOUND;
config->Read(_T("/PEDALES/ACTIONS/Milieu"), &actionIndex);
cmbPedalActionMiddle->SetSelection(actionIndex);
actionIndex = wxNOT_FOUND;
config->Read(_T("/PEDALES/ACTIONS/Droit"), &actionIndex);
cmbPedalActionRight->SetSelection(actionIndex);
// lbl = wxStaticText
lblMediaCurrent->SetLabel(wxEmptyString);
lblMediaLength->SetLabel(wxEmptyString);
// sld = wxSlider
sldMediaPosition->Bind(wxEVT_SLIDER, &XT7Main::SliderChanged, this);
lvMediaList->Bind(wxEVT_LIST_ITEM_ACTIVATED, &XT7Main::LoadMedia, this);
// dpk = wxDirPicker
dpkMediaRoot->GetTextCtrl()->SetEditable(false);
dpkMediaRoot->SetPath(config->Read(_T("/Medias/Racine")));
dpkMediaRoot->Bind(wxEVT_DIRPICKER_CHANGED, &XT7Main::MediaRootChanged, this);
// btn = wxButton
btnMediaRootRefresh->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &XT7Main::ListMedia, this);
btnAbout->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &XT7Main::ShowAbout, this);
cmbHIDDevices->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &XT7Main::SavePedalDevice, this);
cmbPedalActionLeft->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &XT7Main::SavePedalAction, this);
cmbPedalActionMiddle->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &XT7Main::SavePedalAction, this);
cmbPedalActionRight->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &XT7Main::SavePedalAction, this);
cmbPedals->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &XT7Main::StartPedalCodeIdentification, this);
// pane = wxCollapsiblePane
panePedalIDs->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, &XT7Main::CollapsiblePaneChanged, this);
panePedalHardware->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, &XT7Main::CollapsiblePaneChanged, this);
txtMediaAutoRewind->Bind(wxEVT_COMMAND_TEXT_ENTER, &XT7Main::SavePedalAutoRewind, this);
// For display on Android handhelds where PPI may be set high for readable display
wxDouble scaleFactor = 1.0;
const wxDouble ppi = wxGetDisplayPPI().GetY();
if (ppi > 96.0) scaleFactor = (ppi / 96.0);
SetSize((int) (600.0 * scaleFactor), (int) (450.0 * scaleFactor));
}
bool XT7Main::ListenToPedal() {
// Create a pedal monitor and an event handler.
wxString device;
if (!config->Read(_T("/PEDALES/Dispositif"), &device)) return false;
if (!AreAllPedalsIdentified()) return false;
wxString devicePath = wxEmptyString;
if (cmbHIDDevices->GetSelection() != wxNOT_FOUND)
devicePath = hidPaths.Item(cmbHIDDevices->GetSelection());
long leftCode, middleCode, rightCode;
config->Read(_T("/PEDALES/ID/Gauche"), &leftCode);
config->Read(_T("/PEDALES/ID/Milieu"), &middleCode);
config->Read(_T("/PEDALES/ID/Droit"), &rightCode);
long autoRewind = 1500;
config->Read(_T("/PEDALES/DIVERS/RetourAuto"), &autoRewind);
pedalEVH = new PedalEVH(this, (wxFileOffset) autoRewind);
pedMonitor = new PedalMonitor_OnOff(devicePath, pedalEVH, leftCode, middleCode, rightCode);
//pedMonitor = new PedalMonitor_Override(devicePath, pedalEVH, leftCode, middleCode, rightCode);
if (pedMonitor->GetThread()->Run() != wxTHREAD_NO_ERROR) {
delete pedalEVH; pedalEVH = NULL;
if (pedMonitor->GetThread()->IsRunning()) {
pedMonitor->GetThread()->Delete();
pedMonitor = NULL;
}
return false;
}
return true;
}
void XT7Main::SavePedalDevice(wxCommandEvent& evt) {
if (config->Write(_T("/PEDALES/Dispositif"), cmbHIDDevices->GetValue())) {
MessageBox(_(L"Enregistré. Vous ne devriez pas jouer avec cette valeur une fois bien paramétrée."), true);
// Individual pedals must be identified again.
config->DeleteGroup(_T("/PEDALES/ID"));
config->Flush();
//MessageBox(_T("Vous devez compléter l'identification de toutes les pédales."), true);
} else {
MessageBox(_(L"Echec de sauvegarde."), true);
}
}
void XT7Main::SavePedalAction(wxCommandEvent& evt) {
// What the user decides to do with each pedal
bool inconsistent = false;
wxComboBox * cmb = static_cast<wxComboBox*> (evt.GetEventObject());
const int actionIndex = cmb->GetSelection();
if (cmb == cmbPedalActionLeft) {
inconsistent = (actionIndex == cmbPedalActionMiddle->GetSelection() || actionIndex == cmbPedalActionRight->GetSelection());
}
if (cmb == cmbPedalActionMiddle) {
inconsistent = (actionIndex == cmbPedalActionLeft->GetSelection() || actionIndex == cmbPedalActionRight->GetSelection());
}
if (cmb == cmbPedalActionRight) {
inconsistent = (actionIndex == cmbPedalActionLeft->GetSelection() || actionIndex == cmbPedalActionMiddle->GetSelection());
}
if (inconsistent) {
MessageBox(_(L"Choix inconsistants."), true);
return;
}
config->Write(_T("/PEDALES/ACTIONS/Gauche"), cmbPedalActionLeft->GetSelection());
config->Write(_T("/PEDALES/ACTIONS/Milieu"), cmbPedalActionMiddle->GetSelection());
config->Write(_T("/PEDALES/ACTIONS/Droit"), cmbPedalActionRight->GetSelection());
config->Flush();
}
void XT7Main::SavePedalAutoRewind(wxCommandEvent& evt) {
config->Write(_T("/PEDALES/DIVERS/RetourAuto"), wxVariant(txtMediaAutoRewind->GetValue()).GetLong());
config->Flush();
long newAutoRewind;
config->Read(_T("/PEDALES/DIVERS/RetourAuto"), &newAutoRewind);
if (pedalEVH) pedalEVH->UpdateAutoRewind((wxFileOffset) newAutoRewind);
}
bool XT7Main::ArePedalActionsConsistent() {
// One pedal, one unique action.
const int left = cmbPedalActionLeft->GetSelection();
const int middle = cmbPedalActionMiddle->GetSelection();
const int right = cmbPedalActionRight->GetSelection();
if ((left == wxNOT_FOUND) || (middle == wxNOT_FOUND) || (right == wxNOT_FOUND)) return false;
if ((left == middle) || (left == right)) return false;
if ((middle == right)) return false;
return true;
}
void XT7Main::StartPedalCodeIdentification(wxCommandEvent& evt) {
// Starts the thread that waits for a pedal to be pressed to catch the byte sent
if (streamError) return;
lblPedalCode->SetLabel(wxEmptyString);
if (!pedalEVH) pedalEVH = new PedalEVH(this);
if (!pedCodeIdentifier) {
wxString device = wxEmptyString;
config->Read(_T("/PEDALES/Dispositif"), &device);
if (device.IsEmpty()) {
MessageBox(_T("Périphérique non déclaré."), true);
return;
}
wxString devicePath = wxEmptyString;
devicePath = hidPaths.Item(cmbHIDDevices->GetSelection());
pedCodeIdentifier = new PedalCodeIdentifier(devicePath, pedalEVH);
pedCodeIdentifier->GetThread()->Run();
}
}
void XT7Main::UpdatePedalCode(const unsigned short code) {
/*
* Once started, process each pedal.
* We delete all known pedal codes and start all over.
* The user needs to do this only once
* or if she changes hardware
* Easier to code this way.
*/
static bool started = false;
if (!started) {
config->DeleteGroup(_T("/PEDALES/ID"));
config->Flush();
started = true;
MessageBox(_T("Vous devez compléter l'identification de toutes les pédales."), true);
}
switch (cmbPedals->GetSelection()) {
case 0:
config->Write(_T("/PEDALES/ID/Gauche"), (long) code);
break;
case 1:
config->Write(_T("/PEDALES/ID/Milieu"), (long) code);
break;
case 2:
config->Write(_T("/PEDALES/ID/Droit"), (long) code);
break;
default:
return;
}
config->Flush();
lblPedalCode->SetLabel(_(L"Enregistré. Vous pouvez identifier une autre pédale."));
configError = !ArePedalsFullyConfigured();
if (!configError) {
MessageBox(_T("Cette fenêtre va se fermer. Veuillez recommencer."));
Close();
}
}
bool XT7Main::AreAllPedalsIdentified() {
long left, middle, right;
return (config->Read(_T("/PEDALES/ID/Gauche"), &left)
&& config->Read(_T("/PEDALES/ID/Milieu"), &middle)
&& config->Read(_T("/PEDALES/ID/Droit"), &right));
}
bool XT7Main::ArePedalsFullyConfigured() {
wxString device = wxEmptyString;
return (config->Read(_T("/PEDALES/Dispositif"), &device) && AreAllPedalsIdentified());
}
void XT7Main::SliderChanged(wxCommandEvent& evt) {
// Manual media positioning
if (medMain) {
int pos = sldMediaPosition->GetValue();
medMain->Seek((wxFileOffset) pos);
wxTimeSpan past(0, 0, 0, pos);
lblMediaCurrent->SetLabel(past.Format(_T("%H:%M:%S")));
szMediaInfo->Layout();
}
}
void XT7Main::UpdateMediaProgressPosition() {
// Called from MediaProgress::Entry() via PedalEVH using CallAfter.
if (medMain) {
sldMediaPosition->SetValue(medMain->Tell());
wxTimeSpan past(0, 0, 0, medMain->Tell());
lblMediaCurrent->SetLabel(past.Format(_T("%H:%M:%S")));
} else {
// Should not happen !!!
sldMediaPosition->SetValue(0);
lblMediaCurrent->SetLabel(wxEmptyString);
lblMediaLength->SetLabel(wxEmptyString);
}
szMediaInfo->Layout();
}
void XT7Main::UpdateMediaControlPosition(wxFileOffset position) {
// Called by PedalEVH from MediaFastMove using CallAfter.
if (medMain) {
medMain->Seek(position, wxFromCurrent);
}
}
void XT7Main::LoadMedia(wxListEvent& evt) {
/*
* N.B. : Length() is always 0 *here*, and in wxEVT_MEDIA_LOADED also.
* But may be real in OnIdle, media dependent.
* Length() may be 0 in OnIdle for some valid media.
* Media type does not seem to be a factor (mp3, mp4, avi ...).
*/
UpdateTitle(); // In case we return early.
if (lvMediaList->GetFocusedItem() == -1) return; // REALLY ? ON DOUBLE CLICK OR ENTER
// Get the file name
wxListItem it;
it.SetId(lvMediaList->GetFocusedItem());
it.SetColumn(2);
it.SetMask(wxLIST_MASK_TEXT);
if (lvMediaList->GetItem(it)) {
wxString mediaRoot = config->Read(_T("/Medias/Racine"));
if (mediaRoot.IsEmpty()) return;
wxFileName media(mediaRoot + wxFileName::GetPathSeparator() + it.GetText());
if (media.Exists()) {
if (pedalEVH)
pedalEVH->PauseFastMoveWorkers();
// Manage media control
medMain->Stop();
if (medMain->Load(media.GetFullPath())) {
UpdateTitle();
loadedMediaPath = media.GetFullPath();
medMain->Show();
medMain->SetSize(medMain->GetBestSize());
panPedals->GetSizer()->Layout();
} else {
medMain->Hide();
}
sldMediaPosition->SetValue(0);
wxTimeSpan zero(0);
lblMediaCurrent->SetLabel(zero.Format(_T("%H:%M:%S")));
// Gives back positioning information
if (!mediaProgress) {
if (!configError) {
mediaProgress = new MediaProgress(pedalEVH);
mediaProgress->GetThread()->Run(); mediaProgress->GetThread()->Pause();
}
} else {
// if LoadMedia called while an action is going on
if (mediaProgress->GetThread()->IsRunning())
mediaProgress->GetThread()->Pause();
}
}
}
}
void XT7Main::OnIdle(wxIdleEvent& evt) {
if (lvMediaList->GetFocusedItem() == -1) return;
wxListItem itFileName;
itFileName.SetId(lvMediaList->GetFocusedItem());
itFileName.SetColumn(2);
itFileName.SetMask(wxLIST_MASK_TEXT);
if (lvMediaList->GetItem(itFileName)) {
wxString mediaRoot = config->Read(_T("/Medias/Racine"));
if (mediaRoot.IsEmpty()) return;
wxFileName media(mediaRoot + wxFileName::GetPathSeparator() + itFileName.GetText());
if (media.GetFullPath() != loadedMediaPath)
return;
}
wxListItem itDuration;
itDuration.SetId(lvMediaList->GetFocusedItem());
itDuration.SetColumn(1);
itDuration.SetMask(wxLIST_MASK_TEXT);
// Manage positioning controls. Update if changed only. May avoid flickering.
if (sldMediaPosition->GetMax() != medMain->Length())
sldMediaPosition->SetMax(medMain->Length());
wxTimeSpan duration(0, 0, 0, medMain->Length());
if (lblMediaLength->GetLabel() != duration.Format(_T("%H:%M:%S")))
lblMediaLength->SetLabel(duration.Format(_T("%H:%M:%S")));
if (lvMediaList->GetItem(itDuration)) {
if (itDuration.GetText() != lblMediaLength->GetLabel()) {
itDuration.SetText(lblMediaLength->GetLabel());
lvMediaList->SetItem(itDuration);
}
}
}
void XT7Main::MediaRootChanged(wxFileDirPickerEvent& evt) {
// A directory where we look for media files.
config->Write(_T("/Medias/Racine"), dpkMediaRoot->GetPath());
config->Flush();
loadedMediaPath = wxString();
}
void XT7Main::ListMedia(wxCommandEvent& evt) {
// We don't recurse in sub directories.
wxString mediaRoot = config->Read(_T("/Medias/Racine"));
if (mediaRoot.IsEmpty()) return;
lvMediaList->ClearAll();
wxArrayString files;
wxDir::GetAllFiles(mediaRoot, &files, wxEmptyString, wxDIR_FILES);
lvMediaList->AppendColumn(_T("Date"));
lvMediaList->AppendColumn(_T("Durée"));
lvMediaList->AppendColumn(_T("Dictée"));
for (int i = 0; i < files.GetCount(); i++) {
wxListItem it;
wxFileName filename(files.Item(i));
it.SetId(i);
it.SetColumn(0);
it.SetText(filename.GetModificationTime().Format(_T("%a %d %b %Y %H:%M:%S")));
long idx = lvMediaList->InsertItem(it);
lvMediaList->SetItemData(idx, (long) filename.GetModificationTime().GetTicks());
it.SetColumn(2);
it.SetText(filename.GetFullName());
lvMediaList->SetItem(it);
}
lvMediaList->SetColumnWidth(0, wxLIST_AUTOSIZE);
lvMediaList->SetColumnWidth(2, wxLIST_AUTOSIZE);
lvMediaList->SortItems(CompareFunction, 0);
panPedals->GetSizer()->Layout();
loadedMediaPath = wxString();
UpdateTitle();
}
void XT7Main::SetStreamError() {
streamError = true;
// We request application restart when stream is established again.
// We don't try to detect if the problem is resolved. Restart is cheap.
MessageBox(_(L"Erreur de communication avec le pédalier. Après avoir réglé le problème,"
" veuillez redémarrer l'application."
"\n\n Au clavier : F5, F6, F7, ESC."), true);
medMain->Stop();
UpdateMediaProgressPosition();
if (mediaProgress && mediaProgress->GetThread()->IsRunning()) mediaProgress->GetThread()->Pause();
if (pedalEVH) pedalEVH->ResetFastMoveWorkers();
}
void XT7Main::ShowAbout(wxCommandEvent& evt) {
wxString msg = _APPNAME_T7_ + _T(" - ") + _APPVERSION_T7_ + _T("\n\n");
msg += _(L"Auteur et copyright :") + _T("\n");
msg += wxString(_T("SET, M.D.")) + _T("\n");
msg += wxString(_T("nmset@yandex.com")) + _T("\n\n");
msg += wxString(_(L"Sous license LGPL"));
MessageBox(msg);
}
////////////////////////////////////////////////////////////////////////////////////////
/*
* Throughout, we want one background non-blocking worker through each
* pedal manager class. We do not want nor need concurrent multiple threads.
* MediaFastMove will have two non-concurrent threads.
* MediaFastMove threads are managed here. They never die.
* MediaProgress thread is managed by XT7Main. It never dies.
*/
PedalEVH::PedalEVH(XT7Main * parent, wxFileOffset newAutoRewindOnPause) {
m_owner = parent;
m_Rewind = NULL;
m_Forward = NULL;
m_autoRewind = newAutoRewindOnPause;
}
PedalEVH::~PedalEVH() {
ResetFastMoveWorkers();
}
void PedalEVH::UpdateAutoRewind(wxFileOffset newAutoRewindOnPause) {
m_autoRewind = newAutoRewindOnPause;
}
void PedalEVH::ResetFastMoveWorkers() {
// They should be assigned NULL from OnFastMoveExit()
// If IsRunning() is false, Delete() crashes app.
if (m_Rewind && m_Rewind->GetThread()->IsRunning()) {
m_Rewind->GetThread()->Delete();
}
if (m_Forward && m_Forward->GetThread()->IsRunning()) {
m_Forward->GetThread()->Delete();
}
}
void PedalEVH::PauseFastMoveWorkers() {
if (m_Rewind && m_Rewind->GetThread()->IsRunning()) {
m_Rewind->GetThread()->Pause();
}
if (m_Forward && m_Forward->GetThread()->IsRunning()) {
m_Forward->GetThread()->Pause();
}
}
/*
* A given pedal fires an action as declared by the user.
*/
void PedalEVH::Left(PedalEvent::PedalStatus status) {
const int action = m_owner->cmbPedalActionLeft->GetSelection();
switch (action) {
case 0:
Rewind(status);
break;
case 1:
FastForward(status);
break;
case 2:
Play(status);
break;
default :
m_owner->MessageBox(_(L"Action mal déclarée."), true);
}
}
void PedalEVH::Middle(PedalEvent::PedalStatus status) {
const int action = m_owner->cmbPedalActionMiddle->GetSelection();
switch (action) {
case 0:
Rewind(status);
break;
case 1:
FastForward(status);
break;
case 2:
Play(status);
break;
default :
m_owner->MessageBox(_(L"Action mal déclarée."), true);
}
}
void PedalEVH::Right(PedalEvent::PedalStatus status) {
const int action = m_owner->cmbPedalActionRight->GetSelection();
switch (action) {
case 0:
Rewind(status);
break;
case 1:
FastForward(status);
break;
case 2:
Play(status);
break;
default :
m_owner->MessageBox(_(L"Action mal déclarée."), true);
}
}
void PedalEVH::Rewind(PedalEvent::PedalStatus status) {
if (status == PedalEvent::PRESSED) {
if (!m_Rewind) {
m_Rewind = new MediaFastMove(m_owner->medMain, -100, 10, this);
m_Rewind->GetThread()->Run();
}
if (m_Rewind->GetThread()->IsPaused()) m_Rewind->GetThread()->Resume();
// UI can update media position.
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsPaused()) m_owner->mediaProgress->GetThread()->Resume();
}
if (status == PedalEvent::RELEASED) {
if (m_Rewind && m_Rewind->GetThread()->IsRunning()) m_Rewind->GetThread()->Pause();
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsRunning()) m_owner->mediaProgress->GetThread()->Pause();
}
}
void PedalEVH::FastForward(PedalEvent::PedalStatus status) {
if (status == PedalEvent::PRESSED) {
if (!m_Forward) {
m_Forward = new MediaFastMove(m_owner->medMain, 100, 10, this);
m_Forward->GetThread()->Run();
}
if (m_Forward->GetThread()->IsPaused()) m_Forward->GetThread()->Resume();
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsPaused()) m_owner->mediaProgress->GetThread()->Resume();
}
if (status == PedalEvent::RELEASED) {
if (m_Forward && m_Forward->GetThread()->IsRunning()) m_Forward->GetThread()->Pause();
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsRunning()) m_owner->mediaProgress->GetThread()->Pause();
}
}
void PedalEVH::Play(PedalEvent::PedalStatus status) {
// Not done through a thread.
if (status == PedalEvent::PRESSED) {
m_owner->medMain->Play();
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsPaused()) m_owner->mediaProgress->GetThread()->Resume();
}
if (status == PedalEvent::RELEASED) {
m_owner->medMain->Pause();
if (m_owner->mediaProgress && m_owner->mediaProgress->GetThread()->IsRunning()) m_owner->mediaProgress->GetThread()->Pause();
wxFileOffset pos = m_owner->medMain->Tell();
// Transcriptionists need that automatic rewind feature on pause.
if (pos > m_autoRewind) {
m_owner->medMain->Seek((m_autoRewind * -1), wxFromCurrent);
OnMediaProgressPosition();
}
}
}
// From PedalCodeIdentifier
void PedalEVH::OnPedalCaught(const unsigned short code) {
if (!code) return;
XT7Main * xapp = static_cast<XT7Main*> (m_owner);
xapp->CallAfter(&XT7Main::UpdatePedalCode, code);
}
void PedalEVH::OnCodeIdentifierExit(PedalCodeIdentifier* active) {
m_owner->pedCodeIdentifier = NULL;
}
void PedalEVH::OnMediaProgressExit(MediaProgress* active) {
m_owner->mediaProgress = NULL;
}
void PedalEVH::OnMediaProgressPosition() {
XT7Main * xapp = static_cast<XT7Main*> (m_owner);
xapp->CallAfter(&XT7Main::UpdateMediaProgressPosition);
}
void PedalEVH::OnMediaControlPosition(wxFileOffset position) {
XT7Main * xapp = static_cast<XT7Main*> (m_owner);
xapp->CallAfter(&XT7Main::UpdateMediaControlPosition, position);
}
void PedalEVH::OnStreamError() {
m_owner->SetStreamError();
}
void PedalEVH::OnPedalMonitorExit() {
m_owner->pedMonitor = NULL;
}
void PedalEVH::OnFastMoveExit(MediaFastMove * active) {
if (active == m_Forward) {
m_Forward = NULL;
}
if (active == m_Rewind) {
m_Rewind = NULL;
}
}