wxWidgets/contrib/samples/mmedia/mmboard.cpp

585 lines
16 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////////
// Name: mmboard.cpp
// Purpose: Multimedia Library sample
// Author: Guilhem Lavaux (created from minimal by J. Smart)
// Modified by:
// Created: 13/02/2000
// RCS-ID: $Id$
// Copyright: (c) Guilhem Lavaux
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "mmboard.cpp"
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------------------------------------------------------
// ressources
// ----------------------------------------------------------------------------
// the application icon
#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
#include "mondrian.xpm"
#endif
// include multimedia classes
#include "wx/mmedia/sndbase.h"
#ifdef __WIN32__
#include "wx/mmedia/sndwin.h"
#endif
#ifdef __UNIX__
#include "wx/mmedia/sndoss.h"
#include "wx/mmedia/sndesd.h"
#endif
#include "wx/statline.h"
#include "wx/stattext.h"
// include personnal classes
#include "mmboard.h"
#include "mmbman.h"
#include "play.xpm"
#include "stop.xpm"
#include "eject.xpm"
#include "pause.xpm"
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Main Multimedia Board frame
class MMBoardFrame : public wxFrame
{
public:
// ctor(s)
MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
// dtor
~MMBoardFrame();
// event handlers
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnOpen(wxCommandEvent& event);
void OnPlay(wxCommandEvent& event);
void OnStop(wxCommandEvent& event);
void OnPause(wxCommandEvent& event);
void OnEject(wxCommandEvent& event);
void OnRefreshInfo(wxEvent& event);
void OnSetPosition(wxCommandEvent& event);
void OpenVideoWindow();
void CloseVideoWindow();
private:
// any class wishing to process wxWidgets events must use this macro
DECLARE_EVENT_TABLE()
private:
void UpdateMMedInfo();
void UpdateInfoText();
MMBoardFile *m_opened_file;
wxSlider *m_positionSlider;
wxBitmapButton *m_playButton, *m_pauseButton, *m_stopButton, *m_ejectButton;
wxStaticText *m_fileType, *m_infoText;
wxWindow *m_video_window;
wxPanel *m_panel;
wxSizer *m_sizer;
wxTimer *m_refreshTimer;
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
MMBoard_Quit = 1,
MMBoard_Open,
MMBoard_About,
MMBoard_PositionSlider,
MMBoard_PlayButton,
MMBoard_PauseButton,
MMBoard_ResumeButton,
MMBoard_StopButton,
MMBoard_EjectButton,
MMBoard_RefreshInfo
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(MMBoardFrame, wxFrame)
EVT_MENU(MMBoard_Quit, MMBoardFrame::OnQuit)
EVT_MENU(MMBoard_About, MMBoardFrame::OnAbout)
EVT_MENU(MMBoard_Open, MMBoardFrame::OnOpen)
EVT_BUTTON(MMBoard_PlayButton, MMBoardFrame::OnPlay)
EVT_BUTTON(MMBoard_StopButton, MMBoardFrame::OnStop)
EVT_BUTTON(MMBoard_PauseButton, MMBoardFrame::OnPause)
EVT_BUTTON(MMBoard_EjectButton, MMBoardFrame::OnEject)
EVT_SLIDER(MMBoard_PositionSlider, MMBoardFrame::OnSetPosition)
EVT_CUSTOM(wxEVT_TIMER, MMBoard_RefreshInfo, MMBoardFrame::OnRefreshInfo)
END_EVENT_TABLE()
// ---------------------------------------------------------------------------
// Main board application launcher
// ---------------------------------------------------------------------------
IMPLEMENT_APP(MMBoardApp)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
bool MMBoardApp::OnInit()
{
// create the main application window
MMBoardFrame *frame = new MMBoardFrame(_T("Multimedia Board"),
wxPoint(50, 50), wxSize(450, 340));
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
frame->Show();
m_caps = TestMultimediaCaps();
if (!m_caps) {
wxMessageBox(_T("Your system has no multimedia capabilities. We are exiting now."), _T("Major error !"), wxOK | wxICON_ERROR, NULL);
return false;
}
wxString msg;
msg.Printf(_T("Detected : %s%s%s"), (m_caps & MM_SOUND_OSS) ? _T("OSS ") : _T(""),
(m_caps & MM_SOUND_ESD) ? _T("ESD ") : _T(""),
(m_caps & MM_SOUND_WIN) ? _T("WIN") : _T(""));
wxMessageBox(msg, _T("Good !"), wxOK | wxICON_INFORMATION, NULL);
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// application would exit immediately.
return true;
}
wxUint8 MMBoardApp::TestMultimediaCaps()
{
wxSoundStream *dev;
wxUint8 caps;
caps = 0;
#ifdef __UNIX__
// We now test the ESD support
dev = new wxSoundStreamESD();
if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_ESD;
delete dev;
// We test the OSS (Open Sound System) support.
// WARNING: There is a conflict between ESD and ALSA. We may be interrested
// in disabling the auto detection of OSS is ESD has been detected.
#if 1
if (!(caps & MM_SOUND_ESD)) {
#endif
dev = new wxSoundStreamOSS();
if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_OSS;
delete dev;
#if 1
}
#endif
#endif
#ifdef __WIN32__
// We test the Windows sound support.
dev = new wxSoundStreamWin();
if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_WIN;
delete dev;
#endif
return caps;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MMBoardFrame::MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
{
#ifdef __WXMAC__
// we need this in order to allow the about menu relocation, since ABOUT is
// not the default id of the about menu
wxApp::s_macAboutMenuItemId = MMBoard_About;
#endif
// set the frame icon
SetIcon(wxICON(mondrian));
// create a menu bar
wxMenu *menuFile = new wxMenu(wxEmptyString, wxMENU_TEAROFF);
// the "About" item should be in the help menu
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(MMBoard_About, wxT("&About...\tCtrl-A"), wxT("Show about dialog"));
menuFile->Append(MMBoard_Open, wxT("&Open\tAlt-O"), wxT("Open file"));
menuFile->AppendSeparator();
menuFile->Append(MMBoard_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
// now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar();
menuBar->Append(menuFile, wxT("&File"));
menuBar->Append(helpMenu, wxT("&Help"));
// ... and attach this menu bar to the frame
SetMenuBar(menuBar);
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(3);
SetStatusText(wxT("Welcome to wxWidgets!"));
#endif // wxUSE_STATUSBAR
// Misc variables
m_opened_file = NULL;
m_panel = new wxPanel(this, wxID_ANY);
// Initialize main slider
m_positionSlider = new wxSlider( m_panel, MMBoard_PositionSlider, 0, 0, 60,
wxDefaultPosition, wxSize(300, wxDefaultSize.y),
wxSL_HORIZONTAL | wxSL_AUTOTICKS);
m_positionSlider->SetPageSize(60); // 60 secs
m_positionSlider->Disable();
// Initialize info panel
wxPanel *infoPanel = new wxPanel( m_panel, wxID_ANY);
infoPanel->SetBackgroundColour(*wxBLACK);
infoPanel->SetForegroundColour(*wxWHITE);
wxBoxSizer *infoSizer = new wxBoxSizer(wxVERTICAL);
m_fileType = new wxStaticText(infoPanel, wxID_ANY, wxEmptyString);
wxStaticLine *line = new wxStaticLine(infoPanel, wxID_ANY);
m_infoText = new wxStaticText(infoPanel, wxID_ANY, wxEmptyString);
UpdateInfoText();
infoSizer->Add(m_fileType, 0, wxGROW | wxALL, 1);
infoSizer->Add(line, 0, wxGROW | wxCENTRE, 20);
infoSizer->Add(m_infoText, 0, wxGROW | wxALL, 1);
infoPanel->SetSizer(infoSizer);
// Bitmap button panel
wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
wxBitmap play_bmp(play_back_xpm);
wxBitmap stop_bmp(stop_back_xpm);
wxBitmap eject_bmp(eject_xpm);
wxBitmap pause_bmp(pause_xpm);
m_playButton = new wxBitmapButton(m_panel, MMBoard_PlayButton, play_bmp);
m_playButton->Disable();
m_pauseButton = new wxBitmapButton(m_panel, MMBoard_PauseButton, pause_bmp);
m_pauseButton->Disable();
m_stopButton = new wxBitmapButton(m_panel, MMBoard_StopButton, stop_bmp);
m_stopButton->Disable();
m_ejectButton = new wxBitmapButton(m_panel, MMBoard_EjectButton, eject_bmp);
m_ejectButton->Disable();
buttonSizer->Add(m_playButton, 0, wxALL, 2);
buttonSizer->Add(m_pauseButton, 0, wxALL, 2);
buttonSizer->Add(m_stopButton, 0, wxALL, 2);
buttonSizer->Add(m_ejectButton, 0, wxALL, 2);
// Top sizer
m_sizer = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0);
m_sizer->Add(m_positionSlider, 0, wxCENTRE | wxGROW | wxALL, 2);
m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0);
m_sizer->Add(buttonSizer, 0, wxALL, 0);
m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0);
m_sizer->Add(infoPanel, 1, wxCENTRE | wxGROW, 0);
m_panel->SetSizer(m_sizer);
m_sizer->Fit(this);
m_sizer->SetSizeHints(this);
// Timer
m_refreshTimer = new wxTimer(this, MMBoard_RefreshInfo);
// Video window
m_video_window = NULL;
// Multimedia file
m_opened_file = NULL;
}
MMBoardFrame::~MMBoardFrame()
{
if (m_opened_file)
delete m_opened_file;
delete m_refreshTimer;
}
void MMBoardFrame::OpenVideoWindow()
{
if (m_video_window)
return;
m_video_window = new wxWindow(m_panel, wxID_ANY, wxDefaultPosition, wxSize(200, 200));
m_video_window->SetBackgroundColour(*wxBLACK);
m_sizer->Prepend(m_video_window, 2, wxGROW | wxSHRINK | wxCENTRE, 1);
m_sizer->Fit(this);
}
void MMBoardFrame::CloseVideoWindow()
{
if (!m_video_window)
return;
Deprecated wxSizer::Remove( wxWindow* ), s/Remove/Detach/ in most places. Made wxSizer child list typesafe. I've not added the wxList implicit conversion kludge yet, let's see who complains first perhaps.. Deprecated wxSizer::{G,S}etOption in favour of {G,S}etProportion in line with the parameter name change in the docs. Added {G,S}etSpacer consistent with the accessors for windows/sizers. Made all wxSizer index parameters size_t -- we support no sensible interpretation for negative indexes in them. Hopefully this will cause no real problems, but code doing (eg. Remove( 0 )) will need to change to use 0u to resolve the ambiguity with overloaded members. This is probably a Good Thing though, ymmv. s/FALSE/false/g ; s/TRUE/true/g ; s/wxASSERT/wxASSERT_MSG/g in sizer.{cpp,h} Fixed (I hope) the brokenness in wxSizer::Show -- I have no code to test this yet, so it's a blind change, but spacers should now be hidden correctly instead of ignored, and it should be properly reversable over multiple calls now too. removed pointless private scoping around DECLARE_CLASS macros. Replace 0's I added previously with NULL -- not like that will end the email thread either.. Added Add( wxSizerItem * ) & co. There are probably a couple of other places we can usefully do something like this too. Stopped short of refactoring everything to raise some issues about sizer method recursion on -dev. Updated wxSizer docs some more, they are still incomplete but getting better. wrapped KeyCode in wxDEPRECATED, converted all (gtk build) instances to GetKeyCode. There may be a few left for other ports. Fixed a couple of other random compile warnings along the way. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18616 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2003-01-07 05:22:07 -05:00
m_sizer->Detach( m_video_window );
delete m_video_window;
m_video_window = NULL;
Deprecated wxSizer::Remove( wxWindow* ), s/Remove/Detach/ in most places. Made wxSizer child list typesafe. I've not added the wxList implicit conversion kludge yet, let's see who complains first perhaps.. Deprecated wxSizer::{G,S}etOption in favour of {G,S}etProportion in line with the parameter name change in the docs. Added {G,S}etSpacer consistent with the accessors for windows/sizers. Made all wxSizer index parameters size_t -- we support no sensible interpretation for negative indexes in them. Hopefully this will cause no real problems, but code doing (eg. Remove( 0 )) will need to change to use 0u to resolve the ambiguity with overloaded members. This is probably a Good Thing though, ymmv. s/FALSE/false/g ; s/TRUE/true/g ; s/wxASSERT/wxASSERT_MSG/g in sizer.{cpp,h} Fixed (I hope) the brokenness in wxSizer::Show -- I have no code to test this yet, so it's a blind change, but spacers should now be hidden correctly instead of ignored, and it should be properly reversable over multiple calls now too. removed pointless private scoping around DECLARE_CLASS macros. Replace 0's I added previously with NULL -- not like that will end the email thread either.. Added Add( wxSizerItem * ) & co. There are probably a couple of other places we can usefully do something like this too. Stopped short of refactoring everything to raise some issues about sizer method recursion on -dev. Updated wxSizer docs some more, they are still incomplete but getting better. wrapped KeyCode in wxDEPRECATED, converted all (gtk build) instances to GetKeyCode. There may be a few left for other ports. Fixed a couple of other random compile warnings along the way. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18616 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2003-01-07 05:22:07 -05:00
m_sizer->Fit(this);
}
// event handlers
void MMBoardFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MMBoardFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxString msg;
msg.Printf( wxT("wxWidgets Multimedia board v1.0a, wxMMedia v2.0a:\n")
wxT("an example of the capabilities of the wxWidgets multimedia classes.\n")
wxT("Copyright 1999, 2000, Guilhem Lavaux.\n"));
wxMessageBox(msg, _T("About MMBoard"), wxOK | wxICON_INFORMATION, this);
}
void MMBoardFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
{
wxString selected_file;
if (m_opened_file) {
if (!m_opened_file->IsStopped()) {
wxCommandEvent event2;
OnStop(event2);
}
delete m_opened_file;
}
// select a file to be opened
selected_file = wxLoadFileSelector(_T("multimedia"), _T("*"), NULL, this);
if (selected_file.IsNull())
return;
m_opened_file = MMBoardManager::Open(selected_file);
// Change the range values of the slider.
MMBoardTime length;
length = m_opened_file->GetLength();
m_positionSlider->SetRange(0, length.hours * 3600 + length.minutes * 60 + length.seconds);
// Update misc info
UpdateMMedInfo();
#if wxUSE_STATUSBAR
SetStatusText(selected_file, 2);
#endif // wxUSE_STATUSBAR
// Update info text
UpdateInfoText();
// Enable a few buttons
m_playButton->Enable();
m_ejectButton->Enable();
m_positionSlider->Enable();
if (m_opened_file->NeedWindow()) {
OpenVideoWindow();
m_opened_file->SetWindow(m_video_window);
} else
CloseVideoWindow();
}
void MMBoardFrame::UpdateInfoText()
{
wxString infotext1, infotext2;
if (m_opened_file) {
infotext1 = wxT("File type:\n\t");
infotext1 += m_opened_file->GetStringType() + wxT("\n");
infotext2 = wxT("File informations:\n\n");
infotext2 += m_opened_file->GetStringInformation();
} else {
infotext1 = wxT("File type: \n\tNo file opened");
infotext2 = wxT("File informations:\nNo information\n\n\n\n\n");
}
m_fileType->SetLabel(infotext1);
m_infoText->SetLabel(infotext2);
}
void MMBoardFrame::UpdateMMedInfo()
{
MMBoardTime current, length;
if (m_opened_file) {
current = m_opened_file->GetPosition();
length = m_opened_file->GetLength();
} else {
current.hours = current.minutes = current.seconds = 0;
length = current;
}
#if wxUSE_STATUSBAR
// We refresh the status bar
wxString temp_string;
temp_string.Printf(wxT("%02d:%02d / %02d:%02d"), current.hours * 60 + current.minutes,
current.seconds, length.hours * 60 + length.minutes, length.seconds);
SetStatusText(temp_string, 1);
#else
wxUnusedVar(length);
#endif // wxUSE_STATUSBAR
// We set the slider position
m_positionSlider->SetValue(current.hours * 3600 + current.minutes * 60 + current.seconds);
}
// ----------------------------------------------------------------------------
// Playing management, refreshers, ...
void MMBoardFrame::OnRefreshInfo(wxEvent& WXUNUSED(event))
{
UpdateMMedInfo();
if (m_opened_file->IsStopped())
{
m_refreshTimer->Stop();
m_playButton->Enable();
m_stopButton->Disable();
m_pauseButton->Disable();
}
}
void MMBoardFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
{
m_stopButton->Enable();
m_pauseButton->Enable();
m_playButton->Disable();
if (m_opened_file->IsPaused())
{
m_opened_file->Resume();
return;
}
m_refreshTimer->Start(1000, false);
m_opened_file->Play();
m_stopButton->Enable();
m_pauseButton->Enable();
m_playButton->Disable();
}
void MMBoardFrame::OnStop(wxCommandEvent& WXUNUSED(event))
{
m_opened_file->Stop();
m_refreshTimer->Stop();
m_stopButton->Disable();
m_playButton->Enable();
UpdateMMedInfo();
}
void MMBoardFrame::OnPause(wxCommandEvent& WXUNUSED(event))
{
m_opened_file->Pause();
m_playButton->Enable();
m_pauseButton->Disable();
}
void MMBoardFrame::OnEject(wxCommandEvent& WXUNUSED(event))
{
m_opened_file->Stop();
delete m_opened_file;
m_opened_file = NULL;
m_playButton->Disable();
m_pauseButton->Disable();
m_stopButton->Disable();
m_ejectButton->Disable();
m_positionSlider->Disable();
UpdateInfoText();
UpdateMMedInfo();
}
void MMBoardFrame::OnSetPosition(wxCommandEvent& WXUNUSED(event))
{
wxUint32 itime;
MMBoardTime btime;
itime = m_positionSlider->GetValue();
btime.seconds = itime % 60;
btime.minutes = (itime / 60) % 60;
btime.hours = itime / 3600;
m_opened_file->SetPosition(btime);
UpdateMMedInfo();
}