312 lines
12 KiB
Lua
312 lines
12 KiB
Lua
-----------------------------------------------------------------------------
|
|
-- Name: media.wx.lua
|
|
-- Purpose: wxMediaCtrl wxLua sample
|
|
-- Author: John Labenski
|
|
-- Modified by:
|
|
-- Created: 07/01/2007
|
|
-- RCS-ID:
|
|
-- Copyright: (c) 2007 John Labenski. All rights reserved.
|
|
-- Licence: wxWidgets licence
|
|
-----------------------------------------------------------------------------
|
|
|
|
-- Load the wxLua module, does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit
|
|
package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
|
|
require("wx")
|
|
|
|
frame = nil -- main wxFrame
|
|
mediaCtrl = nil -- wxMediaCtrl player
|
|
playButton = nil -- wxButton to "play"
|
|
pauseButton = nil -- wxButton to "pause"
|
|
stopButton = nil -- wxButton to "stop"
|
|
timer = nil -- wxTimer to update position in media
|
|
|
|
loadedMedia = false -- set to true if media is ok
|
|
fileName = "" -- Name of the loaded file
|
|
|
|
settingPos = false -- true when pos slider is being changed by user
|
|
|
|
slider_range = 10000 -- all sliders have this range
|
|
|
|
ID_LOADFILE = 1000
|
|
ID_PLAY = 1001
|
|
ID_PAUSE = 1002
|
|
ID_STOP = 1003
|
|
ID_VOLUME = 1004
|
|
ID_POSITON = 1005
|
|
ID_POSTEXT = 1006
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Convert milliseconds to MM:SS
|
|
-- ---------------------------------------------------------------------------
|
|
function msToMMSS(ms)
|
|
local m = math.floor(ms/(60*1000))
|
|
local s = math.floor((ms - m*60*1000)/1000)
|
|
return string.format("%02d:%02d", m, s)
|
|
end
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Update the GUI controls based on the mediaCtrl
|
|
-- ---------------------------------------------------------------------------
|
|
function UpdateButtons()
|
|
local play_ok = false
|
|
local pause_ok = false
|
|
local stop_ok = false
|
|
|
|
local state = mediaCtrl:GetState()
|
|
|
|
if not loadedMedia then state = -1 end -- not valid to do anything
|
|
|
|
if state == wx.wxMEDIASTATE_PLAYING then
|
|
play_ok = false
|
|
pause_ok = true
|
|
stop_ok = true
|
|
elseif state == wx.wxMEDIASTATE_PAUSED then
|
|
play_ok = true
|
|
pause_ok = false
|
|
stop_ok = true
|
|
else --if state == wx.wxMEDIASTATE_STOPPED then
|
|
play_ok = true
|
|
pause_ok = false
|
|
stop_ok = false
|
|
end
|
|
|
|
playButton:Enable(play_ok)
|
|
pauseButton:Enable(pause_ok)
|
|
stopButton:Enable(stop_ok)
|
|
|
|
volumeSlider:SetValue(mediaCtrl:GetVolume()*slider_range)
|
|
end
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Entry point into the program
|
|
-- ---------------------------------------------------------------------------
|
|
function main()
|
|
|
|
-- create the wxFrame window
|
|
frame = wx.wxFrame( wx.NULL, -- no parent for toplevel windows
|
|
wx.wxID_ANY, -- don't need a wxWindow ID
|
|
"wxLua Media Demo", -- caption on the frame
|
|
wx.wxDefaultPosition, -- let system place the frame
|
|
wx.wxSize(450, 450), -- set the size of the frame
|
|
wx.wxDEFAULT_FRAME_STYLE ) -- use default frame styles
|
|
|
|
frame:Connect(wx.wxEVT_CLOSE_WINDOW,
|
|
function (event)
|
|
event:Skip()
|
|
if timer then
|
|
timer:Stop() -- always stop before exiting or deleting it
|
|
timer:delete()
|
|
timer = nil
|
|
end
|
|
end)
|
|
|
|
-- -----------------------------------------------------------------------
|
|
|
|
-- create a simple file menu
|
|
local fileMenu = wx.wxMenu()
|
|
fileMenu:Append(ID_LOADFILE, "Load media...\tCtrl+O", "Load a file to play...")
|
|
fileMenu:AppendSeparator()
|
|
fileMenu:Append(wx.wxID_EXIT, "E&xit\tCtrl+Q", "Quit the program")
|
|
|
|
-- create a simple help menu
|
|
local helpMenu = wx.wxMenu()
|
|
helpMenu:Append(wx.wxID_ABOUT, "&About", "About the wxLua Media Application")
|
|
|
|
-- create a menu bar and append the file and help menus
|
|
local menuBar = wx.wxMenuBar()
|
|
menuBar:Append(fileMenu, "&File")
|
|
menuBar:Append(helpMenu, "&Help")
|
|
|
|
-- attach the menu bar into the frame
|
|
frame:SetMenuBar(menuBar)
|
|
|
|
-- create a simple status bar
|
|
frame:CreateStatusBar(1)
|
|
frame:SetStatusText("Welcome to wxLua.")
|
|
|
|
-- -----------------------------------------------------------------------
|
|
|
|
panel = wx.wxPanel(frame, wx.wxID_ANY)
|
|
|
|
mediaCtrl = wx.wxMediaCtrl(panel, wx.wxID_ANY, "",
|
|
wx.wxDefaultPosition, wx.wxSize(200, 200))
|
|
|
|
playButton = wx.wxButton(panel, ID_PLAY, "Play")
|
|
pauseButton = wx.wxButton(panel, ID_PAUSE, "Pause")
|
|
stopButton = wx.wxButton(panel, ID_STOP, "Stop")
|
|
volumeSlider = wx.wxSlider(panel, ID_VOLUME, slider_range, 0, slider_range)
|
|
|
|
buttonSizer = wx.wxFlexGridSizer(1, 5, 5, 5)
|
|
buttonSizer:AddGrowableCol(4)
|
|
buttonSizer:Add(playButton, 0, 0)
|
|
buttonSizer:Add(pauseButton, 0, 0)
|
|
buttonSizer:Add(stopButton, 0, 0)
|
|
buttonSizer:Add(wx.wxStaticText(panel, wx.wxID_ANY, "Volume : "), 0, wx.wxALIGN_CENTER_VERTICAL)
|
|
buttonSizer:Add(volumeSlider, 1, wx.wxEXPAND)
|
|
|
|
posSlider = wx.wxSlider(panel, ID_POSITON, 0, 0, slider_range)
|
|
posText = wx.wxStaticText(panel, ID_POSTEXT, "Position 00:00/00:00 ")
|
|
posSizer = wx.wxFlexGridSizer(1, 5, 5, 5)
|
|
posSizer:AddGrowableCol(1)
|
|
posSizer:Add(posText, 0, wx.wxALIGN_CENTER_VERTICAL)
|
|
posSizer:Add(posSlider, 1, wx.wxEXPAND)
|
|
|
|
mainSizer = wx.wxFlexGridSizer(2, 1, 5, 5)
|
|
mainSizer:AddGrowableRow(0)
|
|
mainSizer:AddGrowableCol(0)
|
|
mainSizer:Add(mediaCtrl, 1, wx.wxEXPAND, 0)
|
|
mainSizer:Add(buttonSizer, 0, wx.wxEXPAND, 0)
|
|
mainSizer:Add(posSizer, 0, wx.wxEXPAND, 0)
|
|
|
|
panel:SetSizer(mainSizer)
|
|
mainSizer:SetSizeHints(frame)
|
|
|
|
UpdateButtons()
|
|
|
|
-- -----------------------------------------------------------------------
|
|
|
|
panel:Connect(ID_PLAY, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
|
function (event)
|
|
local ok = mediaCtrl:Play()
|
|
|
|
if not ok then
|
|
wx.wxMessageBox(string.format("Unable to play %s: Unsupported format?", fileName),
|
|
"wxLua Media Demo",
|
|
wx.wxICON_ERROR + wx.wxOK)
|
|
end
|
|
end )
|
|
panel:Connect(ID_PAUSE, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
|
function (event)
|
|
local ok = mediaCtrl:Pause()
|
|
|
|
if not ok then
|
|
wx.wxMessageBox(string.format("Unable to pause %s: Unsupported format?", fileName),
|
|
"wxLua Media Demo",
|
|
wx.wxICON_ERROR + wx.wxOK)
|
|
end
|
|
end )
|
|
panel:Connect(ID_STOP, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
|
function (event)
|
|
local ok = mediaCtrl:Stop()
|
|
|
|
if not ok then
|
|
wx.wxMessageBox(string.format("Unable to stop %s: Unsupported format?", fileName),
|
|
"wxLua Media Demo",
|
|
wx.wxICON_ERROR + wx.wxOK)
|
|
end
|
|
end )
|
|
|
|
panel:Connect(ID_VOLUME, wx.wxEVT_SCROLL_THUMBRELEASE,
|
|
function (event)
|
|
local pos = event:GetPosition()
|
|
mediaCtrl:SetVolume(pos/slider_range)
|
|
end )
|
|
|
|
panel:Connect(ID_POSITON, wx.wxEVT_SCROLL_THUMBTRACK,
|
|
function (event) settingPos = true end)
|
|
|
|
panel:Connect(ID_POSITON, wx.wxEVT_SCROLL_THUMBRELEASE,
|
|
function (event)
|
|
if loadedMedia then
|
|
local pos = event:GetPosition()
|
|
local len = mediaCtrl:Length()
|
|
local ok = mediaCtrl:Seek(len*pos/slider_range)
|
|
if ok == wx.wxInvalidOffset then
|
|
wx.wxMessageBox(string.format("Unable to seek in %s: Unsupported format?", fileName),
|
|
"wxLua Media Demo",
|
|
wx.wxICON_ERROR + wx.wxOK)
|
|
end
|
|
end
|
|
|
|
settingPos = false
|
|
end )
|
|
|
|
mediaCtrl:Connect(wx.wxEVT_MEDIA_STATECHANGED,
|
|
function (event)
|
|
UpdateButtons()
|
|
end)
|
|
|
|
-- -----------------------------------------------------------------------
|
|
|
|
timer = wx.wxTimer(panel)
|
|
panel:Connect(wx.wxEVT_TIMER,
|
|
function (event)
|
|
local len = 1 -- avoid /0
|
|
local pos = 0
|
|
local str = "Position 00:00/00:00"
|
|
|
|
if loadedMedia then
|
|
len = mediaCtrl:Length()
|
|
pos = mediaCtrl:Tell()
|
|
str = string.format("Position %s/%s", msToMMSS(pos), msToMMSS(len))
|
|
end
|
|
|
|
if not settingPos then
|
|
posSlider:SetValue(slider_range*pos/len)
|
|
end
|
|
|
|
if posText:GetLabel() ~= str then
|
|
posText:SetLabel(str)
|
|
end
|
|
end)
|
|
|
|
timer:Start(300)
|
|
|
|
-- -----------------------------------------------------------------------
|
|
|
|
frame:Connect(ID_LOADFILE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
local dlg = wx.wxFileDialog(frame, "Choose a media file",
|
|
wx.wxGetCwd(), "", "All Files (*)|*|MP3 Music Files (*.mp3)|*.mp3|MPG Video Files (*.mpg)|*.mpg|AVI Movie Files (*.avi)|*.avi",
|
|
wx.wxFD_OPEN + wx.wxFD_FILE_MUST_EXIST + wx.wxFD_CHANGE_DIR )
|
|
if dlg:ShowModal() == wx.wxID_OK then
|
|
local filepath = dlg:GetPath()
|
|
loadedMedia = false
|
|
fileName = ""
|
|
|
|
if not mediaCtrl:Load(filepath) then
|
|
wx.wxMessageBox(string.format("Unable to load %s: Unsupported format?", filepath),
|
|
"wxLua Media Demo",
|
|
wx.wxICON_ERROR + wx.wxOK)
|
|
else
|
|
posSlider:SetValue(0)
|
|
loadedMedia = true
|
|
fileName = dlg:GetFilename()
|
|
local ms = mediaCtrl:Length()
|
|
local s = mediaCtrl:GetBestSize()
|
|
frame:SetStatusText(string.format("Loaded: '%s' Length %s Size %dx%d", fileName, msToMMSS(ms), s:GetWidth(), s:GetHeight()))
|
|
mediaCtrl:SetInitialSize()
|
|
panel:GetSizer():Layout()
|
|
end
|
|
end
|
|
dlg:Destroy()
|
|
UpdateButtons()
|
|
end )
|
|
|
|
-- connect the selection event of the exit menu item to an
|
|
-- event handler that closes the window
|
|
frame:Connect(wx.wxID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event) frame:Close(true) end )
|
|
|
|
-- connect the selection event of the about menu item
|
|
frame:Connect(wx.wxID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
|
function (event)
|
|
wx.wxMessageBox('This is the "About" dialog of the Media wxLua sample.\n'..
|
|
wxlua.wxLUA_VERSION_STRING.." built with "..wx.wxVERSION_STRING,
|
|
"About wxLua Media",
|
|
wx.wxOK + wx.wxICON_INFORMATION,
|
|
frame)
|
|
end )
|
|
|
|
-- show the frame window
|
|
frame:Show(true)
|
|
end
|
|
|
|
main()
|
|
|
|
-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
|
|
-- otherwise the wxLua program will exit immediately.
|
|
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
|
|
-- MainLoop is already running or will be started by the C++ program.
|
|
wx.wxGetApp():MainLoop()
|