Code:
# Zeus Video Player 1.2 for RMXP and RMVX
# How to Use :
# Graphics.play_movie(path, cancelable, fit)
# path = path of the avi file
# cancelable = true if we want to allow to stop the video before its end, or false
# fit = true if we want the video to be stretched to fit when not in 640x480, false if we want it to be centered.
# ex : Graphics.play_movie("Movies/prout.avi", true, true)
module Graphics
findWindow = Win32API.new('user32', 'FindWindow', 'pp', 'i')
GetClientRect = Win32API.new('user32', 'GetClientRect', 'ip', 'i')
GetMessage = Win32API.new('user32', 'GetMessage', 'piii', 'i')
TranslateMessage = Win32API.new('user32', 'TranslateMessage', 'p', 'i')
DispatchMessage = Win32API.new('user32', 'DispatchMessage', 'p', 'i')
SendInput = Win32API.new('user32', 'SendInput', 'ipi', 'i')
MultiByteToWideChar = Win32API.new('kernel32', 'MultiByteToWideChar', 'iipipi', 'i')
WideCharToMultiByte = Win32API.new('kernel32', 'WideCharToMultiByte', 'iipipipp', 'i')
GetShortPathName = Win32API.new('kernel32', 'GetShortPathName', 'ppi', 'i')
MciSendString = Win32API.new('winmm', 'mciSendString', 'ppii', 'i')
HWnd = findWindow.call('RGSS Player', 0)
class << self
def play_movie(filename, cancelable = true, fit = true)
MultiByteToWideChar.call(65001, 0, filename, -1, utf16="\0"*520, 260) # utf8 => utf16
WideCharToMultiByte.call(0, 0, utf16, -1, ansi="\0"*260, 260, 0, 0) # utf16 => ansi
l = GetShortPathName.call(ansi, spath="\0"*260, 260)
unless FileTest.exist?(spath = spath[0,l])
raise(error=Errno::ENOENT.new(filename), error.message, caller)
end
MciSendString.call("open \"#{spath}\" alias VIDEO type AVIVideo style Child parent #{HWnd}", 0, 0, 0)
MciSendString.call('where VIDEO source', buffer=' '*28, 28, 0)
src_rect = buffer.split(' ').map! {|s| s.to_i}
return if src_rect.size != 4 # video format not supported
background = Sprite.new
background.bitmap = Bitmap.new(1, 1)
background.bitmap.set_pixel(0, 0, Color.new(0,0,0))
background.zoom_x = background.zoom_y = background.z = 9999
Graphics.update
MciSendString.call('put VIDEO window at 0 0 1 1', 0, 0, 0) # trick for fullscreen
MciSendString.call('play VIDEO', 0, 0, 0)
update_video_rect(fit, src_rect)
do_exit =
if defined? Hangup # RMXP
begin
wait_video_end(cancelable, fit, src_rect)
rescue Hangup
retry
end
else # RMVX
wait_video_end(cancelable, fit, src_rect)
end
Input.update
MciSendString.call('stop VIDEO', 0, 0, 0)
MciSendString.call('close VIDEO', 0, 0, 0)
background.bitmap.dispose
background.dispose
exit if do_exit
end
private
def wait_video_end(cancelable, fit, src_rect)
buffer = "\0"*28
loop do
GetMessage.call(buffer, HWnd, 0, 0)
TranslateMessage.call(buffer)
DispatchMessage.call(buffer)
case buffer.unpack('@4L').first
when 0x0012 #WM_QUIT
break true
when 0x0104 #WM_SYSKEYDOWN
if buffer.unpack('@8L').first == 0x0D #VK_RETURN
SendInput.call(1, [1,0x0D,0,0,0,0].pack('LSSLLLx8'), 28)
Graphics.update
Input.update
update_video_rect(fit, src_rect)
end
end
Input.update
break false if cancelable and Input.trigger?(Input::C)
MciSendString.call('status VIDEO mode', buffer, 28, 0)
break false if buffer !~ /^playing/
end
end
def update_video_rect(fit, src_rect)
GetClientRect.call(HWnd, buffer="\0"*16)
wnd_w, wnd_h = *buffer.unpack('@8LL')
x, y, w, h = *src_rect
if fit or w > wnd_w or h > wnd_h
ratio = w / h.to_f
w, h = wnd_w, (wnd_w / ratio).round
h, w = wnd_h, (wnd_h * ratio).round if h > wnd_h
end
x, y = (wnd_w-w)/2, (wnd_h-h)/2
MciSendString.call("put VIDEO window at #{x} #{y} #{w} #{h}", 0, 0, 0)
end
end
end