高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technical Q&A QA1274
Filtering QuickTime media types using Navigation Services


Q: QuickTime で開けるすべてのファイルをフィルタリングするために、Q&A 1152 で説明されているように、自分の Navigation Services フィルタプロシージャの中で CanQuickTimeOpenFile 関数を使用しています。しかし、さらにこのリストを、オーディオファイルなど特定のメディアタイプのファイルだけに限定したいとも考えています。これを実現する簡単な方法はありますか?

A: あります。GetMovieIndTrackType 関数を使って、trackType フィールドにメディアタイプを指定することにより、ファイルのこのリストを特定のメディアタイプ(Flash、Sound、Music、MPEG、など)のファイルに限定できます。

GetMovieIndTrackType の使用は、ムービーの中に指定したメディアタイプのトラックが含まれているかどうかを検出するのに最適です。追加の処理を行う予定であれば、アプリケーションがサポートしている特定のメディアタイプを探す必要があることも考えられます。

GetMovieIndTrackType 関数を使うと、実際にファイルを開く必要があるため、当然、フィルタ処理の速度が低下する可能性があります。すべてのファイルを開かなくても済むようにする 1 つのテクニックとしては、GetMovieImporterForDataRef 関数を使って適切なムービーインポートコンポーネントを見つけ、インポート先のメディアタイプを確認するやり方があります。このメディアタイプは、インポータが作成するメディアトラックの種類を示します(NULL の場合は、複数のメディアタイプがファイルに含まれていることを示します)。この方法は、必ずしもファイルをインポートするものではなく、開くことさえも必要としません。

インポート先のメディアタイプの情報は、次のいずれかの場所で確認できます。すなわち、コンポーネント登録情報(ComponentDescription レコード内)の製造元フィールドとして使われている 4 文字のコード、またはインポータコンポーネントがコンポーネントフラグ movieImportMustGetDestinationMediaType をサポートしている場合は、コンポーネントの MovieImportGetDestinationMediaType 関数を呼び出すことによって(ただし、この関数は、Carbon アプリケーションからは呼び出せないという不具合 (r. 3328291) があります)、インポート先のメディアタイプを取得できます。MovieImportGetDestinationMediaType のテクニックは、より新しい(QuickTime 6 以降の)コンポーネントに対してのみ使用できます。

インポート先のメディアタイプが 0 以外の場合は、インポータが特定のメディア(トラック)タイプでのみムービーを作成することを示します。AVI や DV の場合のように、インポート先のメディアタイプが 0 の場合は、インポータが複数のメディアタイプを混合したファイルを作成することを示します。後者の場合、ファイルにオーディオデータが含まれていることが考えられますが、実際にファイルをインポートしてさまざまなトラックを調査しなければ分かりません。

以下に紹介する Navigation Services のフィルタ関数のサンプルは、CanQuickTimeOpenFile API を使って、QuickTime で開けるすべてのファイルをチェックする方法と、GetMovieImporterForDataRefMovieImportGetDestinationMediaType を使って、ムービーインポータに対してインポート先のメディアタイプを照会し、特定のメディアタイプのファイルに絞り込む方法を示しています。



リスト 1. Navigation Services フィルタプロシージャでの QuickTime メディアタイプのフィルタ処理



#define kAliasDataRefType FOUR_CHAR_CODE('alis')

#define SHOW_ONLY_AUDIO_FILES   1 
#define SHOW_ONLY_VIDEO_FILES   0


OSStatus    GetFSSpecFromAEDesc( FSSpec *fsspec, AEDesc* theItem )
{
    OSStatus    err           = noErr;
    AEDesc      coerceDesc    = { NULL, NULL };

    /* AEDesc がまだ FSSpec でない場合は、FSSpec に変換する... */
    if (theItem->descriptorType != typeFSS)
    {
        err = AECoerceDesc( theItem, typeFSS, &coerceDesc );
        /* AEDesc から FSSpec を取得する */
        if ( err == noErr )
        {
            err = AEGetDescData( &coerceDesc, fsspec, sizeof(FSSpec) );
            AEDisposeDesc( &coerceDesc );
        }
    }
    else
    {
        err = AEGetDescData( theItem, fsspec, sizeof(FSSpec) );
    }

    return( err );
}



pascal Boolean NavLaunchServicesFilterProc(AEDesc* theItem,
                                            void* info,
                                            NavCallBackUserData ioUserData,
                                            NavFilterModes filterMode)
    {
    #pragma unused(ioUserData)

    NavFileOrFolderInfo *myInfo     = (NavFileOrFolderInfo *)info;
    OSStatus            err         = noErr;
    Boolean             showItem    = false;
    FSSpec              fsspec;


    if ( filterMode == kNavFilteringBrowserList )
    {
        if (theItem->descriptorType == typeFSS)
        {
            /* ファイルまたはフォルダのどちらか? */
            if (myInfo->isFolder)
            {
                /* すべてのフォルダを表示 */
                showItem = true;
            }
            else    /* ファイルはあるがフォルダはない */ 
            {
                Boolean outCanOpenWithGraphicsImporter  = false;
                Boolean outCanOpenAsMovie               = false;

                err = GetFSSpecFromAEDesc( &fsspec, theItem );
                if ( err != noErr ) goto BailWithError;
/*
CanQuickTimeOpenFile 関数に関する参考文献を、本文書の最後に示します。


対象ファイルの FSSpec を渡すだけで、QuickTime は、
outCanOpenWithGraphicsImporter パラメータと outCanOpenAsMovie 
パラメータの中で、ファイルがグラフィックスインポータを使って、
またはそのままムービーとして開けるかどうかを示す値を返します。


特に興味深いのは、inFlags パラメータとして渡せる各種のフラグです。
これらは、QuickTime の検索方法に影響を与えます。
次に各種フラグのリストを示します。


-inFlags 定数-

kQTDontUseDataToFindImporter

このフラグは、ファイル中のデータを検索には利用しないように
QuickTime に指示します。これにより、開けるファイルがないという
結果が返される場合には特に検索の速度は上がりますが、
QuickTime は、ファイルタイプやファイル拡張子で認識できない
ファイルを開けないと報告することになります。

kQTDontLookForMovieImporterIfGraphicsImporterFound

このフラグは、ファイルを開く方法が見つかった時点で、
QuickTime に検索を終了するように指示します。ファイルが、
グラフィックスインポータを使ってまたはそのままムービーとして
開けるかどうかを知りたい場合、そしてその方法を問わない場合に
このフラグを渡します。


kQTAllowOpeningStillImagesAsMovies

このフラグは、QuickTime に、静止画をムービーとして開くことを
検討するように指示します。このフラグをグラフィックスインポータで
開けるとき、QuickTime は自動的に、ファイルをムービーとして開ける
と報告します。

kQTAllowImportersThatWouldCreateNewFile

このフラグは、QuickTime に、新しいファイルを作成するインポータを
含めるように指示します。このフラグがクリアされている場合、
QuickTime は、新しいファイルを作成しなくてもそのまま
インポートできるインポータのみを含めます。


kQTAllowAggressiveImporters

このフラグは、PICT や TEXT のような通例ムービーとは考えられない
ファイルタイプのためにムービーインポータを含めるように指示します。
このフラグがクリアされている場合、QuickTime は、これらの
ムービーインポータを除外します。


検索の速度が向上するので、ファイルを開く方法にこだわらない場合は、
kQTDontLookForMovieImporterIfGraphicsImporterFound
フラグの使用を推奨します。状況によっては、検索の速度を向上させる 
kQTDontUseDataToFindImporter フラグを使うのが便利かもしれませんが、
欠点は、拡張子またはファイルタイプを認識できないファイルをスキップ
してしまうことです。


*/

                err = CanQuickTimeOpenFile(
                    &fsspec,
                        /* ファイルの種類。分からない場合は 0 */
                    myInfo->fileAndFolder.fileInfo.finderInfo.fdType,
                        /* ファイルの拡張子。分からない場合は 0 */
                    0,
                        /* ファイルをグラフィックスインポータで開ける場合は true を返す
                            */
            #if SHOW_ONLY_VIDEO_FILES
                    &outCanOpenWithGraphicsImporter,
            #elif SHOW_ONLY_AUDIO_FILES
                    0,
            #endif
                        /* ファイルをムービーインポータで開ける場合は true を返す
                            */
                    &outCanOpenAsMovie,
                        /* ファイルをグラフィックスインポータまたはムービーインポータの
                           どちらでも開ける場合は、true を返すが
                           QuickTime はグラフィックスインポータの使用を優先する 
                            */
                    nil,
                     /* inFlags
            QuickTime に、ファイルを見つけ次第検索を終了するように指示するために
            kQTDontLookForMovieImporterIfGraphicsImporterFound を指定する
                        ファイルを、グラフィックスインポータを使って開けるか、
                        ムービーとして開けるかは問わない */
                    kQTDontLookForMovieImporterIfGraphicsImporterFound);

                if ( err != noErr ) goto BailWithError;

                if (outCanOpenAsMovie)
                {
                    OSErr                   err = noErr;
                        // ファイルタイプに関連付けられている MovieImport
                        // コンポーネント
                    Component               theImporter = nil;
                        // componentManufacturer を見るために使用
                    ComponentDescription    cd;                         
                    OSType                  destinationMediaType = 0;
                    long                    myFlags = 0;                
                    AliasHandle             theAliasHandle;

                    // エイリアスデータ参照を作成

                    err = NewAlias(nil, &fsspec, &theAliasHandle);
                    if (err == noErr)
                    {
                        // インポータコンポーネントを探す
                        // (ComponentInstance ではないので、
                        // あとで閉じる必要はない)

                        err = GetMovieImporterForDataRef(kAliasDataRefType,
                                                    (Handle)theAliasHandle,
                                                    myFlags,
                                                    &theImporter);

                        if (noErr == err) 
                        {
                            // 説明のフラグと製造元タイプ
                            // のフィールドを見る
                            GetComponentInfo(theImporter, 
                                &cd, nil, nil, nil);

                        // このコンポーネントによって 
                        // movieImportMustGetDestinationMediaType が設定されて
                        // いる場合は、MovieImportGetDestinationMediaType
                        // をこのコンポーネントに呼び出すことにより、送り
                        // 先のメディアタイプを照会できることを示す

                            if (cd.componentFlags &
                                    movieImportMustGetDestinationMediaType)
                            {

                                // インポータにインポート先のメディアタイプを尋ねる
                                // (注:インポータコンポーネントを開く
                                // 必要はない。必要な処理が自動的に行われる)

                                MovieImportGetDestinationMediaType(
                                    (MovieImportComponent)theImporter,
                                    &destinationMediaType);
                            }

                            else    // GetComponentInfo からの製造元タイプ
                                    // を使用する。製造元フィールドは、
                                    // コンポーネントによってサポートされる
                                    // QuickTime メディアタイプを示している
                                    // (たとえば、サウンドは 'soun')。
                                    // サブタイプの値は、コンポーネントが
                                    // インポートできるデータタイプを
                                    // 示す(たとえば 'AIFF')
                            {
                                destinationMediaType = 
                                    cd.componentManufacturer;
                            }
                        }

                        // else

                        // この形式用のインポータは存在しないが QuickTime が
                        // この形式(QuickTime ムービーファイル)
                        // を開くことができるか、またはインポータが
                        // 存在しないかのいずれか。どちらの場合も、
                        // destinationMediaType は 0

                        // 現時点では、質問の答えには destinationMediaType
                        // (おそらく 0)を使う
                        //

                        // メディアタイプが分かっており、サポートして
                        // いるトラックタイプを確認できる。
                        // それを認識できなかった場合は、ファイルを開き、
                        // GetMovieIndTrackType を使って
                        // 調べる必要がある

                        if (destinationMediaType)
                        {
                        
                    #if SHOW_ONLY_AUDIO_FILES
                            // サウンド ('soun') メディアタイプかどうかをチェック
                            if (destinationMediaType == SoundMediaType)
                    #elif SHOW_ONLY_VIDEO_FILES
                            // ビデオ ('vide') メディアタイプかどうかをチェック
                            if (destinationMediaType == VideoMediaType)
                    #endif
                    
                            {
                                showItem = true;
                            }
                        }
                        else    // 有力な情報がないため、開いて
                                // GetMovieIndTrackType を使って
                                // ムービーのトラックを調べる。
                                // その後、必ずムービーを閉じる
                        {
                            OSErr err = noErr;
                            short fileRefNum = 0;

                            err = OpenMovieFile(&fsspec, 
                                                &fileRefNum,
                                                fsRdPerm);
                            if (err == noErr)
                            {
                                // 最初のムービーを取得したい
                                short   resID = 0;
                                Movie   theMovie = nil;

                                err = NewMovieFromFile(&theMovie,
                                                        fileRefNum,
                                                        &resID,
                                                        NULL,
                                                        newMovieActive,
                                                        NULL);
                                if (err == noErr)
                                {
                                    // トラック(メディア)タイプを調べる

                                    if(GetMovieIndTrackType(theMovie,
                                                1L,
                                    #if SHOW_ONLY_AUDIO_FILES
                                                SoundMediaType,
                                    #elif SHOW_ONLY_VIDEO_FILES
                                                VideoMediaType,
                                    #endif
                                                movieTrackMediaType))
                                        {
                                            // ムービーは希望のメディアタイプ!

                                            showItem = true;
                                        }
                                    DisposeMovie(theMovie);
                                }
                                CloseMovieFile(fileRefNum);
                            }
                        }
                        DisposeHandle((Handle)theAliasHandle);
                    }
                }
                else if (outCanOpenWithGraphicsImporter)
                {
                    showItem = true;
                }
            }
        }
    }

    return (showItem);

BailWithError:
    return( false );

}




参考資料:

Navigation Services Reference

CanQuickTimeOpenFile API

GetMovieIndTrackType API

MovieImportGetDestinationMediaType API

Movie Data Exchange Components



[2003 年 7 月 23 日]