/* =============================================================================== RiffInfo.mc : RIFF ファイルの中身のデータ構成を表示する =============================================================================== */ #set p print #set IDC( c1,c2,c3,c4 ) (#c1+(#c2<<8)+(#c3<<16)+(#c4<<24)) fname = null; // RIFF ファイルの名前 ^ShowData? = #TRUE; // 既知のチャンクなら詳細内容を表示するというフラグ for( i = 0 ; i < argc ; i++ ) { prm = argv[i]; if( prm == "/s" ) // 既知のチャンクでも詳細内容は非表示という指定? ^ShowData? = #FALSE; else if( prm'part == "/" ) { #p prm : " は不正なオプションです!"; return; } else fname = argv[i]; } if( fname == null ) // コマンド引数でファイル名の指定なし? fname = ^GetOpenFile(); // ファイル名入力のダイアログボックスを表示 if( ! fname ) // ファイル名の入力なし? return; ^file = ::File.Open( fname, "in" ); #p ^file.name; ^file.Read( id'ULONG ); if( id == #IDC(`R`,`I`,`F`,`F`) ) { if( ^ShowListInfo( id, 0, 1 ) <= 0 ) #p " データ構成が不正です!"; } else #p " これは RIFF ファイルではありません!"; FIN: #p ; delete ^file; return; OnError: #p ::ErrorMessage( $err_code, $err_info ); goto FIN; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowListInfo( id, top_pos, depth ) { ^file.Read( size'ULONG, fcc'ULONG ); #p top_pos'x(6) : " "'rep( depth ) : id'Idcs : " " : fcc'Idcs'quote(`'`) : " 0x" : size'x(2) ; size = ( size + 1 ) & ~01 ; // 偶数化 cur_pos = top_pos + 12; end_pos = cur_pos + ( size - 4 ); while( cur_pos < end_pos ) { if( ^file.Read( Fcc'ULONG ) < 0 ) return -1; switch( Fcc ) { case #IDC(`L`,`I`,`S`,`T`): new_pos = ^ShowListInfo( Fcc, cur_pos, depth + 1 ); // 再帰呼出! break; default: new_pos = ^ShowChunkInfo( Fcc, cur_pos, depth + 1 ); break; } if( new_pos <= cur_pos ) // データ不正? return 0; cur_pos = new_pos; } if( cur_pos != end_pos ) // データ不正? return 0; return end_pos; // 本 LIST ブロックの最終位置 OnFileError: return -1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkInfo( fcc, top_pos, depth ) { ^file.Read( size'ULONG ); #p top_pos'x(6) : " "'rep( depth ) : "CHUNK " : fcc'Idcs'quote(`'`) : " 0x" : size'x(2) ; if( ^ShowData? ) // 既知のチャンクは詳細内容を表示? { indent = " : " + " "'rep( depth ) + "| "; ^ShowChunkData[ fcc ]( size, indent ); } SEEK_BLOCK_END: size = ( size + 1 ) & ~01 ; // 偶数化 end_pos = top_pos + 8 + size; if( ^file.Seek( end_pos ) != end_pos ) return 0; return end_pos; // 本 CHUNK ブロックの最終位置 OnFileError: return -1; OnFuncError: $err_state = 0; goto SEEK_BLOCK_END; NotJustSize: #p indent : " .........."; goto SEEK_BLOCK_END; } //----------------------------------------------------------------------------- function ^ShowChunkData[ #IDC(`a`,`v`,`i`,`h`) ]( size, indent ) { MainAVIHeader ::= { .dwMicroSecPerFrame 'ULONG; .dwMaxBytesPerSec 'ULONG; .dwPaddingGranularity 'ULONG; .dwFlags 'ULONG; .dwTotalFrames 'ULONG; .dwInitialFrames 'ULONG; .dwStreams 'ULONG; .dwSuggestedBufferSize 'ULONG; .dwWidth 'ULONG; .dwHeight 'ULONG; .dwReserved 'ULONG(4); } sz = MainAVIHeader'size; #p indent : "MainAVIHeader:" : ( sz != size ? " 0x" + sz'x(2) : "" ); if( sz <= size ) { ^file.Read( MainAVIHeader ); scope MainAVIHeader { #p indent : " .dwMicroSecPerFrame = ": .dwMicroSecPerFrame :"\n": indent : " .dwMaxBytesPerSec = ": .dwMaxBytesPerSec :"\n": indent : " .dwPaddingGranularity = ": .dwPaddingGranularity :"\n": indent : " .dwFlags = 0x": .dwFlags'x(4) :"\n": indent : " .dwTotalFrames = ": .dwTotalFrames :"\n": indent : " .dwInitialFrames = ": .dwInitialFrames :"\n": indent : " .dwStreams = ": .dwStreams :"\n": indent : " .dwSuggestedBufferSize = ": .dwSuggestedBufferSize :"\n": indent : " .dwWidth = ": .dwWidth :"\n": indent : " .dwHeight = ": .dwHeight :"\n": -; } } if( sz != size ) warp NotJustSize; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkData[ #IDC(`s`,`t`,`r`,`h`) ]( size, indent ) { AVIStreamHeader ::= { .fccType 'ULONG; .fccHandler 'ULONG; .dwFlags 'ULONG; .wPriority 'USHORT; .wLanguage 'USHORT; .dwInitialFrames 'ULONG; .dwScale 'ULONG; .dwRate 'ULONG; .dwStart 'ULONG; .dwLength 'ULONG; .dwSuggestedBufferSize 'ULONG; .dwQuality 'ULONG; .dwSampleSize 'ULONG; .rcFrame 'SHORT(4); // ← RECT だが各要素は LONG ではない! } sz = AVIStreamHeader'size; #p indent : "AVIStreamHeader:" : ( sz != size ? " 0x" + sz'x(2) : "" ); if( sz <= size ) { ^file.Read( AVIStreamHeader ); scope AVIStreamHeader { #p indent : " .fccType = ": .fccType'Idcs'quote(`'`) :"\n": indent : " .fccHandler = ": .fccHandler'Idcs'quote(`'`) :"\n": indent : " .dwFlags = 0x": .dwFlags'x(4) :"\n": indent : " .wPriority = ": .wPriority :"\n": indent : " .wLanguage = ": .wLanguage :"\n": indent : " .dwInitialFrames = ": .dwInitialFrames :"\n": indent : " .dwScale = ": .dwScale :"\n": indent : " .dwRate = ": .dwRate :"\n": indent : " .dwStart = ": .dwStart :"\n": indent : " .dwLength = ": .dwLength :"\n": indent : " .dwSuggestedBufferSize = ": .dwSuggestedBufferSize :"\n": indent : " .dwQuality = ": .dwQuality :"\n": indent : " .dwSampleSize = ": .dwSampleSize :"\n": indent : " .rcFrame = ": .rcFrame(0), .rcFrame(1), .rcFrame(2), .rcFrame(3) :"\n": -; ^StrmType = .fccType; } } if( sz != size ) warp NotJustSize; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkData[ #IDC(`s`,`t`,`r`,`f`) ]( size, indent ) // Stream Format { switch( ^StrmType ) { case #IDC(`v`,`i`,`d`,`s`): goto VIDEO_FORMAT; case #IDC(`a`,`u`,`d`,`s`): goto AUDIO_FORMAT; default: ^StrmType = 0; warp NotJustSize; } VIDEO_FORMAT: BITMAPINFOHEADER ::= { .biSize 'ULONG; .biWidth 'LONG; .biHeight 'LONG; .biPlanes 'USHORT; .biBitCount 'USHORT; .biCompression 'ULONG; .biSizeImage 'ULONG; .biXPelsPerMeter 'LONG; .biYPelsPerMeter 'LONG; .biClrUsed 'ULONG; .biClrImportant 'ULONG; } sz = BITMAPINFOHEADER'size; #p indent : "BITMAPINFOHEADER:" : ( sz != size ? " 0x" + sz'x(2) : "" ); if( sz <= size ) { ^file.Read( BITMAPINFOHEADER ); scope BITMAPINFOHEADER { #p indent : " .biSize = ": .biSize : "\n": indent : " .biWidth = ": .biWidth : "\n": indent : " .biHeight = ": .biHeight : "\n": indent : " .biPlanes = ": .biPlanes : "\n": indent : " .biBitCount = ": .biBitCount : "\n": indent : " .biCompression = ": .biCompression'Idcs'quote(`'`) : "\n": indent : " .biSizeImage = ": .biSizeImage : "\n": indent : " .biXPelsPerMeter = ": .biXPelsPerMeter : "\n": indent : " .biYPelsPerMeter = ": .biYPelsPerMeter : "\n": indent : " .biClrUsed = ": .biClrUsed : "\n": indent : " .biClrImportant = ": .biClrImportant : "\n": -; } } goto FIN; AUDIO_FORMAT: WAVEFORMATEX ::= { .wFormatTag 'USHORT; .nChannels 'USHORT; .nSamplesPerSec 'ULONG ; .nAvgBytesPerSec 'ULONG ; .nBlockAlign 'USHORT; .wBitsPerSample 'USHORT; if( size >= 0x12 ) .cbSize 'USHORT; } sz = WAVEFORMATEX'size; #p indent : "WAVEFORMATEX:" : ( sz != size ? " 0x" + sz'x(2) : "" ); if( sz <= size ) { ^file.Read( WAVEFORMATEX ); scope WAVEFORMATEX { #p indent : " .wFormatTag = 0x": .wFormatTag'x(2) : "\n": indent : " .nChannels = " : .nChannels : "\n": indent : " .nSamplesPerSec = " : .nSamplesPerSec : "\n": indent : " .nAvgBytesPerSec = " : .nAvgBytesPerSec : "\n": indent : " .nBlockAlign = " : .nBlockAlign : "\n": indent : " .wBitsPerSample = " : .wBitsPerSample : "\n":-; if( size >= 0x12 ) #p indent : " .cbSize = 0x": .cbSize'x(2) : "\n":-; } } FIN: ^StrmType = 0; if( sz != size ) warp NotJustSize; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkData[ #IDC(`s`,`t`,`r`,`n`) ]( size, indent ) { ^file.Read( Name'C( size ) ); #p indent : " Stream Name: " : Name'quote; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkData[ #IDC(`i`,`d`,`x`,`1`) ]( size, indent ) { AVIINDEXENTRY ::= { .ckid 'ULONG; .dwFlags 'ULONG; .dwChunkOffset 'ULONG; .dwChunkLength 'ULONG; } sz = AVIINDEXENTRY'size; rz = size; for( i = 0 ;; i++ ) { #p indent : "AVIINDEXENTRY[" : i : "]:" : ( rz < sz ? " 0x" + rz'x(2) : "" ); if( rz < sz ) warp NotJustSize; ^file.Read( AVIINDEXENTRY ); scope AVIINDEXENTRY { #p indent : " .ckid = " : .ckid'Idcs'quote(`'`) :"\n": indent : " .dwFlags = 0x" : .dwFlags'x(2) :"\n": indent : " .dwChunkOffset = 0x" : .dwChunkOffset'x(2) :"\n": indent : " .dwChunkLength = 0x" : .dwChunkLength'x(2) :"\n": -; } if(( rz -= sz ) == 0 ) break; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^ShowChunkData[ #IDC(`f`,`m`,`t`,` `) ]( size, indent ) { WAVEFORMATEX ::= { .wFormatTag 'USHORT; .nChannels 'USHORT; .nSamplesPerSec 'ULONG ; .nAvgBytesPerSec 'ULONG ; .nBlockAlign 'USHORT; .wBitsPerSample 'USHORT; if( size >= 0x12 ) .cbSize 'USHORT; } sz = WAVEFORMATEX'size; #p indent : "WAVEFORMATEX:" : ( sz != size ? " 0x" + sz'x(2) : "" ); if( sz <= size ) { ^file.Read( WAVEFORMATEX ); scope WAVEFORMATEX { #p indent : " .wFormatTag = 0x": .wFormatTag'x(2) : "\n": indent : " .nChannels = " : .nChannels : "\n": indent : " .nSamplesPerSec = " : .nSamplesPerSec : "\n": indent : " .nAvgBytesPerSec = " : .nAvgBytesPerSec : "\n": indent : " .nBlockAlign = " : .nBlockAlign : "\n": indent : " .wBitsPerSample = " : .wBitsPerSample : "\n":-; if( size >= 0x12 ) #p indent : " .cbSize = 0x": .cbSize'x(2) : "\n":-; } } if( sz != size ) warp NotJustSize; } //----------------------------------------------------------------------------- function 'Idcs( c ) { return ( c & 0xFF )'c + (( c >> 8 ) & 0xFF )'c + (( c >> 16 ) & 0xFF )'c + (( c >> 24 ) & 0xFF )'c ; } //----------------------------------------------------------------------------- function ^GetOpenFile() { Comdlg32 = ::DLL.Link( "COMDLG32", "sys" ); GetOpenFileName = Comdlg32.GetEntry( "GetOpenFileNameW" ); #set MAX_PATH 260 #set OFN_PATHMUSTEXIST 0x00000800 #set OFN_FILEMUSTEXIST 0x00001000 FileName'USHORT( #MAX_PATH ); Filter'USHORT( 256 ); i = 0; i += Filter'puts( "ALL", i ) + 1; i += Filter'puts( "*.*", i ) + 1; i += Filter'puts( "AVI files", i ) + 1; i += Filter'puts( "*.avi", i ) + 1; i += Filter'puts( "WAV files", i ) + 1; i += Filter'puts( "*.wav", i ) + 1; OPENFILENAME ::= { .lStructSize 'ULONG; .hwndOwner 'ULONG = #NULL; .hInstance 'ULONG = #NULL; .lpstrFilter 'ULONG = Filter'addr; .lpstrCustomFilter 'ULONG = #NULL; .nMaxCustFilter 'ULONG = 0; .nFilterIndex 'ULONG = 1; .lpstrFile 'ULONG = FileName'addr; .nMaxFile 'ULONG = #MAX_PATH; .lpstrFileTitle 'ULONG = #NULL; .nMaxFileTitle 'ULONG = 0; .lpstrInitialDir 'ULONG = #NULL; .lpstrTitle 'ULONG = "RIFF ファイルの選択"'addr; .Flags 'ULONG = #OFN_PATHMUSTEXIST | #OFN_FILEMUSTEXIST; .nFileOffset 'USHORT = 0; .nFileExtension 'USHORT = 0; .lpstrDefExt 'ULONG = #NULL; .lCustData 'ULONG = 0; .lpfnHook 'ULONG = #NULL; .lpTemplateName 'ULONG = #NULL; } OPENFILENAME.lStructSize = OPENFILENAME'size; ofn = ::Buffer( OPENFILENAME.lStructSize ); ofn.Write( OPENFILENAME ); ofn.Seek(0); if( GetOpenFileName( ofn ) ) return FileName'gets; else return null; } //-----------------------------------------------------------------------------