1///////////////////////////////////////////////////////////////////////////// 2// Name: mmboard.cpp 3// Purpose: Multimedia Library sample 4// Author: Guilhem Lavaux (created from minimal by J. Smart) 5// Modified by: 6// Created: 13/02/2000 7// RCS-ID: $Id: mmboard.cpp 43163 2006-11-07 15:32:27Z VZ $ 8// Copyright: (c) Guilhem Lavaux 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20// For compilers that support precompilation, includes "wx/wx.h". 21#include "wx/wxprec.h" 22 23#ifdef __BORLANDC__ 24 #pragma hdrstop 25#endif 26 27// for all others, include the necessary headers (this file is usually all you 28// need because it includes almost all "standard" wxWidgets headers 29#ifndef WX_PRECOMP 30 #include "wx/wx.h" 31#endif 32 33// ---------------------------------------------------------------------------- 34// ressources 35// ---------------------------------------------------------------------------- 36 37// the application icon 38#if !defined(__WXMSW__) && !defined(__WXPM__) 39 #include "mondrian.xpm" 40#endif 41 42// include multimedia classes 43#include "wx/mmedia/sndbase.h" 44#ifdef __WIN32__ 45 #include "wx/mmedia/sndwin.h" 46#endif 47#ifdef __UNIX__ 48 #include "wx/mmedia/sndoss.h" 49 #include "wx/mmedia/sndesd.h" 50#endif 51 52#include "wx/statline.h" 53#include "wx/stattext.h" 54 55// include personnal classes 56#include "mmboard.h" 57#include "mmbman.h" 58 59#include "play.xpm" 60#include "stop.xpm" 61#include "eject.xpm" 62#include "pause.xpm" 63 64// ---------------------------------------------------------------------------- 65// private classes 66// ---------------------------------------------------------------------------- 67 68// Main Multimedia Board frame 69class MMBoardFrame : public wxFrame 70{ 71public: 72 // ctor(s) 73 MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size); 74 // dtor 75 ~MMBoardFrame(); 76 77 // event handlers 78 void OnQuit(wxCommandEvent& event); 79 void OnAbout(wxCommandEvent& event); 80 void OnOpen(wxCommandEvent& event); 81 void OnPlay(wxCommandEvent& event); 82 void OnStop(wxCommandEvent& event); 83 void OnPause(wxCommandEvent& event); 84 void OnEject(wxCommandEvent& event); 85 void OnRefreshInfo(wxEvent& event); 86 void OnSetPosition(wxCommandEvent& event); 87 88 void OpenVideoWindow(); 89 void CloseVideoWindow(); 90 91private: 92 // any class wishing to process wxWidgets events must use this macro 93 DECLARE_EVENT_TABLE() 94 95private: 96 void UpdateMMedInfo(); 97 void UpdateInfoText(); 98 99 MMBoardFile *m_opened_file; 100 101 wxSlider *m_positionSlider; 102 wxBitmapButton *m_playButton, *m_pauseButton, *m_stopButton, *m_ejectButton; 103 wxStaticText *m_fileType, *m_infoText; 104 wxWindow *m_video_window; 105 106 wxPanel *m_panel; 107 wxSizer *m_sizer; 108 109 wxTimer *m_refreshTimer; 110}; 111 112// ---------------------------------------------------------------------------- 113// constants 114// ---------------------------------------------------------------------------- 115 116// IDs for the controls and the menu commands 117enum 118{ 119 // menu items 120 MMBoard_Quit = 1, 121 MMBoard_Open, 122 MMBoard_About, 123 MMBoard_PositionSlider, 124 MMBoard_PlayButton, 125 MMBoard_PauseButton, 126 MMBoard_ResumeButton, 127 MMBoard_StopButton, 128 MMBoard_EjectButton, 129 MMBoard_RefreshInfo 130}; 131 132// ---------------------------------------------------------------------------- 133// event tables and other macros for wxWidgets 134// ---------------------------------------------------------------------------- 135 136BEGIN_EVENT_TABLE(MMBoardFrame, wxFrame) 137 EVT_MENU(MMBoard_Quit, MMBoardFrame::OnQuit) 138 EVT_MENU(MMBoard_About, MMBoardFrame::OnAbout) 139 EVT_MENU(MMBoard_Open, MMBoardFrame::OnOpen) 140 EVT_BUTTON(MMBoard_PlayButton, MMBoardFrame::OnPlay) 141 EVT_BUTTON(MMBoard_StopButton, MMBoardFrame::OnStop) 142 EVT_BUTTON(MMBoard_PauseButton, MMBoardFrame::OnPause) 143 EVT_BUTTON(MMBoard_EjectButton, MMBoardFrame::OnEject) 144 EVT_SLIDER(MMBoard_PositionSlider, MMBoardFrame::OnSetPosition) 145 EVT_CUSTOM(wxEVT_TIMER, MMBoard_RefreshInfo, MMBoardFrame::OnRefreshInfo) 146END_EVENT_TABLE() 147 148// --------------------------------------------------------------------------- 149// Main board application launcher 150// --------------------------------------------------------------------------- 151 152IMPLEMENT_APP(MMBoardApp) 153 154// ============================================================================ 155// implementation 156// ============================================================================ 157 158// ---------------------------------------------------------------------------- 159// the application class 160// ---------------------------------------------------------------------------- 161 162bool MMBoardApp::OnInit() 163{ 164 // create the main application window 165 MMBoardFrame *frame = new MMBoardFrame(_T("Multimedia Board"), 166 wxPoint(50, 50), wxSize(450, 340)); 167 168 // and show it (the frames, unlike simple controls, are not shown when 169 // created initially) 170 frame->Show(); 171 172 m_caps = TestMultimediaCaps(); 173 174 if (!m_caps) { 175 wxMessageBox(_T("Your system has no multimedia capabilities. We are exiting now."), _T("Major error !"), wxOK | wxICON_ERROR, NULL); 176 return false; 177 } 178 179 wxString msg; 180 msg.Printf(_T("Detected : %s%s%s"), (m_caps & MM_SOUND_OSS) ? _T("OSS ") : _T(""), 181 (m_caps & MM_SOUND_ESD) ? _T("ESD ") : _T(""), 182 (m_caps & MM_SOUND_WIN) ? _T("WIN") : _T("")); 183 184 wxMessageBox(msg, _T("Good !"), wxOK | wxICON_INFORMATION, NULL); 185 186 // success: wxApp::OnRun() will be called which will enter the main message 187 // loop and the application will run. If we returned false here, the 188 // application would exit immediately. 189 return true; 190} 191 192wxUint8 MMBoardApp::TestMultimediaCaps() 193{ 194 wxSoundStream *dev; 195 wxUint8 caps; 196 197 caps = 0; 198 199#ifdef __WIN32__ 200 // We test the Windows sound support. 201 202 dev = new wxSoundStreamWin(); 203 if (dev->GetError() == wxSOUND_NOERROR) 204 caps |= MM_SOUND_WIN; 205 delete dev; 206 207#elif defined __UNIX__ 208 // We now test the ESD support 209 210 dev = new wxSoundStreamESD(); 211 if (dev->GetError() == wxSOUND_NOERROR) 212 caps |= MM_SOUND_ESD; 213 delete dev; 214 215 // We test the OSS (Open Sound System) support. 216 // WARNING: There is a conflict between ESD and ALSA. We may be interrested 217 // in disabling the auto detection of OSS is ESD has been detected. 218#if 1 219 if (!(caps & MM_SOUND_ESD)) { 220#endif 221 222 dev = new wxSoundStreamOSS(); 223 if (dev->GetError() == wxSOUND_NOERROR) 224 caps |= MM_SOUND_OSS; 225 delete dev; 226#if 1 227 } 228#endif 229 230#endif 231 232 return caps; 233} 234 235// ---------------------------------------------------------------------------- 236// main frame 237// ---------------------------------------------------------------------------- 238 239// frame constructor 240MMBoardFrame::MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size) 241 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size) 242{ 243#ifdef __WXMAC__ 244 // we need this in order to allow the about menu relocation, since ABOUT is 245 // not the default id of the about menu 246 wxApp::s_macAboutMenuItemId = MMBoard_About; 247#endif 248 249 // set the frame icon 250 SetIcon(wxICON(mondrian)); 251 252 // create a menu bar 253 wxMenu *menuFile = new wxMenu(wxEmptyString, wxMENU_TEAROFF); 254 255 // the "About" item should be in the help menu 256 wxMenu *helpMenu = new wxMenu; 257 helpMenu->Append(MMBoard_About, wxT("&About...\tCtrl-A"), wxT("Show about dialog")); 258 259 menuFile->Append(MMBoard_Open, wxT("&Open\tAlt-O"), wxT("Open file")); 260 menuFile->AppendSeparator(); 261 menuFile->Append(MMBoard_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program")); 262 263 // now append the freshly created menu to the menu bar... 264 wxMenuBar *menuBar = new wxMenuBar(); 265 menuBar->Append(menuFile, wxT("&File")); 266 menuBar->Append(helpMenu, wxT("&Help")); 267 268 // ... and attach this menu bar to the frame 269 SetMenuBar(menuBar); 270 271#if wxUSE_STATUSBAR 272 // create a status bar just for fun (by default with 1 pane only) 273 CreateStatusBar(3); 274 SetStatusText(wxT("Welcome to wxWidgets!")); 275#endif // wxUSE_STATUSBAR 276 277 // Misc variables 278 m_opened_file = NULL; 279 280 m_panel = new wxPanel(this, wxID_ANY); 281 282 // Initialize main slider 283 m_positionSlider = new wxSlider( m_panel, MMBoard_PositionSlider, 0, 0, 60, 284 wxDefaultPosition, wxSize(300, wxDefaultCoord), 285 wxSL_HORIZONTAL | wxSL_AUTOTICKS); 286 m_positionSlider->SetPageSize(60); // 60 secs 287 m_positionSlider->Disable(); 288 289 // Initialize info panel 290 wxPanel *infoPanel = new wxPanel( m_panel, wxID_ANY); 291 infoPanel->SetBackgroundColour(*wxBLACK); 292 infoPanel->SetForegroundColour(*wxWHITE); 293 294 wxBoxSizer *infoSizer = new wxBoxSizer(wxVERTICAL); 295 296 m_fileType = new wxStaticText(infoPanel, wxID_ANY, wxEmptyString); 297#if wxUSE_STATLINE 298 wxStaticLine *line = new wxStaticLine(infoPanel, wxID_ANY); 299#endif // wxUSE_STATLINE 300 m_infoText = new wxStaticText(infoPanel, wxID_ANY, wxEmptyString); 301 302 UpdateInfoText(); 303 304 infoSizer->Add(m_fileType, 0, wxGROW | wxALL, 1); 305#if wxUSE_STATLINE 306 infoSizer->Add(line, 0, wxGROW | wxCENTRE, 20); 307#endif // wxUSE_STATLINE 308 infoSizer->Add(m_infoText, 0, wxGROW | wxALL, 1); 309 310 infoPanel->SetSizer(infoSizer); 311 312 // Bitmap button panel 313 wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); 314 315 wxBitmap play_bmp(play_back_xpm); 316 wxBitmap stop_bmp(stop_back_xpm); 317 wxBitmap eject_bmp(eject_xpm); 318 wxBitmap pause_bmp(pause_xpm); 319 320 m_playButton = new wxBitmapButton(m_panel, MMBoard_PlayButton, play_bmp); 321 m_playButton->Disable(); 322 m_pauseButton = new wxBitmapButton(m_panel, MMBoard_PauseButton, pause_bmp); 323 m_pauseButton->Disable(); 324 m_stopButton = new wxBitmapButton(m_panel, MMBoard_StopButton, stop_bmp); 325 m_stopButton->Disable(); 326 m_ejectButton = new wxBitmapButton(m_panel, MMBoard_EjectButton, eject_bmp); 327 m_ejectButton->Disable(); 328 329 buttonSizer->Add(m_playButton, 0, wxALL, 2); 330 buttonSizer->Add(m_pauseButton, 0, wxALL, 2); 331 buttonSizer->Add(m_stopButton, 0, wxALL, 2); 332 buttonSizer->Add(m_ejectButton, 0, wxALL, 2); 333 334 // Top sizer 335 m_sizer = new wxBoxSizer(wxVERTICAL); 336#if wxUSE_STATLINE 337 m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0); 338#endif // wxUSE_STATLINE 339 m_sizer->Add(m_positionSlider, 0, wxCENTRE | wxGROW | wxALL, 2); 340#if wxUSE_STATLINE 341 m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0); 342#endif // wxUSE_STATLINE 343 m_sizer->Add(buttonSizer, 0, wxALL, 0); 344#if wxUSE_STATLINE 345 m_sizer->Add(new wxStaticLine(m_panel, wxID_ANY), 0, wxGROW | wxCENTRE, 0); 346#endif // wxUSE_STATLINE 347 m_sizer->Add(infoPanel, 1, wxCENTRE | wxGROW, 0); 348 349 m_panel->SetSizer(m_sizer); 350 m_sizer->Fit(this); 351 m_sizer->SetSizeHints(this); 352 353 // Timer 354 m_refreshTimer = new wxTimer(this, MMBoard_RefreshInfo); 355 356 // Video window 357 m_video_window = NULL; 358 359 // Multimedia file 360 m_opened_file = NULL; 361} 362 363MMBoardFrame::~MMBoardFrame() 364{ 365 if (m_opened_file) 366 delete m_opened_file; 367 368 delete m_refreshTimer; 369} 370 371void MMBoardFrame::OpenVideoWindow() 372{ 373 if (m_video_window) 374 return; 375 376 m_video_window = new wxWindow(m_panel, wxID_ANY, wxDefaultPosition, wxSize(200, 200)); 377 m_video_window->SetBackgroundColour(*wxBLACK); 378 m_sizer->Prepend(m_video_window, 2, wxGROW | wxSHRINK | wxCENTRE, 1); 379 380 m_sizer->Fit(this); 381} 382 383void MMBoardFrame::CloseVideoWindow() 384{ 385 if (!m_video_window) 386 return; 387 388 m_sizer->Detach( m_video_window ); 389 delete m_video_window; 390 m_video_window = NULL; 391 392 m_sizer->Fit(this); 393} 394 395// event handlers 396 397void MMBoardFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) 398{ 399 // true is to force the frame to close 400 Close(true); 401} 402 403void MMBoardFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) 404{ 405 wxString msg; 406 msg.Printf( wxT("wxWidgets Multimedia board v1.0a, wxMMedia v2.0a:\n") 407 wxT("an example of the capabilities of the wxWidgets multimedia classes.\n") 408 wxT("Copyright 1999, 2000, Guilhem Lavaux.\n")); 409 410 wxMessageBox(msg, _T("About MMBoard"), wxOK | wxICON_INFORMATION, this); 411} 412 413void MMBoardFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) 414{ 415 wxString selected_file; 416 417 if (m_opened_file) { 418 if (!m_opened_file->IsStopped()) { 419 wxCommandEvent event2; 420 OnStop(event2); 421 } 422 delete m_opened_file; 423 } 424 425 // select a file to be opened 426#if wxUSE_FILEDLG 427 selected_file = wxLoadFileSelector(_T("multimedia"), _T("*"), NULL, this); 428#endif // wxUSE_FILEDLG 429 if (selected_file.empty()) 430 return; 431 432 m_opened_file = MMBoardManager::Open(selected_file); 433 434 // Change the range values of the slider. 435 MMBoardTime length; 436 437 length = m_opened_file->GetLength(); 438 m_positionSlider->SetRange(0, length.hours * 3600 + length.minutes * 60 + length.seconds); 439 440 // Update misc info 441 UpdateMMedInfo(); 442 443#if wxUSE_STATUSBAR 444 SetStatusText(selected_file, 2); 445#endif // wxUSE_STATUSBAR 446 447 // Update info text 448 UpdateInfoText(); 449 450 // Enable a few buttons 451 m_playButton->Enable(); 452 m_ejectButton->Enable(); 453 m_positionSlider->Enable(); 454 455 if (m_opened_file->NeedWindow()) { 456 OpenVideoWindow(); 457 m_opened_file->SetWindow(m_video_window); 458 } else 459 CloseVideoWindow(); 460} 461 462void MMBoardFrame::UpdateInfoText() 463{ 464 wxString infotext1, infotext2; 465 466 if (m_opened_file) { 467 infotext1 = wxT("File type:\n\t"); 468 infotext1 += m_opened_file->GetStringType() + wxT("\n"); 469 470 infotext2 = wxT("File informations:\n\n"); 471 infotext2 += m_opened_file->GetStringInformation(); 472 } else { 473 infotext1 = wxT("File type: \n\tNo file opened"); 474 infotext2 = wxT("File informations:\nNo information\n\n\n\n\n"); 475 } 476 477 m_fileType->SetLabel(infotext1); 478 m_infoText->SetLabel(infotext2); 479} 480 481void MMBoardFrame::UpdateMMedInfo() 482{ 483 MMBoardTime current, length; 484 485 if (m_opened_file) { 486 current = m_opened_file->GetPosition(); 487 length = m_opened_file->GetLength(); 488 } else { 489 current.hours = current.minutes = current.seconds = 0; 490 length = current; 491 } 492 493#if wxUSE_STATUSBAR 494 // We refresh the status bar 495 wxString temp_string; 496 temp_string.Printf(wxT("%02d:%02d / %02d:%02d"), current.hours * 60 + current.minutes, 497 current.seconds, length.hours * 60 + length.minutes, length.seconds); 498 SetStatusText(temp_string, 1); 499#else 500 wxUnusedVar(length); 501#endif // wxUSE_STATUSBAR 502 503 // We set the slider position 504 m_positionSlider->SetValue(current.hours * 3600 + current.minutes * 60 + current.seconds); 505} 506 507// ---------------------------------------------------------------------------- 508// Playing management, refreshers, ... 509 510void MMBoardFrame::OnRefreshInfo(wxEvent& WXUNUSED(event)) 511{ 512 UpdateMMedInfo(); 513 514 if (m_opened_file->IsStopped()) 515 { 516 m_refreshTimer->Stop(); 517 m_playButton->Enable(); 518 m_stopButton->Disable(); 519 m_pauseButton->Disable(); 520 } 521} 522 523void MMBoardFrame::OnPlay(wxCommandEvent& WXUNUSED(event)) 524{ 525 m_stopButton->Enable(); 526 m_pauseButton->Enable(); 527 m_playButton->Disable(); 528 529 if (m_opened_file->IsPaused()) 530 { 531 m_opened_file->Resume(); 532 return; 533 } 534 535 m_refreshTimer->Start(1000, false); 536 537 m_opened_file->Play(); 538 539 m_stopButton->Enable(); 540 m_pauseButton->Enable(); 541 m_playButton->Disable(); 542} 543 544void MMBoardFrame::OnStop(wxCommandEvent& WXUNUSED(event)) 545{ 546 m_opened_file->Stop(); 547 m_refreshTimer->Stop(); 548 549 m_stopButton->Disable(); 550 m_playButton->Enable(); 551 552 UpdateMMedInfo(); 553} 554 555void MMBoardFrame::OnPause(wxCommandEvent& WXUNUSED(event)) 556{ 557 m_opened_file->Pause(); 558 559 m_playButton->Enable(); 560 m_pauseButton->Disable(); 561} 562 563void MMBoardFrame::OnEject(wxCommandEvent& WXUNUSED(event)) 564{ 565 m_opened_file->Stop(); 566 567 delete m_opened_file; 568 m_opened_file = NULL; 569 570 m_playButton->Disable(); 571 m_pauseButton->Disable(); 572 m_stopButton->Disable(); 573 m_ejectButton->Disable(); 574 m_positionSlider->Disable(); 575 576 UpdateInfoText(); 577 UpdateMMedInfo(); 578} 579 580void MMBoardFrame::OnSetPosition(wxCommandEvent& WXUNUSED(event)) 581{ 582 wxUint32 itime; 583 MMBoardTime btime; 584 585 itime = m_positionSlider->GetValue(); 586 btime.seconds = itime % 60; 587 btime.minutes = (itime / 60) % 60; 588 btime.hours = itime / 3600; 589 m_opened_file->SetPosition(btime); 590 591 UpdateMMedInfo(); 592} 593