1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
| unit Unit1;
{
This demo shows how to play AVI video from memory using
the mciSendCommand and mmio functions
Date: 17 Oct 2003
(c) Nils Haeck www.simdesign.nl
}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, MMSystem, ExtCtrls;
type
TForm1 = class(TForm)
edFilename: TEdit;
Label1: TLabel;
btnPick: TButton;
btnOpen: TButton;
btnPlay: TButton;
lbDeviceID: TLabel;
Panel1: TPanel;
procedure btnPickClick(Sender: TObject);
procedure btnOpenClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnPlayClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FIsOpened: boolean;
FDeviceID: Word;
public
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
// Global memory pointer - for now
var
FMem: pointer = nil;
FSize: integer = 0;
FOpened: boolean = False;
const
FFourCC = 'IOCB'; // acronym for IO CallBack (but it really does not matter - choose as you wish)
function MyIOCallback(lpmmioinfo: PChar; uMessage: UINT; lParam1, lParam2: LPARAM): Longint stdcall;
// This function is called and will provide access to the file. The MM system "thinks"
// this is a file, while we use the global memory stream.
var
AInfo: pmmioInfo;
begin
AInfo := pmmioInfo(lpmmioinfo);
case uMessage of
MMIOM_OPEN:
// Open the "file"
begin
if FOpened then begin
Result := 0;
exit;
end;
FOpened := True;
AInfo.lDiskOffset := 0;
Result := 0;
end;
MMIOM_CLOSE:
// Close the "file"
Result := 0;
MMIOM_READ:
// Read data from the "file"
begin
// Copy from memory - no checking
Move(pointer(integer(FMem) + AInfo.lDiskOffset)^, pointer(lParam1)^, lParam2);
AInfo.lDiskOffset := AInfo.lDiskOffset + lParam2;
Result := lParam2;
end;
MMIOM_SEEK:
// Seek new position in the "file"
begin
case lParam2 of
// From beginning:
0: AInfo.lDiskOffset := lParam1;
// From current:
1: AInfo.lDiskOffset := AInfo.lDiskOffset + lParam1;
// From end:
2: AInfo.lDiskOffset := FSize - 1 - lParam1;
end;
Result := AInfo.lDiskOffset;
end;
else
// Unexpected msgs. For instance, we do not process MMIOM_WRITE in this sample
Result := -1;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
// Setup mmio callback
if not assigned(mmioInstallIOProc(mmioStringToFourCC(FFou rCC, 0), @MyIOCallback, MMIO_INSTALLPROC or MMIO_GLOBALPROC)) then
ShowMessage('Could not install IO proc');
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
GenParm: TMCI_Generic_Parms;
begin
// Close MCI
if FIsOpened then begin
GenParm.dwCallback := Handle;
mciSendCommand(FDeviceID, mci_Close, 0, Longint(@GenParm));
FIsOpened := False;
end;
// remove mmio callback
mmioInstallIOProc(mmioStringToFourCC(FFourCC, 0), nil, MMIO_REMOVEPROC);
// Free globally assigned memory
if assigned(FMem) then FreeMem(FMem);
end;
procedure TForm1.btnPickClick(Sender: TObject);
begin
with TOpendialog.Create(nil) do
try
Title := 'Open MP3 file';
Filter := 'Multimedia files|*.mp3;*.avi;*.mpg';
if Execute then
edFilename.Text := FileName;
finally
Free;
end;
end;
procedure TForm1.btnOpenClick(Sender: TObject);
var
S: TStream;
OpenParm: TMCI_Open_Parms;
GenParm: TMCI_Generic_Parms;
FFlags: Longint;
FError: Longint;
ErrMsg: array[0..4095] of Char;
AError: string;
begin
// Open the file
S := TFileStream.Create(edFilename.Text, fmOpenRead or fmShareDenyNone);
try
if assigned(FMem) then FreeMem(FMem);
if FIsOpened then begin
GenParm.dwCallback := Handle;
mciSendCommand(FDeviceID, mci_Close, 0, Longint(@GenParm));
FIsOpened := False;
end;
// Copy to global memory
FSize := S.Size;
GetMem(FMem, FSize);
S.Read(FMem^, FSize);
finally
S.Free;
end;
// Now try the media player .. see if it wants to play from memory
FillChar(OpenParm, SizeOf(TMCI_Open_Parms), 0);
// Open a specific device type - obviously, and unfortunately,
// the memory play function does NOT work for mpegvideo.
// OpenParm.lpstrDeviceType := 'mpegvideo'; // does not work
OpenParm.lpstrDeviceType := 'avivideo';
// Set the name of the file with extension .IOCB+ to invoke our own
// I/O callbacks. This way the file is read from memory
OpenParm.lpstrElementName := 'test.IOCB+';
// OpenParm.lpstrElementName := PChar(edFilename.Text); // alternative, directly read file
OpenParm.dwCallback := Handle;
FFlags := mci_Open_Type or MCI_OPEN_ELEMENT;
FError := mciSendCommand(0, mci_Open, FFlags, Longint(@OpenParm));
if FError <> 0 then begin
// problem opening device
if not mciGetErrorString(FError, ErrMsg, SizeOf(ErrMsg)) then
AError := 'Unknown error'
else
SetString(AError, ErrMsg, StrLen(ErrMsg));
lbDeviceID.Caption := AError;
end else begin
// device successfully opened
FIsOpened := True;
FDeviceID := OpenParm.wDeviceID;
// Display device ID
lbDeviceID.Caption := Format('Device ID: %d', [FDeviceID]);
end;
end;
procedure TForm1.btnPlayClick(Sender: TObject);
var
PlayParm: TMCI_Play_Parms;
AWindowParm: TMCI_Anim_Window_Parms;
FError: Longint;
begin
if not FIsOpened then exit;
AWindowParm.Wnd := Longint(Panel1.Handle);
FError := mciSendCommand(FDeviceID, mci_Window, mci_Wait or mci_Anim_Window_hWnd, Longint(@AWindowParm) );
// play
PlayParm.dwCallback := Handle;
FError := mciSendCommand(FDeviceID, mci_Play, 0, Longint(@PlayParm));
end;
end. |
Partager