Add loop point controls, draw waveform and playhead.
This commit is contained in:
parent
efc67f483c
commit
8aac911f07
|
|
@ -75,6 +75,7 @@ wx = dependency('wxwidgets', version: '>=3.0.4')
|
||||||
taglib = dependency('taglib', version: '>=1.11')
|
taglib = dependency('taglib', version: '>=1.11')
|
||||||
sqlite3 = dependency('sqlite3')
|
sqlite3 = dependency('sqlite3')
|
||||||
yaml = dependency('yaml-cpp')
|
yaml = dependency('yaml-cpp')
|
||||||
|
snd = dependency('sndfile')
|
||||||
|
|
||||||
install_subdir(
|
install_subdir(
|
||||||
'assets',
|
'assets',
|
||||||
|
|
@ -86,5 +87,5 @@ executable('SampleHive',
|
||||||
sources: src,
|
sources: src,
|
||||||
cpp_args: [wx_cxx_flags],
|
cpp_args: [wx_cxx_flags],
|
||||||
link_args: [wx_libs],
|
link_args: [wx_libs],
|
||||||
dependencies: [wx, taglib, sqlite3, yaml],
|
dependencies: [wx, taglib, sqlite3, yaml, snd],
|
||||||
install: true)
|
install: true)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ enum ControlIDs
|
||||||
BC_Settings,
|
BC_Settings,
|
||||||
BC_Loop,
|
BC_Loop,
|
||||||
BC_Stop,
|
BC_Stop,
|
||||||
|
BC_LoopPointButton,
|
||||||
|
BC_LoopPointText,
|
||||||
BC_Mute,
|
BC_Mute,
|
||||||
BC_Autoplay,
|
BC_Autoplay,
|
||||||
BC_Volume,
|
BC_Volume,
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,10 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <ios>
|
||||||
|
|
||||||
#include <wx/aboutdlg.h>
|
#include <wx/aboutdlg.h>
|
||||||
#include <wx/accel.h>
|
#include <wx/accel.h>
|
||||||
|
|
@ -29,6 +31,9 @@
|
||||||
#include <wx/artprov.h>
|
#include <wx/artprov.h>
|
||||||
#include <wx/busyinfo.h>
|
#include <wx/busyinfo.h>
|
||||||
#include <wx/dataview.h>
|
#include <wx/dataview.h>
|
||||||
|
#include <wx/dcclient.h>
|
||||||
|
#include <wx/dcbuffer.h>
|
||||||
|
#include <wx/dc.h>
|
||||||
#include <wx/debug.h>
|
#include <wx/debug.h>
|
||||||
#include <wx/defs.h>
|
#include <wx/defs.h>
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
|
|
@ -47,15 +52,20 @@
|
||||||
#include <wx/menu.h>
|
#include <wx/menu.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
#include <wx/object.h>
|
#include <wx/object.h>
|
||||||
|
#include <wx/pen.h>
|
||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
#include <wx/stringimpl.h>
|
#include <wx/stringimpl.h>
|
||||||
|
#include <wx/textctrl.h>
|
||||||
#include <wx/textdlg.h>
|
#include <wx/textdlg.h>
|
||||||
#include <wx/valtext.h>
|
#include <wx/valtext.h>
|
||||||
#include <wx/variant.h>
|
#include <wx/variant.h>
|
||||||
#include <wx/vector.h>
|
#include <wx/vector.h>
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
#include <wx/unix/stdpaths.h>
|
#include <wx/unix/stdpaths.h>
|
||||||
|
#include <wx/wxcrt.h>
|
||||||
|
|
||||||
|
#include <sndfile.hh>
|
||||||
|
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "ControlID_Enums.hpp"
|
#include "ControlID_Enums.hpp"
|
||||||
|
|
@ -244,30 +254,50 @@ MainFrame::MainFrame()
|
||||||
m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
|
m_TopSplitter->SplitHorizontally(m_TopPanel, m_BottomSplitter);
|
||||||
m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);
|
m_BottomSplitter->SplitVertically(m_BottomLeftPanel, m_BottomRightPanel);
|
||||||
|
|
||||||
|
m_TopWaveformPanel = new wxPanel(m_TopPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER);
|
||||||
|
m_TopControlsPanel = new wxPanel(m_TopPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxNO_BORDER);
|
||||||
|
|
||||||
|
// Looping region controls
|
||||||
|
m_LoopPointAButton = new wxToggleButton(m_TopControlsPanel, BC_LoopPointButton, _("A"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
|
m_LoopPointAButton->SetToolTip("Set Loop point A");
|
||||||
|
m_LoopPointAButton->Disable();
|
||||||
|
m_LoopPointAText = new wxTextCtrl(m_TopControlsPanel, BC_LoopPointText, _("00:00"), wxDefaultPosition, wxDefaultSize, wxTE_RIGHT | wxTE_PROCESS_ENTER);
|
||||||
|
m_LoopPointAText->Disable();
|
||||||
|
m_LoopPointAText->SetMinSize(wxSize(60, -1));
|
||||||
|
m_LoopPointAText->SetMaxSize(wxSize(60, -1));
|
||||||
|
m_LoopPointBButton = new wxToggleButton(m_TopControlsPanel, BC_LoopPointButton, _("B"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
|
m_LoopPointBButton->SetToolTip("Set Loop point B");
|
||||||
|
m_LoopPointBButton->Disable();
|
||||||
|
m_LoopPointBText = new wxTextCtrl(m_TopControlsPanel, BC_LoopPointText, _("00:00"), wxDefaultPosition, wxDefaultSize, wxTE_RIGHT | wxTE_PROCESS_ENTER);
|
||||||
|
m_LoopPointBText->Disable();
|
||||||
|
m_LoopPointBText->SetMinSize(wxSize(60, -1));
|
||||||
|
m_LoopPointBText->SetMaxSize(wxSize(60, -1));
|
||||||
|
|
||||||
// Initializing browser controls on top panel.
|
// Initializing browser controls on top panel.
|
||||||
m_AutoPlayCheck = new wxCheckBox(m_TopPanel, BC_Autoplay, _("Autoplay"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
|
m_AutoPlayCheck = new wxCheckBox(m_TopControlsPanel, BC_Autoplay, _("Autoplay"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE);
|
||||||
m_AutoPlayCheck->SetToolTip(_("Autoplay"));
|
m_AutoPlayCheck->SetToolTip(_("Autoplay"));
|
||||||
m_VolumeSlider = new wxSlider(m_TopPanel, BC_Volume, 100, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
|
m_VolumeSlider = new wxSlider(m_TopControlsPanel, BC_Volume, 100, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
|
||||||
m_VolumeSlider->SetToolTip(_("Volume"));
|
m_VolumeSlider->SetToolTip(_("Volume"));
|
||||||
m_VolumeSlider->SetMinSize(wxSize(120, -1));
|
m_VolumeSlider->SetMinSize(wxSize(120, -1));
|
||||||
m_VolumeSlider->SetMaxSize(wxSize(120, -1));
|
m_VolumeSlider->SetMaxSize(wxSize(120, -1));
|
||||||
m_SamplePosition = new wxStaticText(m_TopPanel, BC_SamplePosition, "--:--/--:--",
|
m_SamplePosition = new wxStaticText(m_TopControlsPanel, BC_SamplePosition, "--:--/--:--",
|
||||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL);
|
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL);
|
||||||
|
|
||||||
// Temporary widget to show a waveform sample image
|
// Temporary widget to show a waveform sample image
|
||||||
// TODO: Replace with actual waveform display
|
// TODO: Replace with actual waveform display
|
||||||
m_WaveformViewer = new wxStaticBitmap(m_TopPanel, wxID_ANY, wxBitmap(WAVEFORM_SVG));
|
// m_WaveformBitmap.LoadFile(WAVEFORM_SVG);
|
||||||
|
// m_WaveformViewer = new wxStaticBitmap(m_TopWaveformPanel, wxID_ANY, m_WaveformBitmap);
|
||||||
|
|
||||||
// Initialize browser control buttons
|
// Initialize browser control buttons
|
||||||
m_PlayButton = new wxButton(m_TopPanel, BC_Play, _("Play"), wxDefaultPosition, wxDefaultSize, 0);
|
m_PlayButton = new wxButton(m_TopControlsPanel, BC_Play, _("Play"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
m_PlayButton->SetToolTip(_("Play"));
|
m_PlayButton->SetToolTip(_("Play"));
|
||||||
m_LoopButton = new wxToggleButton(m_TopPanel, BC_Loop, _("Loop"), wxDefaultPosition, wxDefaultSize, 0);
|
m_LoopButton = new wxToggleButton(m_TopControlsPanel, BC_Loop, _("Loop"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
m_LoopButton->SetToolTip(_("Loop"));
|
m_LoopButton->SetToolTip(_("Loop"));
|
||||||
m_StopButton = new wxButton(m_TopPanel, BC_Stop, _("Stop"), wxDefaultPosition, wxDefaultSize, 0);
|
m_StopButton = new wxButton(m_TopControlsPanel, BC_Stop, _("Stop"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
m_StopButton->SetToolTip(_("Stop"));
|
m_StopButton->SetToolTip(_("Stop"));
|
||||||
m_SettingsButton = new wxButton(m_TopPanel, BC_Settings, _("Settings"), wxDefaultPosition, wxDefaultSize, 0);
|
m_SettingsButton = new wxButton(m_TopControlsPanel, BC_Settings, _("Settings"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
m_SettingsButton->SetToolTip(_("Settings"));
|
m_SettingsButton->SetToolTip(_("Settings"));
|
||||||
m_MuteButton = new wxToggleButton(m_TopPanel, BC_Mute, _("Mute"), wxDefaultPosition, wxDefaultSize, 0);
|
m_MuteButton = new wxToggleButton(m_TopControlsPanel, BC_Mute, _("Mute"), wxDefaultPosition, wxDefaultSize, 0);
|
||||||
m_MuteButton->SetToolTip(_("Mute"));
|
m_MuteButton->SetToolTip(_("Mute"));
|
||||||
|
|
||||||
// Initializing wxSearchCtrl on bottom panel.
|
// Initializing wxSearchCtrl on bottom panel.
|
||||||
|
|
@ -386,6 +416,10 @@ MainFrame::MainFrame()
|
||||||
Bind(wxEVT_TOGGLEBUTTON, &MainFrame::OnClickMute, this, BC_Mute);
|
Bind(wxEVT_TOGGLEBUTTON, &MainFrame::OnClickMute, this, BC_Mute);
|
||||||
Bind(wxEVT_MEDIA_FINISHED, &MainFrame::OnMediaFinished, this, BC_MediaCtrl);
|
Bind(wxEVT_MEDIA_FINISHED, &MainFrame::OnMediaFinished, this, BC_MediaCtrl);
|
||||||
Bind(wxEVT_BUTTON, &MainFrame::OnClickSettings, this, BC_Settings);
|
Bind(wxEVT_BUTTON, &MainFrame::OnClickSettings, this, BC_Settings);
|
||||||
|
Bind(wxEVT_TOGGLEBUTTON, &MainFrame::OnClickLoopPointsButton, this, BC_LoopPointButton);
|
||||||
|
Bind(wxEVT_TOGGLEBUTTON, &MainFrame::OnClickLoopPointsButton, this, BC_LoopPointButton);
|
||||||
|
Bind(wxEVT_TEXT_ENTER, &MainFrame::OnEnterLoopPoints, this, BC_LoopPointText);
|
||||||
|
Bind(wxEVT_TEXT_ENTER, &MainFrame::OnEnterLoopPoints, this, BC_LoopPointText);
|
||||||
Bind(wxEVT_CHECKBOX, &MainFrame::OnCheckAutoplay, this, BC_Autoplay);
|
Bind(wxEVT_CHECKBOX, &MainFrame::OnCheckAutoplay, this, BC_Autoplay);
|
||||||
Bind(wxEVT_SCROLL_THUMBTRACK, &MainFrame::OnSlideVolume, this, BC_Volume);
|
Bind(wxEVT_SCROLL_THUMBTRACK, &MainFrame::OnSlideVolume, this, BC_Volume);
|
||||||
Bind(wxEVT_SCROLL_THUMBRELEASE, &MainFrame::OnReleaseVolumeSlider, this, BC_Volume);
|
Bind(wxEVT_SCROLL_THUMBRELEASE, &MainFrame::OnReleaseVolumeSlider, this, BC_Volume);
|
||||||
|
|
@ -412,6 +446,9 @@ MainFrame::MainFrame()
|
||||||
Bind(wxEVT_BUTTON, &MainFrame::OnClickAddHive, this, BC_HiveAdd);
|
Bind(wxEVT_BUTTON, &MainFrame::OnClickAddHive, this, BC_HiveAdd);
|
||||||
Bind(wxEVT_BUTTON, &MainFrame::OnClickRemoveHive, this, BC_HiveRemove);
|
Bind(wxEVT_BUTTON, &MainFrame::OnClickRemoveHive, this, BC_HiveRemove);
|
||||||
|
|
||||||
|
m_TopWaveformPanel->Bind(wxEVT_PAINT, &MainFrame::OnPaint, this);
|
||||||
|
m_TopWaveformPanel->Bind(wxEVT_MOTION, &MainFrame::OnHoverPlayhead, this);
|
||||||
|
|
||||||
// Adding widgets to their sizers
|
// Adding widgets to their sizers
|
||||||
m_MainSizer->Add(m_MainPanel, 1, wxALL | wxEXPAND, 0);
|
m_MainSizer->Add(m_MainPanel, 1, wxALL | wxEXPAND, 0);
|
||||||
|
|
||||||
|
|
@ -424,14 +461,18 @@ MainFrame::MainFrame()
|
||||||
m_BrowserControlSizer->Add(0,0,1, wxALL | wxEXPAND, 0);
|
m_BrowserControlSizer->Add(0,0,1, wxALL | wxEXPAND, 0);
|
||||||
m_BrowserControlSizer->Add(m_SamplePosition, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
m_BrowserControlSizer->Add(m_SamplePosition, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
m_BrowserControlSizer->Add(30,0,0, wxALL | wxEXPAND, 0);
|
m_BrowserControlSizer->Add(30,0,0, wxALL | wxEXPAND, 0);
|
||||||
|
m_BrowserControlSizer->Add(m_LoopPointAButton, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
|
m_BrowserControlSizer->Add(m_LoopPointAText, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
|
m_BrowserControlSizer->Add(m_LoopPointBButton, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
|
m_BrowserControlSizer->Add(m_LoopPointBText, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
m_BrowserControlSizer->Add(m_MuteButton, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
m_BrowserControlSizer->Add(m_MuteButton, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
m_BrowserControlSizer->Add(m_VolumeSlider, 1, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
m_BrowserControlSizer->Add(m_VolumeSlider, 1, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
m_BrowserControlSizer->Add(m_AutoPlayCheck, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
m_BrowserControlSizer->Add(m_AutoPlayCheck, 0, wxALL | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 2);
|
||||||
|
|
||||||
m_WaveformDisplaySizer->Add(m_WaveformViewer, 1, wxALL | wxEXPAND, 2);
|
// m_WaveformDisplaySizer->Add(m_WaveformViewer, 1, wxALL | wxEXPAND, 2);
|
||||||
|
|
||||||
m_TopPanelMainSizer->Add(m_WaveformDisplaySizer, 1, wxALL | wxEXPAND, 2);
|
m_TopPanelMainSizer->Add(m_TopWaveformPanel, 1, wxALL | wxEXPAND, 2);
|
||||||
m_TopPanelMainSizer->Add(m_BrowserControlSizer, 0, wxALL | wxEXPAND, 2);
|
m_TopPanelMainSizer->Add(m_TopControlsPanel, 0, wxALL | wxEXPAND, 2);
|
||||||
|
|
||||||
m_BottomLeftPanelMainSizer->Add(m_Notebook, 1, wxALL | wxEXPAND, 0);
|
m_BottomLeftPanelMainSizer->Add(m_Notebook, 1, wxALL | wxEXPAND, 0);
|
||||||
|
|
||||||
|
|
@ -464,6 +505,16 @@ MainFrame::MainFrame()
|
||||||
m_TopSizer->SetSizeHints(m_MainPanel);
|
m_TopSizer->SetSizeHints(m_MainPanel);
|
||||||
m_TopSizer->Layout();
|
m_TopSizer->Layout();
|
||||||
|
|
||||||
|
m_TopControlsPanel->SetSizer(m_BrowserControlSizer);
|
||||||
|
m_BrowserControlSizer->Fit(m_TopControlsPanel);
|
||||||
|
m_BrowserControlSizer->SetSizeHints(m_TopControlsPanel);
|
||||||
|
m_BrowserControlSizer->Layout();
|
||||||
|
|
||||||
|
m_TopWaveformPanel->SetSizer(m_WaveformDisplaySizer);
|
||||||
|
m_WaveformDisplaySizer->Fit(m_TopWaveformPanel);
|
||||||
|
m_WaveformDisplaySizer->SetSizeHints(m_TopWaveformPanel);
|
||||||
|
m_WaveformDisplaySizer->Layout();
|
||||||
|
|
||||||
// Sizer for TopPanel
|
// Sizer for TopPanel
|
||||||
m_TopPanel->SetSizer(m_TopPanelMainSizer);
|
m_TopPanel->SetSizer(m_TopPanelMainSizer);
|
||||||
m_TopPanelMainSizer->Fit(m_TopPanel);
|
m_TopPanelMainSizer->Fit(m_TopPanel);
|
||||||
|
|
@ -885,7 +936,8 @@ void MainFrame::OnClickPlay(wxCommandEvent& event)
|
||||||
|
|
||||||
int selected_row = m_Library->GetSelectedRow();
|
int selected_row = m_Library->GetSelectedRow();
|
||||||
|
|
||||||
if (selected_row < 0) return;
|
if (selected_row < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
wxString selection = m_Library->GetTextValue(selected_row, 1);
|
wxString selection = m_Library->GetTextValue(selected_row, 1);
|
||||||
|
|
||||||
|
|
@ -915,10 +967,14 @@ void MainFrame::OnClickLoop(wxCommandEvent& event)
|
||||||
if (m_LoopButton->GetValue())
|
if (m_LoopButton->GetValue())
|
||||||
{
|
{
|
||||||
bLoop = true;
|
bLoop = true;
|
||||||
|
m_LoopPointAButton->Enable(true);
|
||||||
|
m_LoopPointBButton->Enable(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bLoop = false;
|
bLoop = false;
|
||||||
|
m_LoopPointAButton->Disable();
|
||||||
|
m_LoopPointBButton->Disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -988,6 +1044,8 @@ void MainFrame::UpdateElapsedTime(wxTimerEvent& event)
|
||||||
position.Printf(wxT("%2i:%02i"), current_min, current_sec);
|
position.Printf(wxT("%2i:%02i"), current_min, current_sec);
|
||||||
|
|
||||||
m_SamplePosition->SetLabel(wxString::Format(wxT("%s/%s"), position.c_str(), duration.c_str()));
|
m_SamplePosition->SetLabel(wxString::Format(wxT("%s/%s"), position.c_str(), duration.c_str()));
|
||||||
|
|
||||||
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::OnCheckAutoplay(wxCommandEvent& event)
|
void MainFrame::OnCheckAutoplay(wxCommandEvent& event)
|
||||||
|
|
@ -2858,4 +2916,265 @@ void MainFrame::SetAfterFrameCreate()
|
||||||
m_BottomSplitter->SetSashPosition(300);
|
m_BottomSplitter->SetSashPosition(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnClickLoopPointsButton(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
wxLogDebug("Loop point button clicked");
|
||||||
|
|
||||||
|
if (bLoop)
|
||||||
|
{
|
||||||
|
m_LoopPointAButton->Enable(true);
|
||||||
|
m_LoopPointBButton->Enable(true);
|
||||||
|
|
||||||
|
if (m_LoopPointAButton->GetValue())
|
||||||
|
m_LoopPointAText->Enable(true);
|
||||||
|
else
|
||||||
|
m_LoopPointAText->Disable();
|
||||||
|
|
||||||
|
if (m_LoopPointBButton->GetValue())
|
||||||
|
m_LoopPointBText->Enable(true);
|
||||||
|
else
|
||||||
|
m_LoopPointBText->Disable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_LoopPointAButton->Disable();
|
||||||
|
m_LoopPointBButton->Disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnEnterLoopPoints(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
wxLogDebug("Loop point text changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnPaint(wxPaintEvent& event)
|
||||||
|
{
|
||||||
|
wxPaintDC dc(m_TopWaveformPanel);
|
||||||
|
|
||||||
|
const wxSize size = m_TopWaveformPanel->GetClientSize();
|
||||||
|
|
||||||
|
if(!m_WaveformBitmap.IsOk()
|
||||||
|
|| m_WaveformBitmap.IsNull()
|
||||||
|
|| m_WaveformBitmap.GetWidth() != size.x
|
||||||
|
|| m_WaveformBitmap.GetHeight() != size.y)
|
||||||
|
{
|
||||||
|
m_WaveformBitmap = wxBitmap(wxImage(size.x, size.y), 32);
|
||||||
|
// m_WaveformBitmap.Create(size.x, size.y, 32);
|
||||||
|
wxLogDebug("Updating waveform bitmap..");
|
||||||
|
UpdateWaveformBitmap();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wxLogDebug("Cannot update waveform bitmap..");
|
||||||
|
|
||||||
|
dc.DrawBitmap(m_WaveformBitmap, 0, 0, false);
|
||||||
|
// m_WaveformBitmap.SaveFile("waveform.png", wxBITMAP_TYPE_PNG);
|
||||||
|
|
||||||
|
RenderPlayhead(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::RenderPlayhead(wxDC& dc)
|
||||||
|
{
|
||||||
|
int selected_row = m_Library->GetSelectedRow();
|
||||||
|
|
||||||
|
if (selected_row < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString selected = m_Library->GetTextValue(selected_row, 1);
|
||||||
|
std::string path = GetFilenamePathAndExtension(selected).Path.ToStdString();
|
||||||
|
|
||||||
|
Tags tags(path);
|
||||||
|
|
||||||
|
int length = tags.GetAudioInfo().length;
|
||||||
|
wxLogDebug("Len: %d", length);
|
||||||
|
|
||||||
|
double position = m_MediaCtrl->Tell();
|
||||||
|
wxLogDebug("Pos: %f", position);
|
||||||
|
|
||||||
|
m_Timer->Start(1, wxTIMER_CONTINUOUS);
|
||||||
|
|
||||||
|
int panel_width = m_TopWaveformPanel->GetSize().GetWidth();
|
||||||
|
double line_pos = panel_width * (position / length);
|
||||||
|
|
||||||
|
wxLogDebug("Drawing at: %f", line_pos);
|
||||||
|
|
||||||
|
// Draw the triangle
|
||||||
|
dc.SetPen(wxPen(wxColor(255, 0, 0, 255), 8, wxPENSTYLE_SOLID));
|
||||||
|
dc.DrawLine(line_pos - 5, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
line_pos, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1) + 5);
|
||||||
|
dc.DrawLine(line_pos + 5, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
line_pos, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight()- 1) + 5);
|
||||||
|
|
||||||
|
// Draw the line
|
||||||
|
dc.SetPen(wxPen(wxColor(255, 0, 0, 255), 2, wxPENSTYLE_SOLID));
|
||||||
|
dc.DrawLine(line_pos, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
line_pos, m_TopWaveformPanel->GetSize().GetHeight() - 1);
|
||||||
|
|
||||||
|
// For testing only
|
||||||
|
// dc.DrawLine(100 - 5, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
// 100, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1) + 5);
|
||||||
|
// dc.DrawLine(100 + 5, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
// 100, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight()- 1) + 5);
|
||||||
|
|
||||||
|
// // Draw the line
|
||||||
|
// dc.SetPen(wxPen(wxColor(255, 0, 0, 255), 2, wxPENSTYLE_SOLID));
|
||||||
|
// dc.DrawLine(100, m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
// 100, m_TopWaveformPanel->GetSize().GetHeight() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::UpdateWaveformBitmap()
|
||||||
|
{
|
||||||
|
Database db(*m_InfoBar);
|
||||||
|
Settings settings(this, m_ConfigFilepath, m_DatabaseFilepath);
|
||||||
|
|
||||||
|
int selected_row = m_Library->GetSelectedRow();
|
||||||
|
|
||||||
|
if (selected_row < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString selection = m_Library->GetTextValue(selected_row, 1);
|
||||||
|
|
||||||
|
wxString filepath_with_extension = db.GetSamplePathByFilename(static_cast<std::string>(DATABASE_FILEPATH),
|
||||||
|
selection.BeforeLast('.').ToStdString());
|
||||||
|
wxString filepath_without_extension = db.GetSamplePathByFilename(static_cast<std::string>(DATABASE_FILEPATH),
|
||||||
|
selection.ToStdString());
|
||||||
|
|
||||||
|
std::string extension = settings.ShouldShowFileExtension() ?
|
||||||
|
db.GetSampleFileExtension(static_cast<std::string>(DATABASE_FILEPATH), selection.ToStdString()) :
|
||||||
|
db.GetSampleFileExtension(static_cast<std::string>(DATABASE_FILEPATH), selection.BeforeLast('.').ToStdString());
|
||||||
|
|
||||||
|
wxString path = selection.Contains(wxString::Format(".%s", extension)) ?
|
||||||
|
filepath_with_extension : filepath_without_extension;
|
||||||
|
|
||||||
|
SndfileHandle snd_file(path);
|
||||||
|
|
||||||
|
int channels = snd_file.channels();
|
||||||
|
double sample_rate = snd_file.samplerate();
|
||||||
|
sf_count_t frames = snd_file.frames();
|
||||||
|
|
||||||
|
std::vector<float> sample;
|
||||||
|
sample.resize(frames * channels);
|
||||||
|
|
||||||
|
std::vector<signed char> waveform;
|
||||||
|
|
||||||
|
snd_file.read(&sample.at(0), frames * channels);
|
||||||
|
|
||||||
|
float display_width = m_TopWaveformPanel->GetSize().GetWidth();
|
||||||
|
float display_height = m_TopWaveformPanel->GetSize().GetHeight();
|
||||||
|
|
||||||
|
double max_value;
|
||||||
|
snd_file.command(SFC_CALC_NORM_SIGNAL_MAX, &max_value, sizeof(max_value));
|
||||||
|
|
||||||
|
float normalized_value = max_value > 1.0f ? 1.0f : 1.0f / max_value;
|
||||||
|
|
||||||
|
float samples_per_pixel = static_cast<float>(frames) / (float)display_width;
|
||||||
|
// float samples_per_pixel = waveform.size() / float(display_width);
|
||||||
|
|
||||||
|
if (channels == 2)
|
||||||
|
{
|
||||||
|
for (int i = 0, j = 0 ; i < frames; i++)
|
||||||
|
{
|
||||||
|
float sum = (((sample[j] + sample[j + 1]) * 0.5f) * normalized_value) * float(display_height / 2.0f);
|
||||||
|
waveform.push_back(sum);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
waveform.resize(frames);
|
||||||
|
|
||||||
|
for (int i = 0; i < frames; i++)
|
||||||
|
{
|
||||||
|
waveform[i] = (sample[i] * normalized_value) * float(display_height / 2.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// float minimap_height = 0.0f;
|
||||||
|
// // make minimap
|
||||||
|
// std::vector<char> miniMap;
|
||||||
|
// miniMap.resize(display_width);
|
||||||
|
// // float samples_per_pixel = static_cast<float>(sampleLength) / (float)display_width;
|
||||||
|
// float fIndex;
|
||||||
|
// uint iIndex;
|
||||||
|
// for (uint16_t i = 0; i < display_width; i++)
|
||||||
|
// {
|
||||||
|
// fIndex = float(i) * samples_per_pixel;
|
||||||
|
// iIndex = fIndex;
|
||||||
|
// auto minmax = std::minmax_element(waveform.begin() + iIndex, waveform.begin() + iIndex + int(samples_per_pixel));
|
||||||
|
// signed char min = std::abs(*minmax.first);
|
||||||
|
// signed char max = std::abs(*minmax.second);
|
||||||
|
// signed char maxValue = std::max(min, max);
|
||||||
|
// miniMap[i] = (float)maxValue / (float)(display_height / 2) * (float)minimap_height;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*===========================Draw code============================*/
|
||||||
|
wxMemoryDC mdc(m_WaveformBitmap);
|
||||||
|
|
||||||
|
if (!mdc.IsOk())
|
||||||
|
{
|
||||||
|
wxLogDebug("MDC NOT OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wxLogDebug("MDC OK");
|
||||||
|
|
||||||
|
mdc.SetPen(wxPen(wxColour(255, 255, 255, 255), 2, wxPENSTYLE_SOLID));
|
||||||
|
|
||||||
|
for(int i = 0; i < waveform.size() - 1; i++)
|
||||||
|
{
|
||||||
|
// dc.DrawPoint((display_width * static_cast<float>(i)) / waveform.size(),
|
||||||
|
// (waveform[i] / samples_per_pixel) + float(display_height / 2.0f));
|
||||||
|
|
||||||
|
// dc.DrawLine((display_width * static_cast<float>(i)) / waveform.size(),
|
||||||
|
// waveform[i] + float(display_height / 2.0f),
|
||||||
|
// (display_width * static_cast<float>(i)) / waveform.size(),
|
||||||
|
// waveform[i] + float(display_height / 2.0f));
|
||||||
|
|
||||||
|
mdc.DrawLine((display_width * i) / waveform.size(), waveform[i] + display_height / 2.0f,
|
||||||
|
(display_width * i) / waveform.size(), (waveform[i] / samples_per_pixel) + display_height / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (!mdc.IsOk())
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// dc.Blit(m_TopWaveformPanel->GetSize().GetWidth() - (m_TopWaveformPanel->GetSize().GetWidth() - 1),
|
||||||
|
// m_TopWaveformPanel->GetSize().GetHeight() - (m_TopWaveformPanel->GetSize().GetHeight() - 1),
|
||||||
|
// m_WaveformBitmap.GetWidth(), m_WaveformBitmap.GetHeight(), &mdc, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainFrame::OnHoverPlayhead(wxMouseEvent& event)
|
||||||
|
{
|
||||||
|
int selected_row = m_Library->GetSelectedRow();
|
||||||
|
|
||||||
|
if (selected_row < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString selected = m_Library->GetTextValue(selected_row, 1);
|
||||||
|
std::string path = GetFilenamePathAndExtension(selected).Path.ToStdString();
|
||||||
|
|
||||||
|
Tags tags(path);
|
||||||
|
|
||||||
|
int length = tags.GetAudioInfo().length;
|
||||||
|
|
||||||
|
double position = m_MediaCtrl->Tell();
|
||||||
|
|
||||||
|
int panel_width = m_TopWaveformPanel->GetSize().GetWidth();
|
||||||
|
double line_pos = panel_width * (position / length);
|
||||||
|
|
||||||
|
wxPoint pos = event.GetPosition();
|
||||||
|
|
||||||
|
if (pos.x >= line_pos - (line_pos - 5) && pos.x >= line_pos - (line_pos + 5) && pos.y <= line_pos + 5 && pos.y >= line_pos - 5)
|
||||||
|
{
|
||||||
|
this->SetCursor(wxCursor(wxCURSOR_CROSS));
|
||||||
|
wxLogDebug("Capturing mouse..");
|
||||||
|
// SetBackgroundColour("Green");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetCursor(wxCursor(wxCURSOR_ARROW));
|
||||||
|
// SetBackgroundColour("Brown");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLogDebug("Mouse at: '(%d, %d)'", pos.x, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
MainFrame::~MainFrame(){}
|
MainFrame::~MainFrame(){}
|
||||||
|
|
|
||||||
|
|
@ -106,16 +106,22 @@ class MainFrame : public wxFrame
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Top panel controls
|
// Top panel controls
|
||||||
wxPanel* m_TopPanel;
|
wxPanel* m_TopPanel;
|
||||||
|
wxPanel* m_TopWaveformPanel;
|
||||||
|
wxPanel* m_TopControlsPanel;
|
||||||
wxBoxSizer* m_TopSizer;
|
wxBoxSizer* m_TopSizer;
|
||||||
wxBoxSizer* m_TopPanelMainSizer;
|
wxBoxSizer* m_TopPanelMainSizer;
|
||||||
wxBoxSizer* m_WaveformDisplaySizer;
|
wxBoxSizer* m_WaveformDisplaySizer;
|
||||||
wxStaticBitmap* m_WaveformViewer;
|
wxBitmap m_WaveformBitmap ;
|
||||||
wxBoxSizer* m_BrowserControlSizer;
|
wxBoxSizer* m_BrowserControlSizer;
|
||||||
wxButton* m_PlayButton;
|
wxButton* m_PlayButton;
|
||||||
wxToggleButton* m_LoopButton;
|
wxToggleButton* m_LoopButton;
|
||||||
wxButton* m_StopButton;
|
wxButton* m_StopButton;
|
||||||
wxButton* m_SettingsButton;
|
wxButton* m_SettingsButton;
|
||||||
wxToggleButton* m_MuteButton;
|
wxToggleButton* m_MuteButton;
|
||||||
|
wxToggleButton* m_LoopPointAButton;
|
||||||
|
wxToggleButton* m_LoopPointBButton;
|
||||||
|
wxTextCtrl* m_LoopPointAText;
|
||||||
|
wxTextCtrl* m_LoopPointBText;
|
||||||
wxStaticText* m_SamplePosition;
|
wxStaticText* m_SamplePosition;
|
||||||
wxSlider* m_VolumeSlider;
|
wxSlider* m_VolumeSlider;
|
||||||
wxCheckBox* m_AutoPlayCheck;
|
wxCheckBox* m_AutoPlayCheck;
|
||||||
|
|
@ -186,6 +192,8 @@ class MainFrame : public wxFrame
|
||||||
void OnSlideVolume(wxScrollEvent& event);
|
void OnSlideVolume(wxScrollEvent& event);
|
||||||
void OnReleaseVolumeSlider(wxScrollEvent& event);
|
void OnReleaseVolumeSlider(wxScrollEvent& event);
|
||||||
void OnClickSettings(wxCommandEvent& event);
|
void OnClickSettings(wxCommandEvent& event);
|
||||||
|
void OnClickLoopPointsButton(wxCommandEvent& event);
|
||||||
|
void OnEnterLoopPoints(wxCommandEvent& event);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// DirCtrl event handlers
|
// DirCtrl event handlers
|
||||||
|
|
@ -264,6 +272,12 @@ class MainFrame : public wxFrame
|
||||||
// Call after frame creation
|
// Call after frame creation
|
||||||
void SetAfterFrameCreate();
|
void SetAfterFrameCreate();
|
||||||
|
|
||||||
|
// Drawing playhead and waveform
|
||||||
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
void RenderPlayhead(wxDC& dc);
|
||||||
|
void UpdateWaveformBitmap();
|
||||||
|
void OnHoverPlayhead(wxMouseEvent& event);
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
friend class App;
|
friend class App;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue