314 lines
6.8 KiB
ObjectPascal

(*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Any non-GPL usage of this software or parts of this software is strictly
* forbidden.
*
* The "appropriate copyright message" mentioned in section 2c of the GPLv2
* must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
*
*)
{$I ..\..\source\compiler.inc}
unit MainFormUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, PasLibVlcUnit;
const
PIPE_BUFF_SIZE = 1024;
type
TPipeServer = class(TThread)
private
FOverlapped : Boolean;
FStream : TStream;
FPipeName : string;
hEvent : THandle;
hPipe : THandle;
oOverlap : TOverlapped;
fPendingIO : BOOL;
dwState : DWORD;
cbToWrite : DWORD;
cbWritten : DWORD;
fSuccess : BOOL;
dwWait : DWORD;
chBuff : packed array[0..PIPE_BUFF_SIZE-1] of byte;
procedure Execute_non_overlapped();
procedure Execute_overlapped();
protected
procedure Execute(); override;
public
constructor Create(AStream : TStream; pipeName : string; AOverlapped : Boolean = TRUE);
destructor Destroy; override;
end;
type
TMainForm = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
pname : string;
stream : TFileStream;
server : TPipeServer;
p_li : libvlc_instance_t_ptr;
p_mi : libvlc_media_player_t_ptr;
public
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
constructor TPipeServer.Create(AStream : TStream; pipeName : string; AOverlapped : Boolean = TRUE);
var
dwPipeMode : DWORD;
begin
inherited Create(TRUE);
FStream := AStream;
FPipeName := pipeName;
FOverlapped := AOverlapped;
dwPipeMode := PIPE_ACCESS_OUTBOUND;
if FOverlapped then
begin
FillChar(oOverlap, sizeof(oOverlap), 0);
hEvent := CreateEvent(NIL, TRUE, TRUE, NIL);
oOverlap.hEvent := hEvent;
dwPipeMode := dwPipeMode or FILE_FLAG_OVERLAPPED;
end;
hPipe := CreateNamedPipe(
PChar(FPipeName),
dwPipeMode,
PIPE_TYPE_MESSAGE or
PIPE_WAIT,
1,
PIPE_BUFF_SIZE,
PIPE_BUFF_SIZE,
50,
NIL);
end;
destructor TPipeServer.Destroy;
begin
CloseHandle(hPipe);
if (FOverlapped) then
begin
CloseHandle(hEvent);
end;
inherited Destroy;
end;
procedure TPipeServer.Execute_non_overlapped;
var
bConn : Bool;
begin
bConn := FALSE;
while not Terminated do
begin
bConn := ConnectNamedPipe(hPipe, NIL);
if bConn then break;
if (GetLastError() = ERROR_PIPE_CONNECTED) then
begin
bConn := TRUE;
break;
end;
end;
if bConn then
begin
while not Terminated do
begin
cbToWrite := FStream.Read(chBuff, PIPE_BUFF_SIZE);
if (cbToWrite < 1) then break;
fSuccess := WriteFile(
hPipe,
chBuff,
cbToWrite,
cbWritten,
NIL);
if (not fSuccess) then break;
if (cbToWrite <> cbWritten) then break;
end;
end;
end;
procedure TPipeServer.Execute_overlapped;
begin
if (ConnectNamedPipe(hPipe, @oOverlap)) then exit;
cbToWrite := 0;
fPendingIO := FALSE;
case GetLastError() of
ERROR_IO_PENDING : fPendingIO := TRUE;
ERROR_PIPE_CONNECTED : if (not SetEvent(oOverlap.hEvent)) then exit;
end;
if (fPendingIO) then dwState := 0 else dwState := 1;
while not Terminated do
begin
dwWait := WaitForSingleObject(hEvent, 50);
if (dwWait = WAIT_TIMEOUT) then continue;
if (dwWait <> WAIT_OBJECT_0) then break;
if (fPendingIO) then
begin
fSuccess := GetOverlappedResult(hPipe, oOverlap, cbWritten, FALSE);
if not fSuccess then break;
if (dwState = 1) then
begin
if (cbWritten <> cbToWrite) then break;
end;
if (dwState = 0) then
begin
dwState := 1;
end;
end;
if (dwState = 1) then
begin
cbToWrite := FStream.Read(chBuff, PIPE_BUFF_SIZE);
if (cbToWrite < 1) then break;
fSuccess := WriteFile(
hPipe,
chBuff,
cbToWrite,
cbWritten,
@oOverlap);
if (fSuccess and (cbWritten = cbToWrite)) then
begin
fPendingIO := FALSE;
continue;
end;
if ((not fSuccess) and (GetLastError() = ERROR_IO_PENDING)) then
begin
fPendingIO := TRUE;
continue;
end;
break;
end;
end;
end;
procedure TPipeServer.Execute();
begin
if (FOverlapped) then Execute_overlapped() else Execute_non_overlapped();
end;
// =============================================================================
procedure TMainForm.FormCreate(Sender: TObject);
var
p_md : libvlc_media_t_ptr;
begin
pname := '\\.\pipe\vlcpipe' + IntToStr(Round(Now() * SecsPerDay));
stream := TFileStream.Create('..\..\_testFiles\test.ts', fmOpenRead);
server := TPipeServer.Create(stream, pname, TRUE);
libvlc_dynamic_dll_init();
if (libvlc_dynamic_dll_error <> '') then
begin
MessageDlg(libvlc_dynamic_dll_error, mtError, [mbOK], 0);
exit;
end;
with TArgcArgs.Create([
libvlc_dynamic_dll_path,
'--intf=dummy',
'--ignore-config',
'--quiet',
'--no-video-title-show',
'--no-video-on-top'
// '--vout=vdummy',
// '--aout=adummy'
]) do
begin
p_li := libvlc_new(ARGC, ARGS);
Free;
end;
p_mi := NIL;
p_md := libvlc_media_new_location(p_li, PAnsiChar('stream://\' + pname));
if (p_md <> NIL) then
begin
p_mi := libvlc_media_player_new_from_media(p_md);
if (p_mi <> NIL) then
begin
libvlc_media_player_set_display_window(p_mi, SELF.Handle);
end;
libvlc_media_player_play(p_mi);
libvlc_media_release(p_md);
end;
end;
procedure TMainForm.FormActivate(Sender: TObject);
begin
OnActivate := NIL;
Sleep(50);
server.Resume;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
server.Terminate;
server.WaitFor;
server.Free;
if (p_mi <> NIL) then
begin
libvlc_media_player_stop(p_mi);
libvlc_media_player_release(p_mi);
p_mi := NIL;
end;
if (p_li <> NIL) then
begin
libvlc_release(p_li);
p_li := NIL;
end;
stream.Free;
end;
end.