www.pudn.com > DirectShowPlayer.rar > AMPU1.PAS
// Avalon Media Player
// Copyright © 2001 Pulsar Studio / Lord Trancos.
unit AMPU1;
// --------------------------------------------------------------------
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, mmSystem, ComCtrls, Menus, Registry,
Common, Skinned, DX8DS, DirectShow;
type
TForm1 = class(TForm)
WinCapt: TImage;
ButOpen: TImage;
ButPlay: TImage;
ButPause: TImage;
ButStop: TImage;
ButClose: TImage;
OSDTime: TLabel;
Timer1: TTimer;
ButMini: TImage;
BackGround: TImage;
SldVolBack: TImage;
SldVolFore: TImage;
OSDInfo: TLabel;
SldPosBack: TImage;
SldPosFore: TImage;
ButMenu: TImage;
PopupMenu: TPopupMenu;
Menu1: TMenuItem;
N1: TMenuItem;
Menu2: TMenuItem;
ButNext: TImage;
ButPrev: TImage;
ChkLoop: TImage;
ChkAutoFS: TImage;
ChkAutoRes: TImage;
N2: TMenuItem;
Menu3: TMenuItem;
procedure hHalt(_errMsg: string);
procedure hWarning(_wrnMsg: string);
procedure WinCaptMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure PlayNextFile(_loop: boolean);
procedure PlayPrevFile;
function LoadCurrentFile: boolean;
procedure LoadAndPlay;
procedure PlayCurrentFile;
procedure PauseCurrentFile;
procedure StopCurrentFile;
procedure OpenFiles;
procedure GenericButMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
function GenericButMouseUp(Sender: TObject;
X, Y: Integer): boolean;
procedure GenericChkMouseUp(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButOpenMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButPlayMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButPauseMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButStopMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButCloseMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Timer1Timer(Sender: TObject);
procedure ButMiniMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SetWaveOutVolume(_x: longint);
function GetWaveOutVolume: longint;
procedure UpdatePositionSlider;
procedure SldVolMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SldVolMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
procedure SldPosMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure WinCaptMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure ButMenuMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Menu1Click(Sender: TObject);
procedure Menu2Click(Sender: TObject);
procedure ButNextMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure ButPrevMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Menu3Click(Sender: TObject);
procedure CreateParams(var Params: TCreateParams); override;
procedure LoadCFG;
procedure SaveCFG;
private
{ Private declarations }
procedure WMOnMove(var Msg: TMessage); message WM_MOVE;
procedure CMOpenFile(var Msg: TMessage); message CM_OPENFILE;
public
{ Public declarations }
end;
var
Form1 : TForm1;
OrgP : TPoint;
OrgXY : TPoint;
const
SKIN_FILENAME = 'ampskin.bmp';
INFODISPLAY_MAXSTRLEN = 27;
SRCPOINT_BUTOPEN : TPoint = (X: 0; Y: 94);
SRCPOINT_BUTPREV : TPoint = (X: 18; Y: 94);
SRCPOINT_BUTPLAY : TPoint = (X: 36; Y: 94);
SRCPOINT_BUTPAUSE : TPoint = (X: 54; Y: 94);
SRCPOINT_BUTSTOP : TPoint = (X: 72; Y: 94);
SRCPOINT_BUTNEXT : TPoint = (X: 90; Y: 94);
SRCPOINT_BUTMENU : TPoint = (X: 149; Y: 94);
SRCPOINT_BUTCLOSE : TPoint = (X: 169; Y: 94);
SRCPOINT_BUTMINI : TPoint = (X: 189; Y: 94);
SRCPOINT_CHKLOOP : TPoint = (X: 211; Y: 94);
SRCPOINT_CHKAUTOFS : TPoint = (X: 225; Y: 94);
SRCPOINT_CHKAUTORES : TPoint = (X: 239; Y: 94);
SRCPOINT_BACKGROUND : TPoint = (X: 0; Y: 0);
SRCPOINT_SLDVOLFORE : TPoint = (X: 109; Y: 94);
SRCPOINT_SLDPOSFORE : TPoint = (X: 0; Y: 84);
ERRXX = 'Error';
ERR00 = 'Can not initialize skin engine.';
ERR01 = 'Error loading skin file: ';
ERR02 = 'Not enough memory.';
WRNXX = 'Error';
WRN00 = 'File not found: ';
WRN01 = 'Error loading file: ';
MSC00 = 'paused';
MSC01 = '[%s] ';
MSC02 = ' %s || %d x %d || %.2f FPS || %d kbits/sec. ';
// -------------------------------------------------------------------
implementation
uses AMPU2, AMPU3;
{$R *.DFM}
// -------------------------------------------------------------------
procedure TForm1.hHalt(_errMsg: string);
begin
MessageBox(Handle, pChar(_errMsg), ERRXX, MB_ICONERROR);
Application.Terminate;
end;
// -------------------------------------------------------------------
procedure TForm1.hWarning(_wrnMsg: string);
begin
MessageBox(Handle, pChar(_wrnMsg), WRNXX, MB_ICONWARNING);
end;
// --------------------------------------------------------------------
procedure TForm1.WMOnMove(var Msg: TMessage);
begin
inherited;
if (Assigned(Form2)) then
begin
Form2.Left := Left;
Form2.Top := Top + Height;
end;
end;
// --------------------------------------------------------------------
procedure TForm1.CMOpenFile(var Msg: TMessage);
var _param1 : string;
_len : longint;
begin
if Msg.WParam <> 0 then
begin
// Get string and remove atom.
SetLength(_param1, 255);
_len := GlobalGetAtomName(Msg.wParam, @_param1[1], 255);
SetLength(_param1, _len);
GlobalDeleteAtom(Msg.WParam);
// Show window.
if IsIconic(Application.Handle)
then Application.Restore
else Application.BringToFront;
// Run parameter.
Form2.RunFN(_param1);
end;
end;
// --------------------------------------------------------------------
procedure TForm1.LoadCFG;
var _reg : TRegistry;
_str : string[3];
begin
// Create TRegistry.
try _reg := tRegistry.Create; except exit; end;
// Open key.
_reg.RootKey := HKEY_CURRENT_USER;
if _reg.OpenKey(REG_KEY00, false) then
begin
// Read string.
try _str := _reg.ReadString(''); except end;
// Set CFG
skinChecked(chkLoop, (_str[1] = 'x'));
skinChecked(chkAutoFS, (_str[2] = 'x'));
skinChecked(chkAutoRes, (_str[3] = 'x'));
end;
// Close registry
_reg.CloseKey;
_reg.Free;
end;
// --------------------------------------------------------------------
procedure TForm1.SaveCFG;
var _reg : TRegistry;
_str : string[3];
begin
// Prepare data.
_str := ' ';
if skinImgChecked(chkLoop) then _str[1] := 'x';
if skinImgChecked(chkAutoFS) then _str[2] := 'x';
if skinImgChecked(chkAutoRes) then _str[3] := 'x';
// Create TRegistry.
try _reg := tRegistry.Create; except exit; end;
// Open key.
_reg.RootKey := HKEY_CURRENT_USER;
if _reg.OpenKey(REG_KEY00, true) then
try _reg.WriteString('', _str); except end; // Write string.
// Close registry
_reg.CloseKey;
_reg.Free;
end;
// --------------------------------------------------------------------
function MSecToStr(_msec: Comp): string;
var _timeStamp : TTimeStamp;
_dateTime : TDateTime;
begin
_timeStamp := MSecsToTimeStamp(_msec);
_timeStamp.Date := 1;
_dateTime := TimeStampToDateTime(_timeStamp);
Result := TimeToStr(_dateTime);
end;
// --------------------------------------------------------------------
procedure TForm1.WinCaptMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
OrgP := Point(Left, Top);
OrgXY := ClientToScreen(Point(X, Y));
end;
// --------------------------------------------------------------------
procedure TForm1.WinCaptMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
var _p : TPoint;
begin
if (Shift = [ssLeft]) then
begin
_p := ClientToScreen(Point(X, Y));
SetBounds(OrgP.X + (_p.X - OrgXY.X),
OrgP.Y + (_p.Y - OrgXY.Y), Width, Height);
end;
end;
// -------------------------------------------------------------------
procedure TForm1.PlayNextFile(_loop: boolean);
begin
if Form3.ListBox1.Items.Count = 0 then exit;
CurrentIdx := CurrentIdx + 1;
if CurrentIdx >= Form3.ListBox1.Items.Count then
if _loop then CurrentIdx := 0 else exit;
CurrentFile := Form3.ListBox1.Items[CurrentIdx];
Form3.Listbox1.Repaint;
LoadAndPlay;
end;
// --------------------------------------------------------------------
procedure TForm1.PlayPrevFile;
begin
if Form3.ListBox1.Items.Count = 0 then exit;
CurrentIdx := (CurrentIdx - 1);
if CurrentIdx < 0 then CurrentIdx := Form3.ListBox1.Items.Count - 1;
CurrentFile := Form3.ListBox1.Items[CurrentIdx];
Form3.Listbox1.Repaint;
LoadAndPlay;
end;
// --------------------------------------------------------------------
procedure TForm1.GenericButMouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
skinImgSetCellAndUpdate(TImage(Sender), 1);
Application.ProcessMessages;
end;
// --------------------------------------------------------------------
function TForm1.GenericButMouseUp(Sender: TObject;
X, Y: Integer): boolean;
begin
skinImgSetCellAndUpdate(TImage(Sender), 0);
Application.ProcessMessages;
Result := skinImgInside(TImage(Sender), X, Y);
end;
// --------------------------------------------------------------------
procedure TForm1.GenericChkMouseUp(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var _val : byte;
begin
// change value
_val := skinImgGetValue(TImage(Sender));
if skinImgInside(TImage(Sender), X, Y) then
if _val = SKIN_CHKVAL_FALSE
then _val := SKIN_CHKVAL_TRUE
else _val := SKIN_CHKVAL_FALSE;
skinImgSetValue(TImage(Sender), _val);
// display
if _val = SKIN_CHKVAL_FALSE
then skinImgSetCellAndUpdate(TImage(Sender), 0)
else skinImgSetCellAndUpdate(TImage(Sender), 2);
Application.ProcessMessages;
end;
// --------------------------------------------------------------------
procedure TForm1.PlayCurrentFile;
begin
Player.MediaControl.Run;
PlayState := STATE_PLAY;
end;
// --------------------------------------------------------------------
procedure TForm1.PauseCurrentFile;
begin
case PlayState of
STATE_PLAY:
begin
Player.MediaControl.Pause;
PlayState := STATE_PAUSE;
end;
STATE_PAUSE: PlayCurrentFile;
end;
end;
// --------------------------------------------------------------------
procedure TForm1.StopCurrentFile;
begin
if Player.Initialized then
begin
CurrPos := 0;
Player.MediaControl.Stop;
dsmpSetPos(Player, 0);
PlayState := STATE_STOP;
end;
end;
// --------------------------------------------------------------------
procedure TForm1.OpenFiles;
var _idx : longint;
begin
_idx := Form3.AddFilesToPlayList(true);
if _idx > -1 then
begin
CurrentIdx := _idx;
CurrentFile := Form3.ListBox1.Items[CurrentIdx];
Form3.Listbox1.Repaint;
LoadAndPlay;
end;
end;
// --------------------------------------------------------------------
function TForm1.LoadCurrentFile: boolean;
begin
Result := false;
// Stop playing.
if (Player.Initialized) and (PlayState <> STATE_STOP)
then StopCurrentFile;
// Free player.
dsmpFree(Player);
// Load current file.
if (CurrentFile <> '') then
begin
// File exists ?
if not fileexists(CurrentFile) then
begin hWarning(WRN00 + CurrentFile); exit; end;
// Load.
if not dsmpLoadFile(Player, CurrentFile) then
begin
dsmpFree(Player);
hWarning(WRN01 + CurrentFile);
exit;
end;
// Set Info text.
OSDInfoTxt := Format(MSC01, [ExtractFileName(CurrentFile)]);
// Set time format.
Player.MediaSeeking.SetTimeFormat(TIME_FORMAT_MEDIA_TIME);
// Get duration.
Player.MediaSeeking.GetDuration(Duration);
DurationStr := MSecToStr(Duration div 10000);
OSDTime.Hint := DurationStr;
// Has video ?
if dsmpVideoAvail(Player) then with Player do
begin
// Resize our video window.
if skinImgChecked(ChkAutoRes) then
begin
Form2.ClientWidth := VideoWidth;
Form2.ClientHeight := VideoHeight;
end;
// Set file info.
Form2.VideoInfo.SimpleText := Format(MSC02, [DurationStr,
VideoWidth, VideoHeight,
VideoFPS,
VideoBitRate shr 10]);
// Adjust true video window.
dsmpSetVWAsChild(Player, Form2.VideoDisplay.Handle,
DSVIDEO_WINDOW_CHILD_STYLE);
VideoWindow.SetWindowPosition(0, 0, Form2.ClientWidth,
Form2.ClientHeight);
Application.ProcessMessages;
Form2.Visible := true;
if IsWindowVisible(Form1.Handle) then Form2.PlaceWindow;
Application.ProcessMessages;
if skinImgChecked(ChkAutoFS) then
begin
Player.VideoWindow.SetWindowForeground(-1);
Player.VideoWindow.put_FullScreenMode(true);
end;
end else Form2.Visible := false;
// All right.
Result := true;
end;
// Check Form1 visibility
if (not Visible) and (Player.Initialized) and
(not dsmpVideoAvail(Player)) then Visible := true;
end;
// --------------------------------------------------------------------
procedure TForm1.SetWaveOutVolume(_x: longint);
var _value : longint;
_volume : dWord;
begin
if (_x < 0) then _x := 0;
if (_x > SldVolBack.Width) then _x := SldVolBack.Width;
_value := ($FFFF * _x) div SldVolBack.Width;
_volume := _value shl 16 + _value;
waveOutSetVolume(0, _volume);
SldVolFore.Width := _x;
end;
// --------------------------------------------------------------------
function TForm1.GetWaveOutVolume: longint;
var _value : longint;
_volume : dWord;
begin
waveOutGetVolume(0, @_volume);
_value := ((_volume shr 16 and $FFFF) + (_volume and $FFFF)) shr 1;
Result := (_value * SldVolBack.Width) div $FFFF;
end;
// --------------------------------------------------------------------
procedure TForm1.UpdatePositionSlider;
begin
if (Player.Initialized)
then SldPosFore.Width := (SldPosBack.Width * CurrPos) div Duration;
end;
// --------------------------------------------------------------------
procedure TForm1.LoadAndPlay;
begin
if (LoadCurrentFile) then PlayCurrentFile;
end;
// --------------------------------------------------------------------
procedure TForm1.ButOpenMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then OpenFiles;
end;
// --------------------------------------------------------------------
procedure TForm1.ButPlayMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then
if Player.Initialized then PlayCurrentFile else PlayNextFile(false);
end;
// --------------------------------------------------------------------
procedure TForm1.ButPauseMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then
if Player.Initialized then PauseCurrentFile;
end;
// --------------------------------------------------------------------
procedure TForm1.ButStopMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then
if Player.Initialized then StopCurrentFile;
end;
// --------------------------------------------------------------------
procedure TForm1.ButNextMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then
if Player.Initialized then PlayNextFile(true);
end;
// --------------------------------------------------------------------
procedure TForm1.ButPrevMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then
if Player.Initialized then PlayPrevFile;
end;
// --------------------------------------------------------------------
procedure TForm1.ButCloseMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then Close;
end;
// --------------------------------------------------------------------
procedure TForm1.ButMiniMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then Application.Minimize;
end;
// --------------------------------------------------------------------
procedure TForm1.ButMenuMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if GenericButMouseUp(Sender, X, Y) then PopupMenu.Popup(Left, Top);
end;
// --------------------------------------------------------------------
procedure TForm1.SldVolMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then SetWaveOutVolume(X);
end;
// --------------------------------------------------------------------
procedure TForm1.SldPosMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var _pos : int64;
begin
if (Button = mbLeft) and (Player.Initialized) and (PlayState <> STATE_STOP) then
begin
if (X < 0) then X := 0;
if (X > SldPosBack.Width) then X := SldPosBack.Width;
_pos := (X * Duration) div SldPosBack.Width;
dsmpSetPos(Player, _pos);
end;
end;
// --------------------------------------------------------------------
procedure TForm1.SldVolMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
if Shift = [ssLeft] then SetWaveOutVolume(X);
end;
// --------------------------------------------------------------------
procedure TForm1.Menu1Click(Sender: TObject);
// About
begin
ShowMessage(ABOUT);
end;
// --------------------------------------------------------------------
procedure TForm1.Menu2Click(Sender: TObject);
// Playlist editor.
begin
Form3.Visible := not Form3.Visible;
end;
// --------------------------------------------------------------------
procedure TForm1.Menu3Click(Sender: TObject);
// Exit.
begin
Close;
end;
// --------------------------------------------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);
var _str : string;
begin
// Get Position.
if (Player.Initialized)
then Player.MediaSeeking.GetCurrentPosition(CurrPos)
else CurrPos := 0;
// Check EOF
if (Player.Initialized) and (PlayState = STATE_PLAY) and
(CurrPos >= Duration) then
begin
StopCurrentFile;
PlayNextFile(skinImgChecked(ChkLoop));
end;
// Update position.
UpdatePositionSlider;
// Update info display.
if (Length(OSDInfoTxt) > INFODISPLAY_MAXSTRLEN) then
begin
SetLength(_str, Length(OSDInfoTxt));
Move(OSDInfoTxt[2], _str[1], Length(OSDInfoTxt)-1);
_str[length(_str)] := OSDInfoTxt[1];
OSDInfoTxt := _str;
end;
OSDInfo.Caption := OSDInfoTxt;
if Player.Initialized then
begin
// Update time display.
if PlayState <> STATE_PAUSE
then OSDTime.Caption := MSecToStr(CurrPos div 10000)
else OSDTime.Caption := MSC00;
end else begin
OSDTime.Hint := '';
OSDTime.Caption := '';
end;
end;
// --------------------------------------------------------------------
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName := WINDOWCLASSNAME;
end;
// --------------------------------------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.Title := TITLE;
Left := (Screen.Width shr 1) - (Width shr 1) - 1;
Top := (Screen.Height shr 1) - (Height shr 1) - 1;
// DirectX (DirectShow)
dsmpReset(Player);
// Skin
if not skinInit then begin hHalt(ERR00); exit; end;
if not skinLoad(ExtractFilePath(paramstr(0))+ SKIN_FILENAME) then
begin hHalt(ERR01 + SKIN_FILENAME); exit; end;
if (not skinImgInitAndUpdate(ButOpen, SRCPOINT_BUTOPEN)) or
(not skinImgInitAndUpdate(ButPlay, SRCPOINT_BUTPLAY)) or
(not skinImgInitAndUpdate(ButPause, SRCPOINT_BUTPAUSE)) or
(not skinImgInitAndUpdate(ButStop, SRCPOINT_BUTSTOP)) or
(not skinImgInitAndUpdate(ButPrev, SRCPOINT_BUTPREV)) or
(not skinImgInitAndUpdate(ButNext, SRCPOINT_BUTNEXT)) or
(not skinImgInitAndUpdate(ButClose, SRCPOINT_BUTCLOSE)) or
(not skinImgInitAndUpdate(ButMini, SRCPOINT_BUTMINI)) or
(not skinImgInitAndUpdate(ButMenu, SRCPOINT_BUTMENU)) or
(not skinImgInitAndUpdate(ChkLoop, SRCPOINT_CHKLOOP)) or
(not skinImgInitAndUpdate(ChkAutoFS, SRCPOINT_CHKAUTOFS)) or
(not skinImgInitAndUpdate(ChkAutoRes, SRCPOINT_CHKAUTORES)) or
(not skinImgInitAndUpdate(BackGround, SRCPOINT_BACKGROUND)) or
(not skinImgInitAndUpdate(SldVolFore, SRCPOINT_SLDVOLFORE)) or
(not skinImgInitAndUpdate(SldPosFore, SRCPOINT_SLDPOSFORE))
then begin hHalt(ERR02); exit; end;
skinChecked(ChkLoop, true); // Loop enabled by default.
skinChecked(ChkAutoRes, true); // Auto resize enabled by default.
SldPosFore.Width := 0;
SldVolFore.Width := GetWaveOutVolume;
LoadCFG; // Load config.
end;
// --------------------------------------------------------------------
procedure TForm1.FormDestroy(Sender: TObject);
begin
// Stop
if (Player.Initialized) and (PlayState <> STATE_STOP)
then StopCurrentFile;
// Save config.
SaveCFG;
// Free Skin
skinClose;
// DirectX (DirectShow)
dsmpFree(Player);
end;
// --------------------------------------------------------------------
end.