/* * * // Windowに直接描画するとき * // SetFilter(SMPEG.SMPEGfilter_bilinear()); * // とかすればスムーズに拡大・縮小されるのかと思いきや、そうでもない。 * // 微妙な違いはあるのだが、拡大とかする前の段階での処理のようで、 * // 見比べてみないと分からない程度。 * // よって、とりあえずデフォルトのままにしておく。 * * private void SetFilter(IntPtr filter) * { * IntPtr f = SMPEG.SMPEG_filter(mpeg, filter); * // 古いフィルタの後始末 * SMPEG.SMPEG_Filter fs = (SMPEG.SMPEG_Filter)Marshal.PtrToStructure(f, typeof(SMPEG.SMPEG_Filter)); * fs.destroy(f); * } * * //*/ /// <summary> /// play中のムービーを停止させる /// </summary> public void Stop() { lock (lockObject) { #if RELEASE_ON_STOP if (fileName != null) { // Release()で一端filenameはnullになるので、終わってから再設定する。(´ω`) string tmp = fileName; Release(); fileName = tmp; } #else Debug.Assert(Loaded); if (IsPlaying) { if (!paused) { InnerStop(); } paused = false; SMPEG.SMPEG_rewind(mpeg); // 巻き戻す } #endif } }
/// <summary> /// 再生開始 /// </summary> public YanesdkResult Play() { lock (lockObject) { #if RELEASE_ON_STOP if (IsPlaying) { if (!paused) { InnerStop(); } paused = false; SMPEG.SMPEG_rewind(mpeg); // 巻き戻す } else { if (!Loaded && fileName != null) { YanesdkResult result = Load(fileName); if (result != YanesdkResult.NoError) { return(result); } } } #else Stop(); #endif readyToDraw = false; // 描画しなおされるまでは描画準備状態とする InnerPlay(); return(YanesdkResult.NoError); } }
/// <summary> /// 読み込んでいた動画の解放 /// </summary> public void Release() { lock (lockObject) { fileName = null; if (Loaded) { SDL.Mix_HookMusic(null, IntPtr.Zero); Stop(); SMPEG.SMPEG_delete(mpeg); mpeg = IntPtr.Zero; if (Yanesdk.System.Platform.PlatformID == Yanesdk.System.PlatformID.Windows && sdlWindowCreated) { IntPtr sdlHwnd = GetSDLWindowHandle(); SetParent(sdlHwnd, IntPtr.Zero); ShowWindow(sdlHwnd, SW_HIDE); } } if (tmpFile != null) { tmpFile.Dispose(); tmpFile = null; } if (surface != null) { surface.Dispose(); surface = null; } } }
/// <summary> /// 再生開始とループ設定の反映 /// </summary> private void InnerPlay() { SMPEG.SMPEG_play(mpeg); // ループ設定を反映させる if (loop) { SMPEG.SMPEG_loop(mpeg, loop ? 1 : 0); } }
/// <summary> /// SDL.Mix_HookMusic()に登録する関数 /// </summary> private void mix_HookMusic(/* void * */ IntPtr udata, /* Uint8 * */ IntPtr stream, int len) { // lock (lockObject) // これはデッドロックするかも。。 if (mpeg != IntPtr.Zero && SMPEG.SMPEG_status(mpeg) == SMPEG.SMPEGstatus.SMPEG_PLAYING) { SMPEG.SMPEG_playAudio(mpeg, stream, len); } }
/// <summary> /// 再生停止 /// </summary> private void InnerStop() { SMPEG.SMPEG_loop(mpeg, 0); // ループしてると止まらないらしい SMPEG.SMPEG_stop(mpeg); }
/// <summary> /// mpegファイルを読み込む /// </summary> /// <param name="filename">ファイル名</param> public YanesdkResult Load(string filename) { lock (lockObject) { Release(); tmpFile = FileSys.GetTmpFile(filename); if (tmpFile == null || tmpFile.FileName == null) { return(YanesdkResult.FileNotFound); } // 読み込み。 //mpeg = SMPEG.SMPEG_new(tmpFile.FileName, ref info, SDL.SDL_WasInit(SDL.SDL_INIT_AUDIO) == 0 ? 1 : 0); mpeg = SMPEG.SMPEG_new(tmpFile.FileName, ref info, 0); if (SMPEG.SMPEG_error(mpeg) != null) { Debug.Fail(SMPEG.SMPEG_error(mpeg)); return(YanesdkResult.SdlError); // …SDL? } // 初期設定 // loop = false; // ループ設定はここでは変更しないほうが良い。 paused = false; SMPEG.SMPEG_enablevideo(mpeg, 1); SMPEG.SMPEG_enableaudio(mpeg, 0); if (info.has_audio != 0) { SDL.SDL_AudioSpec audiofmt = new SDL.SDL_AudioSpec(); audiofmt.format = (ushort)Sound.Sound.SoundConfig.AudioFormat; audiofmt.freq = (ushort)Sound.Sound.SoundConfig.AudioRate; audiofmt.channels = (byte)Sound.Sound.SoundConfig.AudioChannels; audiofmt.samples = (ushort)Sound.Sound.SoundConfig.AudioBuffers; SMPEG.SMPEG_actualSpec(mpeg, ref audiofmt); SDL.Mix_HookMusic(mix_hook, mpeg); SMPEG.SMPEG_enableaudio(mpeg, 1); } SMPEG.SMPEG_enableaudio(mpeg, 1); Volume = volume; // 描画先サーフェスのsmpegへの登録など。 if (window != null) { // SDLWindowに直に描画する if (surface != null) { surface.Dispose(); surface = null; } uint flags = (uint)window.Option; flags &= ~SDL.SDL_OPENGL; // OPENGLはダメ。 IntPtr s = SDL.SDL_SetVideoMode(window.Width, window.Height, window.Bpp, flags); if (s == IntPtr.Zero) { return(YanesdkResult.SdlError); } SMPEG.SMPEG_setdisplay(mpeg, s, IntPtr.Zero, null); SMPEG.SMPEG_move(mpeg, (int)windowRect.Left, (int)windowRect.Top); SMPEG.SMPEG_scaleXY(mpeg, (int)windowRect.Width, (int)windowRect.Height); } else if ( Yanesdk.System.Platform.PlatformID == Yanesdk.System.PlatformID.Windows && hwnd != IntPtr.Zero) { // SDLWindowを貼り付けてそれに描画する if (surface != null) { surface.Dispose(); surface = null; } // 親ウィンドウの位置・サイズを取得 POINT parentPos = new POINT(); ClientToScreen(hwnd, ref parentPos); RECT parentRect = new RECT(); GetClientRect(hwnd, out parentRect); int w = parentRect.right - parentRect.left, h = parentRect.bottom - parentRect.top; // SDLウィンドウの位置を合わせる IntPtr sdlHwnd = GetSDLWindowHandle(); //SetParent(sdlHwnd, hwnd); // これするとどうもバグる… SetWindowPos(sdlHwnd, IntPtr.Zero, parentPos.x, parentPos.y, w, h, SWP_NOZORDER); // SDLウィンドウの作成 uint flags = SDL.SDL_HWSURFACE | SDL.SDL_NOFRAME; IntPtr s = SDL.SDL_SetVideoMode(w, h, 0, flags); if (s == IntPtr.Zero) { return(YanesdkResult.SdlError); } sdlWindowCreated = true; sdlHwnd = GetSDLWindowHandle(); // 変わらないと思うが、一応再取得 if (sdlHwnd == IntPtr.Zero) { return(YanesdkResult.SdlError); } SetParent(sdlHwnd, hwnd); SetWindowPos(sdlHwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); SMPEG.SMPEG_setdisplay(mpeg, s, IntPtr.Zero, null); SMPEG.SMPEG_move(mpeg, 0, 0); SMPEG.SMPEG_scaleXY(mpeg, w, h); } else { // surfaceに描画する if (surface != null && (!surface.CheckRGB888() || surface.Width != Width || surface.Height != Height)) { surface.Dispose(); surface = null; } if (surface == null) { surface = new Surface(); // 拡大・縮小はSMPEG側にやらせると重いので、原寸大で。 YanesdkResult result = surface.CreateDIB(Width, Height, false); if (result != YanesdkResult.NoError) { return(result); } } SMPEG.SMPEG_setdisplay(mpeg, surface.SDL_Surface, mutex, callback); SMPEG.SMPEG_move(mpeg, 0, 0); SMPEG.SMPEG_scaleXY(mpeg, surface.Width, surface.Height); //SetFilter(SMPEG.SMPEGfilter_null()); } this.fileName = filename; // おしまい。 return(YanesdkResult.NoError); } }