今回は前回の続きです。まずは、編集メニューから実行するMovieの「カット&ペースト」処理を見てみます。続いて、ファイルから読み込んだMovieを表示するためにウィンドウを開き、そこに映像のコントロール(再生や停止など)を担当する「Movie Controller」を割り当てる処理を解説します。
ユーザがメニューを選択すると、Carbon Event HandleルーチンとしてインストールされているmyCarbonEventHandler()からdoCommand()が呼ばれます。

doCommand()ルーチンの引き数は2つで、最初が処理対象となるMovieウィンドウのWindowRef、その次がメニューアイテムに割り当てられているコマンドIDです。処理の入り口では、引き数のwindowがゼロでないかどうかをチェックしています。例えば、Movieウィンドウがひとつも開いていない状態でメニューを選択すると、処理はアプリケーションのEvent Handler経由でdoCommand()に渡ってきます。ですから、windowは何も代入されておらずゼロとなります。
Movieウィンドウが開いている時に編集メニューから「カット」を選ぶと、処理はウィンドウ側のEvent Handler経由でdoCommand()に渡ってきます。この場合には、引き数のwindowには対象ウィンドウのWindowRefが代入されています。GetWRefCon()で配列番号を得て、w_play[]とw_mov[]からウィンドウで利用しているMovieControllerとMovieを抽出します。Movie映像のクリップボード経由での編集は、QuickTimeに用意されているMCUndo()、MCCut()、MCCopy()、MCPaste()、MCClear()、PutMovieOnScrap()といったAPIを使えば簡単に実現できます。playがゼロ(NULL)の時には、どの編集処理も禁止されている点に注意してください。playがゼロであれば、引き数のwindowもゼロであり、対象ウィンドウが存在しないことを意味します。こうした場合には、編集メニューの各アイテムをハイライトに変更するのがマナーなのですが、今回はその処理を省略しています。
Carbon Event Handlerから届いたコマンドIDが'quit'の場合には、doQuit()でアプリケーションを終了させます。

処理内容は、オープンされているすべてのMovieウィンドウをdisposeMovieWindow()(後述します)で「正常」に閉じてから、ExitMovies()でQuickTimeの作業領域を開放し、最後にExitToShell()でアプリケーションから抜けます。doQuit()ルーチンの代わりにQuitApplicationEventLoop()を実行し、Carbon Event Loopから抜け出したコード位置(今回はmain()ルーチンの最後)に終了処理を記述しておいてもかまいません。
ファイルメニューから「開く」を選択すると、Movieファイルを選ぶためのopenMovie()ルーチンが呼ばれます。

openMovie()は、NavigationサービスのNavGetFile()を使い「ファイル選択ダイアログ」をオープンします。この時に使う「選択可能なファイルタイプリスト」は'open'リソースとして用意されています(今回は'MooV'ひとつ)。処理の途中では「何もしない」sfEventProc()コールバックルーチンをNavEventUPPとしてインストールしていまが、これは、ファイル選択ダイアログを移動可能(Movable Dialog)にするためです。ダイアログでの処理が終わると、AEGetNthPtr()を使い選んだファイルのFSSpec構造体(保存場所情報)を得ることができます。それをloadMovie()に渡し、ファイルからMovie情報を抽出します。loadMovie()は、OpenMovieFile()とNewMovieFromFile()を使った簡単なルーチンです。
ファイルから抽出されたMovie情報は、ファイル名と供にopenMovieWindow()ルーチンに渡されます。

GetMovieBox()で映像の縦横サイズを得たら、それをnewMovieWindow()に渡し「映像表示サイズ」と一致したウィンドウを作成します。

newMovieWindow()の最初の仕事は、w_mov[]配列をサーチして空きがあるかどうかを調べることです。配列に空きがあれば、その配列番号をウィンドウのwindowRefConフィールドに保存し、あとから参照できるようにします。空きが無ければ、準備しておいた配列はすべて使い尽くしたことになるので(ウィンドウが50も開いている)、これ以上Movieウィンドウを作成することはできません。
openMovieWindow()で呼ばれているNewMovieController()が、Movie Controllerをウィンドウに割り当てるルーチンです。NewMovieController()が返してたplayと引き数のmovは、後から参照できるようにnewMovieWindow()が見つけた空きの配列番号に保存されます。MCGetControllerBoundsRect()でMovie Controllerのサイズを得たら、それをもとにSizeWindow()でウィンドウサイズを再調整します。SetMovieSelection()は、Movie映像をカット、コピー、クリアーする時の選択範囲を設定します。ここでの初期設定は「選択範囲無し」です。SetMovieTimeValue()ではMovieの映像ポジション(Movie Controllerのつまみ位置)を先頭にしています。MCDoAction()での設定は、Movie Controllerに対するキーボード操作(コマ送りに矢印キー、再生開始にReturnキーなどが使える)を可能にし、MCEnableEditing()では、このMovieを「編集可能」と定義しています。ウィンドウを表示するにはTransitionWindow()を使い、表示後にMCDraw()を実行して映像の先頭とMovie Controllerをウィンドウ上に描画します。
最後に、Movieウィンドウを閉じる時に呼ぶdisposeMovieWindow()ルーチンを解説しておきます。

まずは、GetWRefCon()で得た配列番号からウィンドウに割り当てられているw_play[]とw_mov[]を特定し、DisposeMovieController()とDisposeMovie()を使いその作業領域を解放します。その後、DisposeWindow()でウィンドウを閉じたら、割り当てられていたw_play[]とw_mov[]にゼロを代入して空にしておくことを忘れないでください。この処理を忘れると、オープン可能なMovieウィンドウの数がどんどん減って行き、最後にはウィンドウがまったく開けなくなってしまいます。(一端アプリケーションを終了すれば大丈夫ですが...)
ここで解説している「MoviePlay_3.0」サンプルアプリケーションは、以下のサイトに登録されていますので試してみてください。前回登録したソースはdoCommand()ルーチンに若干バグがありましたので、2002年7月8日付けで再登録してあります。MakeにはMac OS X 10.1とMetrowerks CodeWarrior v8が必要です。
http://www.ottimo.co.jp/library/
来週からMACWORLD Expo NewYorkが開催されます。噂によると、新型のPowerMac G4が発表され、Mac OS X 10.2(Jaguar)の配付時期が決まると言われています。Jaguarは夏の終わりまでに登場するのか?Jobsが行う基調講演のストリーミング放送を楽しみに待ちたいと思います(今回もあるよね?)。
copyright 2002 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact Us: koike@ottimo.co.jp