Ignore:
Timestamp:
Oct 5, 2011, 12:40:56 PM (13 years ago)
Author:
george
Message:
  • Added: Support for play, stop, pause, seek of Windows mmsystem backend.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • CoolAudio/Systems/UAudioSystemWindows.pas

    r279 r280  
    77{$IFDEF Windows}
    88uses
    9   Classes, SysUtils, UAudioSystem, MMSystem;
     9  Windows, Classes, SysUtils, UAudioSystem, MMSystem, DateUtils;
    1010
    1111type
     12  TAudioSystemWindows = class(TAudioSystem)
     13  public
     14    PlayerIndex: Integer;
     15  end;
     16
     17  TMPDeviceTypes = (dtAutoSelect, dtAVIVideo, dtCDAudio, dtDAT, dtDigitalVideo, dtMMMovie,
     18    dtOther, dtOverlay, dtScanner, dtSequencer, dtVCR, dtVideodisc, dtWaveAudio);
    1219
    1320  { TPlayerWindows }
     
    1522  TPlayerWindows = class(TPlayer)
    1623  private
     24    FHandle: HWND;
     25    FDeviceId: MCIDEVICEID;
     26    FDeviceType: TMPDeviceTypes;
     27    FFlags: Longint;
     28    FUseNotify: Boolean;
     29    FNotify: Boolean;
     30    FUseWait: Boolean;
     31    FWait: Boolean;
     32    FAliasName: string;
     33    procedure DoClose;
     34    procedure DoOpen;
     35    procedure SetDeviceType(AValue: TMPDeviceTypes);
     36    procedure CheckError(AValue: Integer);
     37    function GetErrorMessage(Code: Integer): string;
     38    procedure SetActive(AValue: Boolean); override;
     39    procedure SetNotify(AValue: Boolean);
     40    procedure SetWait(AValue: Boolean);
     41    function GetPosition: TDateTime; override;
     42    procedure SetPosition(AValue: TDateTime); override;
     43    function GetLength: TDateTime; override;
     44  public
    1745    procedure Play; override;
    1846    procedure Pause; override;
    1947    procedure Stop; override;
     48    constructor Create; override;
     49    destructor Destroy; override;
     50    property DeviceType: TMPDeviceTypes read FDeviceType write SetDeviceType;
     51    property Handle: HWND read FHandle;
     52    property Wait: Boolean read FWait write SetWait;
     53    property Notify: Boolean read FNotify write SetNotify;
    2054  end;
    2155{$ENDIF}
    2256
     57resourcestring
     58  SMCIUnknownError = 'Unknown error code';
     59
    2360implementation
    2461
     
    2764{ TPlayerWindows }
    2865
     66procedure TPlayerWindows.SetDeviceType(AValue: TMPDeviceTypes);
     67begin
     68  if FDeviceType = AValue then Exit;
     69  FDeviceType := AValue;
     70end;
     71
     72procedure TPlayerWindows.CheckError(AValue: Integer);
     73begin
     74  if AValue <> 0 then raise Exception.Create('Error ' + IntToStr(AValue) + ': ' + GetErrorMessage(AValue));
     75end;
     76
     77function TPlayerWindows.GetErrorMessage(Code: Integer): string;
     78var
     79  ErrMsg: array[0..4095] of Char;
     80begin
     81  if not mciGetErrorString(Code, ErrMsg, SizeOf(ErrMsg)) then
     82    Result := SMCIUnknownError
     83  else SetString(Result, ErrMsg, StrLen(ErrMsg));
     84end;
     85
     86procedure TPlayerWindows.SetActive(AValue: Boolean);
     87begin
     88  if FActive = AValue then Exit;
     89  inherited SetActive(AValue);
     90  if AValue then DoOpen else DoClose;
     91end;
     92
     93procedure TPlayerWindows.SetNotify(AValue: Boolean);
     94begin
     95  if FNotify = AValue then Exit;
     96  FNotify := AValue;
     97  FUseNotify := True;
     98end;
     99
     100procedure TPlayerWindows.SetWait(AValue: Boolean);
     101begin
     102  if FWait = AValue then Exit;
     103  FWait := AValue;
     104  FUseWait := True;
     105end;
     106
     107function TPlayerWindows.GetPosition: TDateTime;
     108var
     109  Parm: TMCI_Status_Parms;
     110begin
     111  FFlags := mci_Wait or mci_Status_Item;
     112  Parm.dwItem := mci_Status_Position;
     113  CheckError(mciSendCommand(FDeviceID, mci_Status, FFlags, Longint(@Parm)));
     114  Result := Parm.dwReturn * OneMillisecond;
     115end;
     116
     117procedure TPlayerWindows.SetPosition(AValue: TDateTime);
     118var
     119  Parm: TMCI_Seek_Parms;
     120begin
     121  if FDeviceID <> 0 then begin
     122    FFlags := 0;
     123    if FUseWait then
     124    begin
     125      if FWait then FFlags := mci_Wait;
     126      FUseWait := False;
     127    end
     128    else FFlags := mci_Wait;
     129    if FUseNotify then
     130    begin
     131      if FNotify then FFlags := FFlags or mci_Notify;
     132      FUseNotify := False;
     133    end;
     134    FFlags := FFlags or mci_To;
     135    Parm.dwTo := Round(AValue / OneMillisecond);
     136    CheckError(mciSendCommand(FDeviceID, mci_Seek, FFlags, Longint(@Parm)));
     137    if FPlaying then Play;
     138  end;
     139end;
     140
     141function TPlayerWindows.GetLength: TDateTime;
     142var
     143  Parm: TMCI_Status_Parms;
     144begin
     145  FFlags := mci_Wait or mci_Status_Item;
     146  Parm.dwItem := mci_Status_Length;
     147  mciSendCommand(FDeviceID, mci_Status, FFlags, Longint(@Parm));
     148  Result := Parm.dwReturn * OneMillisecond;
     149end;
     150
    29151procedure TPlayerWindows.Play;
    30 begin
    31   PlaySound();
    32   sndPlaySound(FFileName, SND_ASYNC);
     152var
     153  Parm: TMCI_Play_Parms;
     154begin
     155  if FDeviceID = 0 then DoOpen;
     156
     157  FFlags := 0;
     158  if FUseNotify then
     159  begin
     160    if FNotify then FFlags := mci_Notify;
     161    FUseNotify := False;
     162  end else FFlags := mci_Notify;
     163  if FUseWait then
     164  begin
     165    if FWait then FFlags := FFlags or mci_Wait;
     166    FUseWait := False;
     167  end;
     168  CheckError(mciSendCommand(FDeviceID, mci_Play, FFlags, Longint(@Parm)));
     169  FPlaying := True;
    33170end;
    34171
    35172procedure TPlayerWindows.Pause;
    36 begin
    37   inherited Pause;
     173var
     174  Parm: TMCI_Generic_Parms;
     175begin
     176  if FPlaying then begin
     177    CheckError(mciSendCommand(FDeviceID, mci_Pause, FFlags, Longint(@Parm)));
     178    FPlaying := False;
     179  end else begin
     180    CheckError(mciSendCommand(FDeviceID, mci_Resume, FFlags, Longint(@Parm)));
     181    FPlaying := True;
     182  end;
    38183end;
    39184
    40185procedure TPlayerWindows.Stop;
    41 begin
    42   sndPlaySound(nil, 0);
     186var
     187  Parm: TMCI_Generic_Parms;
     188begin
     189  FFlags := 0;
     190  if FUseNotify then
     191  begin
     192    if FNotify then FFlags := mci_Notify;
     193    FUseNotify := False;
     194  end else FFlags := mci_Notify;
     195  if FUseWait then
     196  begin
     197    if FWait then FFlags := FFlags or mci_Wait;
     198    FUseWait := False;
     199  end;
     200  CheckError(mciSendCommand(FDeviceID, mci_Stop, FFlags, Longint(@Parm)));
     201  FPlaying := False;
     202end;
     203
     204constructor TPlayerWindows.Create;
     205begin
     206  inherited Create;
     207end;
     208
     209destructor TPlayerWindows.Destroy;
     210begin
     211  Active := False;
     212  inherited Destroy;
     213end;
     214
     215procedure TPlayerWindows.DoOpen;
     216const
     217  DeviceName: array[TMPDeviceTypes] of PChar = ('', 'AVIVideo', 'CDAudio', 'DAT',
     218    'DigitalVideo', 'MMMovie', 'Other', 'Overlay', 'Scanner', 'Sequencer',
     219    'VCR', 'Videodisc', 'WaveAudio');
     220var
     221  Parm: TMCI_Open_Parms;
     222begin
     223  if FDeviceId <> 0 then DoClose;
     224
     225  FillChar(Parm, SizeOf(TMCI_Open_Parms), 0);
     226  Parm.dwCallback := 0;
     227  Parm.lpstrDeviceType := DeviceName[FDeviceType];
     228  Parm.lpstrElementName := PChar(FFileName);
     229
     230  FFlags := 0;
     231
     232  if FUseWait then
     233  begin
     234    if FWait then FFlags := mci_Wait;
     235    FUseWait := False;
     236  end
     237  else
     238    FFlags := mci_Wait;
     239
     240  if FUseNotify then
     241  begin
     242    if FNotify then FFlags := FFlags or mci_Notify;
     243    FUseNotify := False;
     244  end;
     245
     246  if FDeviceType <> dtAutoSelect then
     247    FFlags := FFlags or mci_Open_Type;
     248
     249  if FDeviceType <> dtAutoSelect then
     250    FFlags := FFlags or mci_Open_Type
     251  else
     252    FFlags := FFlags or MCI_OPEN_ELEMENT;
     253
     254  //Parm.dwCallback := Handle;
     255  CheckError(mciSendCommand(0, mci_Open, FFlags, Longint(@Parm)));
     256  FDeviceID := Parm.wDeviceID;
     257  FActive := True;
     258end;
     259
     260procedure TPlayerWindows.DoClose;
     261var
     262  Parm: TMCI_Generic_Parms;
     263begin
     264  if FDeviceId <> 0 then begin
     265    FFlags := 0;
     266    if FUseWait then
     267    begin
     268      if FWait then FFlags := mci_Wait;
     269      FUseWait := False;
     270    end
     271    else FFlags := mci_Wait;
     272    if FUseNotify then
     273    begin
     274      if FNotify then FFlags := FFlags or mci_Notify;
     275      FUseNotify := False;
     276    end;
     277    CheckError(mciSendCommand(FDeviceId, mci_Close, FFlags, Longint(@Parm)));
     278    FDeviceId := 0;
     279    FActive := False;
     280  end;
    43281end;
    44282
Note: See TracChangeset for help on using the changeset viewer.