CEF4Delphi/demos/Delphi_VCL/MediaRouter/uMediaRouterFrm.pas

796 lines
22 KiB
ObjectPascal
Raw Normal View History

// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
// https://www.briskbard.com/index.php?lang=en&pageid=cef
//
// Copyright <20> 2020 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
* Delphi Chromium Embedded 3
*
* Usage allowed under the restrictions of the Lesser GNU General Public License
* or alternatively the restrictions of the Mozilla Public License 1.1
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* Unit owner : Henri Gourvest <hgourvest@gmail.com>
* Web site : http://www.progdigy.com
* Repository : http://code.google.com/p/delphichromiumembedded/
* Group : http://groups.google.com/group/delphichromiumembedded
*
* Embarcadero Technologies, Inc is not permitted to use or redistribute
* this source code without explicit permission.
*
*)
unit uMediaRouterFrm;
{$I cef.inc}
interface
uses
{$IFDEF DELPHI16_UP}
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Menus,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, System.Types, Vcl.ComCtrls, Vcl.ClipBrd,
System.UITypes, Vcl.AppEvnts, Winapi.ActiveX, Winapi.ShlObj, System.SyncObjs,
{$ELSE}
Windows, Messages, SysUtils, Variants, Classes, Graphics, Menus,
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd,
AppEvnts, ActiveX, ShlObj, SyncObjs,
{$ENDIF}
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants,
uCEFWinControl, uCEFSentinel, uCEFChromiumCore;
const
MEDIA_ROUTER_PENDING_LOG_LINES = WM_APP + $B00;
MEDIA_ROUTER_REFRESH_SINKS = WM_APP + $B01;
MEDIA_ROUTER_REFRESH_ROUTES = WM_APP + $B02;
MEDIA_ROUTER_UPDATE_BUTTONS = WM_APP + $B03;
type
TMediaRouterFrm = class(TForm)
Chromium1: TChromium;
CEFWindowParent1: TCEFWindowParent;
Timer1: TTimer;
MainPnl: TPanel;
SinksGbx: TGroupBox;
SinksLbx: TListBox;
SinksButtonsPnl: TPanel;
CreateRouteBtn: TButton;
CentralPnl: TPanel;
SourcePnl: TPanel;
SourceLblPnl: TPanel;
SourceURNLbl: TLabel;
RoutesGbx: TGroupBox;
RoutesLbx: TListBox;
RoutesButtonPnl: TPanel;
TerminateRouteBtn: TButton;
MessageGbx: TGroupBox;
SendMessagePnl: TPanel;
SendMsgBtn: TButton;
MessageMem: TMemo;
LogGbx: TGroupBox;
LogMem: TMemo;
SpacerPnl: TPanel;
NotifySinksBtn: TButton;
NotifyRoutesBtn: TButton;
ClearLogPnl: TPanel;
ClearLogBtn: TButton;
SourceURNCbx: TComboBox;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
procedure Chromium1Sinks(Sender: TObject; const sinks: TCefMediaSinkArray);
procedure Chromium1Routes(Sender: TObject; const routes: TCefMediaRouteArray);
procedure Chromium1RouteStateChanged(Sender: TObject; const route: ICefMediaRoute; state: TCefMediaRouteConnectionState);
procedure Chromium1RouteMessageReceived(Sender: TObject; const route: ICefMediaRoute; const message_: ustring);
procedure Chromium1MediaRouteCreateFinished(Sender: TObject; result: Integer; const error: ustring; const route: ICefMediaRoute);
procedure Timer1Timer(Sender: TObject);
procedure SourceURNEdtChange(Sender: TObject);
procedure SinksLbxClick(Sender: TObject);
procedure CreateRouteBtnClick(Sender: TObject);
procedure TerminateRouteBtnClick(Sender: TObject);
procedure SendMsgBtnClick(Sender: TObject);
procedure NotifySinksBtnClick(Sender: TObject);
procedure NotifyRoutesBtnClick(Sender: TObject);
procedure ClearLogBtnClick(Sender: TObject);
2020-04-21 13:27:34 +02:00
procedure MessageMemChange(Sender: TObject);
procedure RoutesLbxClick(Sender: TObject);
protected
// Variables to control when can we destroy the form safely
FCanClose : boolean; // Set to True in TChromium.OnBeforeClose
FClosing : boolean; // Set to True in the CloseQuery event.
FMediaCS : TCriticalSection;
FLog : TStringList;
FSinks : TCefMediaSinkInfoArray;
FRoutes : TCefMediaRouteInfoArray;
procedure BrowserDestroyMsg(var aMessage : TMessage); message CEF_DESTROY;
procedure PendingLogLinesMsg(var aMessage : TMessage); message MEDIA_ROUTER_PENDING_LOG_LINES;
procedure RefreshSinksMsg(var aMessage : TMessage); message MEDIA_ROUTER_REFRESH_SINKS;
procedure RefreshRoutesMsg(var aMessage : TMessage); message MEDIA_ROUTER_REFRESH_ROUTES;
procedure UpdateButtonsMsg(var aMessage : TMessage); message MEDIA_ROUTER_UPDATE_BUTTONS;
procedure DestroySinksArray;
procedure DestroyRoutesArray;
procedure DestroyAllArrays;
procedure CopySinksArray(const aSinks : TCefMediaSinkArray);
procedure CopyRoutesArray(const aRoutes : TCefMediaRouteArray);
procedure UpdateAvailableSinks;
procedure UpdateAvailableRoutes;
procedure UpdateButtons;
2020-04-21 13:27:34 +02:00
procedure AppendPendingLogStrings;
procedure AddLogEntry(const aMessage1, aMessage2 : string; aRec : boolean); overload;
procedure AddLogEntry(const aMessage1 : string; const aMessage2 : string = ''); overload;
end;
var
MediaRouterFrm: TMediaRouterFrm;
procedure CreateGlobalCEFApp;
implementation
{$R *.dfm}
uses
{$IFDEF DELPHI16_UP}
System.Math,
{$ELSE}
Math,
{$ENDIF}
uCEFMiscFunctions;
// This demo can use a MediaRouter to communicate with devices on the local
// network via the CAST and DIAL protocols.
// TChromium exposes all the ICefMediaObserver events and the ICefMediaRouter
// methods to show the available devices, to established communication routes
// and to send messages to those devices.
// Follow these steps to test this demo :
// STEP 1
// ------
// Turn on your ChromeCast receiver. It can be an Android TV or similar device
// like a Xiaomi MiBox. It must be on the same local network as the computer
// running this demo.
// STEP 2
// ------
// Run this demo and wait a few seconds. It will show all the available devices
// in the local network and the protocol used to communicate with them.
// In the case of the MiBox device it shows a DIAL and a CAST "sink" but after
// a couple of secods the list is updated and it only shows the CAST sink.
// STEP 3
// ------
// Select the CAST sink and click on the "Create route" button. This button will
// use the "Source URN" value to create the route and that value has a CAST URN
// with the "Application ID" of the "Default Media Receiver", which is CC1AD845.
// This ID can be used for tests.
// STEP 4
// ------
// The "Established routes" box will show the routes that you created.
// STEP 5
// ------
// Select the route, type the message and click on the "Send message" button.
// STEP 6
// ------
// Click on the "Terminate route" button.
// WARNING
// =======
// This demo has a known bug when you close the form and it will crash.
// References :
// ============
// https://bitbucket.org/chromiumembedded/cef/issues/2900/add-mediarouter-support-for-cast-receiver
// https://blog.oakbits.com/google-cast-protocol-overview.html
// https://developers.google.com/cast/docs/developers
// https://gist.github.com/jloutsenhizer/8855258
procedure CreateGlobalCEFApp;
begin
GlobalCEFApp := TCefApplication.Create;
GlobalCEFApp.LogFile := 'debug.log';
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
end;
procedure TMediaRouterFrm.Chromium1AfterCreated(Sender: TObject;
const browser: ICefBrowser);
begin
AddLogEntry('Browser initialized.');
end;
procedure TMediaRouterFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser);
begin
FCanClose := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end;
procedure TMediaRouterFrm.Chromium1Close(Sender: TObject;
const browser: ICefBrowser; var aAction: TCefCloseBrowserAction);
begin
PostMessage(Handle, CEF_DESTROY, 0, 0);
aAction := cbaDelay;
end;
procedure TMediaRouterFrm.Chromium1MediaRouteCreateFinished(Sender: TObject;
result: Integer; const error: ustring; const route: ICefMediaRoute);
var
TempMsg, TempID : string;
begin
TempMsg := '';
try
FMediaCS.Acquire;
if (result = CEF_MRCR_OK) then
begin
TempMsg := 'Route created';
2020-04-21 13:27:34 +02:00
if (route <> nil) then TempID := 'Route ID : ' + route.ID;
end
else
TempMsg := error;
finally
FMediaCS.Release;
if (length(TempMsg) > 0) then AddLogEntry(TempID, TempMsg);
2020-04-21 13:27:34 +02:00
PostMessage(Handle, MEDIA_ROUTER_UPDATE_BUTTONS, 0, 0);
end;
end;
procedure TMediaRouterFrm.Chromium1RouteMessageReceived(Sender: TObject;
const route: ICefMediaRoute; const message_: ustring);
var
TempID : string;
begin
if (route <> nil) then
2020-04-21 13:27:34 +02:00
TempID := 'Route ID : ' + route.ID;
2020-04-21 13:27:34 +02:00
AddLogEntry(TempID, 'Message contents : ' + message_, True);
end;
procedure TMediaRouterFrm.Chromium1Routes(Sender: TObject;
const routes: TCefMediaRouteArray);
begin
CopyRoutesArray(routes);
end;
procedure TMediaRouterFrm.Chromium1RouteStateChanged(Sender: TObject;
const route: ICefMediaRoute; state: TCefMediaRouteConnectionState);
var
TempMsg, TempID : string;
begin
2020-04-21 13:27:34 +02:00
if (route <> nil) then TempID := 'Route ID : ' + route.ID;
case state of
2020-04-21 13:27:34 +02:00
CEF_MRCS_CONNECTING : TempMsg := 'Route state : Connecting.';
CEF_MRCS_CONNECTED : TempMsg := 'Route state : Connected.';
CEF_MRCS_CLOSED : TempMsg := 'Route state : Closed.';
CEF_MRCS_TERMINATED : TempMsg := 'Route state : Terminated.';
else TempMsg := 'Route state : Unknown.';
end;
TempMsg := TempMsg + ' ' + dateTimeToStr(now);
AddLogEntry(TempID, TempMsg);
end;
procedure TMediaRouterFrm.Chromium1Sinks(Sender: TObject;
const sinks: TCefMediaSinkArray);
begin
CopySinksArray(sinks);
end;
procedure TMediaRouterFrm.ClearLogBtnClick(Sender: TObject);
begin
LogMem.Lines.Clear;
end;
procedure TMediaRouterFrm.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
CanClose := FCanClose;
if not(FClosing) then
begin
FClosing := True;
Visible := False;
DestroyAllArrays;
Chromium1.CloseBrowser(True);
end;
end;
procedure TMediaRouterFrm.FormCreate(Sender: TObject);
begin
FCanClose := False;
FClosing := False;
FSinks := nil;
FRoutes := nil;
FMediaCS := TCriticalSection.Create;
FLog := TStringList.Create;
end;
procedure TMediaRouterFrm.FormDestroy(Sender: TObject);
begin
FLog.Free;
FMediaCS.Free;
end;
procedure TMediaRouterFrm.FormShow(Sender: TObject);
begin
UpdateButtons;
if not(Chromium1.CreateBrowser(CEFWindowParent1)) then
Timer1.Enabled := True;
end;
2020-04-21 13:27:34 +02:00
procedure TMediaRouterFrm.MessageMemChange(Sender: TObject);
begin
UpdateButtons;
end;
procedure TMediaRouterFrm.NotifyRoutesBtnClick(Sender: TObject);
begin
Chromium1.NotifyCurrentRoutes;
end;
procedure TMediaRouterFrm.NotifySinksBtnClick(Sender: TObject);
begin
Chromium1.NotifyCurrentSinks;
end;
procedure TMediaRouterFrm.SendMsgBtnClick(Sender: TObject);
var
TempMsg, TempID : string;
begin
TempMsg := '';
try
FMediaCS.Acquire;
if (RoutesLbx.Items.Count > 0) and
(FRoutes <> nil) and
(RoutesLbx.ItemIndex >= 0) and
(RoutesLbx.ItemIndex < length(FRoutes)) and
(MessageMem.Lines.Count > 0) then
begin
TempMsg := trim(MessageMem.Lines.Text);
if (length(TempMsg) > 0) and
(FRoutes[RoutesLbx.ItemIndex].RouteIntf <> nil) then
try
2020-04-21 13:27:34 +02:00
TempID := 'Route ID : ' + FRoutes[RoutesLbx.ItemIndex].RouteIntf.ID;
FRoutes[RoutesLbx.ItemIndex].RouteIntf.SendRouteMessage(TempMsg);
2020-04-21 13:27:34 +02:00
TempMsg := 'Message contents : ' + TempMsg;
except
on e : exception do
if CustomExceptionHandler('TMediaRouterFrm.SendMsgBtnClick', e) then raise;
end;
end;
finally
FMediaCS.Release;
if (length(TempMsg) > 0) then AddLogEntry(TempID, TempMsg, False);
end;
end;
procedure TMediaRouterFrm.SinksLbxClick(Sender: TObject);
begin
UpdateButtons;
end;
procedure TMediaRouterFrm.SourceURNEdtChange(Sender: TObject);
begin
UpdateButtons;
end;
procedure TMediaRouterFrm.TerminateRouteBtnClick(Sender: TObject);
begin
try
FMediaCS.Acquire;
if (RoutesLbx.Items.Count > 0) and
(FRoutes <> nil) and
(RoutesLbx.ItemIndex >= 0) and
(RoutesLbx.ItemIndex < length(FRoutes)) and
(FRoutes[RoutesLbx.ItemIndex].RouteIntf <> nil) then
try
FRoutes[RoutesLbx.ItemIndex].RouteIntf.Terminate;
except
on e : exception do
if CustomExceptionHandler('TMediaRouterFrm.TerminateRouteBtnClick', e) then raise;
end;
finally
FMediaCS.Release;
UpdateButtons;
end;
end;
procedure TMediaRouterFrm.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
if not(Chromium1.CreateBrowser(CEFWindowParent1)) and not(Chromium1.Initialized) then
Timer1.Enabled := True;
end;
procedure TMediaRouterFrm.BrowserDestroyMsg(var aMessage : TMessage);
begin
CEFWindowParent1.Free;
end;
procedure TMediaRouterFrm.PendingLogLinesMsg(var aMessage : TMessage);
begin
if FClosing then exit;
2020-04-21 13:27:34 +02:00
AppendPendingLogStrings;
end;
procedure TMediaRouterFrm.AppendPendingLogStrings;
begin
try
FMediaCS.Acquire;
if (FLog <> nil) and (FLog.Count > 0) then
begin
LogMem.Lines.AddStrings(FLog);
LogMem.SelLength := 0;
LogMem.SelStart := Length(LogMem.Text);
FLog.Clear;
end;
finally
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.RefreshSinksMsg(var aMessage : TMessage);
begin
if FClosing then exit;
UpdateAvailableSinks;
2020-04-21 13:27:34 +02:00
AppendPendingLogStrings;
UpdateButtons;
end;
procedure TMediaRouterFrm.RoutesLbxClick(Sender: TObject);
begin
UpdateButtons;
end;
procedure TMediaRouterFrm.RefreshRoutesMsg(var aMessage : TMessage);
begin
if FClosing then exit;
UpdateAvailableRoutes;
2020-04-21 13:27:34 +02:00
AppendPendingLogStrings;
UpdateButtons;
end;
procedure TMediaRouterFrm.UpdateButtonsMsg(var aMessage : TMessage);
begin
if FClosing then exit;
2020-04-21 13:27:34 +02:00
AppendPendingLogStrings;
UpdateButtons;
end;
procedure TMediaRouterFrm.DestroyAllArrays;
begin
try
FMediaCS.Acquire;
DestroyRoutesArray;
DestroySinksArray;
finally
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.DestroySinksArray;
var
i : integer;
begin
if (FSinks <> nil) then
begin
i := pred(length(FSinks));
while (i >= 0) do
begin
FSinks[i].SinkIntf := nil;
dec(i);
end;
Finalize(FSinks);
FSinks := nil;
end;
end;
procedure TMediaRouterFrm.DestroyRoutesArray;
var
i : integer;
begin
if (FRoutes <> nil) then
begin
i := pred(length(FRoutes));
while (i >= 0) do
begin
FRoutes[i].RouteIntf := nil;
dec(i);
end;
Finalize(FRoutes);
FRoutes := nil;
end;
end;
procedure TMediaRouterFrm.CopySinksArray(const aSinks : TCefMediaSinkArray);
var
i, TempLen : integer;
begin
try
FMediaCS.Acquire;
FLog.Add('Sinks available : ' + inttostr(length(aSinks)));
FLog.Add('------------------------------------------');
DestroySinksArray;
if (aSinks <> nil) then
begin
TempLen := length(aSinks);
SetLength(FSinks, TempLen);
i := 0;
while (i < TempLen) do
begin
FSinks[i].ID := aSinks[i].ID;
FSinks[i].Name := aSinks[i].Name;
FSinks[i].Description := aSinks[i].Description;
2020-04-30 17:28:41 +02:00
FSinks[i].IconType := aSinks[i].IconType;
FSinks[i].Valid := aSinks[i].IsValid;
FSinks[i].SinkIntf := aSinks[i];
if aSinks[i].IsCastSink then
FSinks[i].SinkType := mtCast
else
if aSinks[i].IsDialSink then
FSinks[i].SinkType := mtDial
else
FSinks[i].SinkType := mtUnknown;
inc(i);
end;
end;
finally
PostMessage(Handle, MEDIA_ROUTER_REFRESH_SINKS, 0, 0);
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.CopyRoutesArray(const aRoutes : TCefMediaRouteArray);
var
i, TempLen : integer;
begin
try
FMediaCS.Acquire;
FLog.Add('Routes available : ' + inttostr(length(aRoutes)));
FLog.Add('------------------------------------------');
DestroyRoutesArray;
if (aRoutes <> nil) then
begin
TempLen := length(aRoutes);
SetLength(FRoutes, TempLen);
i := 0;
while (i < TempLen) do
begin
FRoutes[i].ID := aRoutes[i].ID;
FRoutes[i].SourceID := aRoutes[i].GetSource.ID;
FRoutes[i].SinkID := aRoutes[i].GetSink.ID;
FRoutes[i].RouteIntf := aRoutes[i];
inc(i);
end;
end;
finally
PostMessage(Handle, MEDIA_ROUTER_REFRESH_ROUTES, 0, 0);
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.CreateRouteBtnClick(Sender: TObject);
var
TempURN, TempErrorMsg : string;
TempSource : ICefMediaSource;
begin
TempURN := trim(SourceURNCbx.Text);
if (length(TempURN) = 0) then
begin
AddLogEntry('Invalid URN');
exit;
end;
TempErrorMsg := '';
try
try
FMediaCS.Acquire;
if (FSinks <> nil) and
(SinksLbx.Items.Count > 0) and
(SinksLbx.ItemIndex >= 0) and
(SinksLbx.ItemIndex < length(FSinks)) then
begin
TempSource := Chromium1.GetSource(TempURN);
if (TempSource <> nil) and TempSource.IsValid then
begin
if (FSinks[SinksLbx.ItemIndex].SinkIntf <> nil) and
FSinks[SinksLbx.ItemIndex].SinkIntf.IsValid then
begin
if FSinks[SinksLbx.ItemIndex].SinkIntf.IsCompatibleWith(TempSource) then
Chromium1.CreateRoute(TempSource, FSinks[SinksLbx.ItemIndex].SinkIntf)
else
TempErrorMsg := 'The selected Sink is not compatible with the Media Source.';
end
else
TempErrorMsg := 'The selected Sink is not valid.';
end
else
TempErrorMsg := 'The Media Source is not valid.';
end
else
TempErrorMsg := 'The sinks list is outdated.';
except
on e : exception do
begin
TempErrorMsg := e.Message;
if CustomExceptionHandler('TMediaRouterFrm.CreateRouteBtnClick', e) then raise;
end;
end;
finally
TempSource := nil;
FMediaCS.Release;
if (length(TempErrorMsg) > 0) then AddLogEntry(TempErrorMsg);
end;
end;
procedure TMediaRouterFrm.UpdateAvailableSinks;
var
i : integer;
2020-04-30 17:28:41 +02:00
TempItem : string;
begin
try
FMediaCS.Acquire;
SinksLbx.Items.Clear;
if (FSinks <> nil) then
begin
i := 0;
while (i < length(FSinks)) do
begin
2020-04-30 17:28:41 +02:00
TempItem := FSinks[i].Name;
case FSinks[i].SinkType of
2020-04-30 17:28:41 +02:00
mtCast : TempItem := TempItem + ' (CAST';
mtDial : TempItem := TempItem + ' (DIAL';
else TempItem := TempItem + ' (UNKNOWN';
end;
case FSinks[i].IconType of
CEF_MSIT_CAST : TempItem := TempItem + ', CAST)';
CEF_MSIT_CAST_AUDIO_GROUP : TempItem := TempItem + ', CAST_AUDIO_GROUP)';
CEF_MSIT_CAST_AUDIO : TempItem := TempItem + ', CAST_AUDIO)';
CEF_MSIT_MEETING : TempItem := TempItem + ', MEETING)';
CEF_MSIT_HANGOUT : TempItem := TempItem + ', HANGOUT)';
CEF_MSIT_EDUCATION : TempItem := TempItem + ', EDUCATION)';
CEF_MSIT_WIRED_DISPLAY : TempItem := TempItem + ', WIRED_DISPLAY)';
CEF_MSIT_GENERIC : TempItem := TempItem + ', GENERIC)';
else TempItem := TempItem + ', UNKNOWN)';
end;
2020-04-30 17:28:41 +02:00
SinksLbx.Items.Add(TempItem);
inc(i);
end;
end;
finally
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.UpdateAvailableRoutes;
var
i : integer;
begin
try
FMediaCS.Acquire;
RoutesLbx.Items.Clear;
if (FRoutes <> nil) then
begin
i := 0;
while (i < length(FRoutes)) do
begin
RoutesLbx.Items.Add('ID : ' + quotedstr(FRoutes[i].ID));
inc(i);
end;
end;
finally
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.UpdateButtons;
begin
TerminateRouteBtn.Enabled := (RoutesLbx.ItemIndex >= 0) and
(RoutesLbx.Items.Count > 0);
SendMsgBtn.Enabled := TerminateRouteBtn.Enabled and
(length(trim(MessageMem.Lines.Text)) > 0);
CreateRouteBtn.Enabled := not(TerminateRouteBtn.Enabled) and
(length(trim(SourceURNCbx.Text)) > 0) and
(SinksLbx.ItemIndex >= 0) and
(SinksLbx.Items.Count > 0);
end;
procedure TMediaRouterFrm.AddLogEntry(const aMessage1, aMessage2 : string; aRec : boolean);
begin
try
FMediaCS.Acquire;
if aRec then
FLog.Add('Message received ' + dateTimeToStr(now))
else
FLog.Add('Message sent ' + dateTimeToStr(now));
FLog.Add(aMessage1);
if (length(aMessage2) > 0) then FLog.Add(aMessage2);
FLog.Add('------------------------------------------');
finally
PostMessage(Handle, MEDIA_ROUTER_PENDING_LOG_LINES, 0, 0);
FMediaCS.Release;
end;
end;
procedure TMediaRouterFrm.AddLogEntry(const aMessage1, aMessage2 : string);
begin
try
FMediaCS.Acquire;
FLog.Add(aMessage1);
if (length(aMessage2) > 0) then FLog.Add(aMessage2);
FLog.Add('------------------------------------------');
finally
PostMessage(Handle, MEDIA_ROUTER_PENDING_LOG_LINES, 0, 0);
FMediaCS.Release;
end;
end;
end.