mirror of
https://github.com/salvadordf/CEF4Delphi.git
synced 2024-11-24 08:02:15 +02:00
Update to CEF 81.2.24
- Added code comments to the MediaRouter demo - Added a Lazarus version of the MediaRouter demo
This commit is contained in:
parent
22b59eae73
commit
a34ae44cb0
@ -3,10 +3,10 @@ CEF4Delphi is an open source project created by Salvador D
|
||||
|
||||
CEF4Delphi is based on DCEF3, made by Henri Gourvest. The original license of DCEF3 still applies to CEF4Delphi. Read the license terms in the first lines of any *.pas file.
|
||||
|
||||
CEF4Delphi uses CEF 81.2.22 which includes Chromium 81.0.4044.113.
|
||||
CEF4Delphi uses CEF 81.2.24 which includes Chromium 81.0.4044.113.
|
||||
The CEF binaries used by CEF4Delphi are available for download at spotify :
|
||||
* [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_81.2.22%2Bg23f4473%2Bchromium-81.0.4044.113_windows32.tar.bz2)
|
||||
* [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_81.2.22%2Bg23f4473%2Bchromium-81.0.4044.113_windows64.tar.bz2)
|
||||
* [32 bits](http://opensource.spotify.com/cefbuilds/cef_binary_81.2.24%2Bgc0b313d%2Bchromium-81.0.4044.113_windows32.tar.bz2)
|
||||
* [64 bits](http://opensource.spotify.com/cefbuilds/cef_binary_81.2.24%2Bgc0b313d%2Bchromium-81.0.4044.113_windows64.tar.bz2)
|
||||
|
||||
|
||||
CEF4Delphi was developed and tested on Delphi 10.3.3 and it has been tested in Delphi 7, Delphi XE, Delphi 10, Delphi 10.2 and Lazarus 2.0.8/FPC 3.0.4. CEF4Delphi includes VCL, FireMonkey (FMX) and Lazarus components.
|
||||
|
@ -6,7 +6,7 @@
|
||||
<MainSource>MediaRouter.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
<TargetedPlatforms>3</TargetedPlatforms>
|
||||
<AppType>Application</AppType>
|
||||
</PropertyGroup>
|
||||
|
@ -45,7 +45,7 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
Width = 250
|
||||
Height = 727
|
||||
Align = alLeft
|
||||
Caption = ' Sinks available on this network '
|
||||
Caption = ' Sinks on this network '
|
||||
Padding.Left = 10
|
||||
Padding.Top = 10
|
||||
Padding.Right = 10
|
||||
@ -114,16 +114,6 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
Padding.Right = 2
|
||||
Padding.Bottom = 10
|
||||
TabOrder = 0
|
||||
object SourceURNEdt: TEdit
|
||||
Left = 65
|
||||
Top = 10
|
||||
Width = 392
|
||||
Height = 21
|
||||
Align = alClient
|
||||
TabOrder = 0
|
||||
Text = 'cast:<appId>?clientId=<clientId>'
|
||||
OnChange = SourceURNEdtChange
|
||||
end
|
||||
object SourceLblPnl: TPanel
|
||||
Left = 0
|
||||
Top = 10
|
||||
@ -131,7 +121,7 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
Height = 21
|
||||
Align = alLeft
|
||||
BevelOuter = bvNone
|
||||
TabOrder = 1
|
||||
TabOrder = 0
|
||||
object SourceURNLbl: TLabel
|
||||
Left = 0
|
||||
Top = 0
|
||||
@ -144,6 +134,20 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
ExplicitHeight = 13
|
||||
end
|
||||
end
|
||||
object SourceURNCbx: TComboBox
|
||||
Left = 65
|
||||
Top = 10
|
||||
Width = 392
|
||||
Height = 21
|
||||
Align = alClient
|
||||
ItemIndex = 1
|
||||
TabOrder = 1
|
||||
Text = 'cast:CC1AD845?clientId=123456789'
|
||||
Items.Strings = (
|
||||
'cast:<appId>?clientId=<clientId>'
|
||||
'cast:CC1AD845?clientId=123456789'
|
||||
'cast:4F8B3483?clientId=123456789')
|
||||
end
|
||||
end
|
||||
object MessageGbx: TGroupBox
|
||||
Left = 20
|
||||
@ -247,7 +251,7 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
Width = 250
|
||||
Height = 727
|
||||
Align = alRight
|
||||
Caption = ' Routes available '
|
||||
Caption = ' Established routes '
|
||||
Padding.Left = 10
|
||||
Padding.Top = 10
|
||||
Padding.Right = 10
|
||||
@ -261,6 +265,7 @@ object MediaRouterFrm: TMediaRouterFrm
|
||||
Align = alClient
|
||||
ItemHeight = 13
|
||||
TabOrder = 0
|
||||
OnClick = RoutesLbxClick
|
||||
end
|
||||
object RoutesButtonPnl: TPanel
|
||||
Left = 12
|
||||
|
@ -72,7 +72,6 @@ type
|
||||
CreateRouteBtn: TButton;
|
||||
CentralPnl: TPanel;
|
||||
SourcePnl: TPanel;
|
||||
SourceURNEdt: TEdit;
|
||||
SourceLblPnl: TPanel;
|
||||
SourceURNLbl: TLabel;
|
||||
RoutesGbx: TGroupBox;
|
||||
@ -90,6 +89,7 @@ type
|
||||
NotifyRoutesBtn: TButton;
|
||||
ClearLogPnl: TPanel;
|
||||
ClearLogBtn: TButton;
|
||||
SourceURNCbx: TComboBox;
|
||||
|
||||
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
@ -115,6 +115,7 @@ type
|
||||
procedure NotifyRoutesBtnClick(Sender: TObject);
|
||||
procedure ClearLogBtnClick(Sender: TObject);
|
||||
procedure MessageMemChange(Sender: TObject);
|
||||
procedure RoutesLbxClick(Sender: TObject);
|
||||
|
||||
protected
|
||||
// Variables to control when can we destroy the form safely
|
||||
@ -162,16 +163,63 @@ uses
|
||||
{$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; //LOGSEVERITY_VERBOSE;
|
||||
{
|
||||
GlobalCEFApp.FrameworkDirPath := 'c:\cef';
|
||||
GlobalCEFApp.ResourcesDirPath := 'c:\cef';
|
||||
GlobalCEFApp.LocalesDirPath := 'c:\cef\locales';
|
||||
}
|
||||
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.Chromium1AfterCreated(Sender: TObject;
|
||||
@ -411,6 +459,8 @@ begin
|
||||
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
|
||||
@ -427,6 +477,11 @@ begin
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.RoutesLbxClick(Sender: TObject);
|
||||
begin
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.RefreshRoutesMsg(var aMessage : TMessage);
|
||||
begin
|
||||
if FClosing then exit;
|
||||
@ -572,7 +627,7 @@ var
|
||||
TempURN, TempErrorMsg : string;
|
||||
TempSource : ICefMediaSource;
|
||||
begin
|
||||
TempURN := trim(SourceURNEdt.Text);
|
||||
TempURN := trim(SourceURNCbx.Text);
|
||||
|
||||
if (length(TempURN) = 0) then
|
||||
begin
|
||||
@ -619,6 +674,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
TempSource := nil;
|
||||
FMediaCS.Release;
|
||||
if (length(TempErrorMsg) > 0) then AddLogEntry(TempErrorMsg);
|
||||
end;
|
||||
@ -682,7 +738,7 @@ begin
|
||||
(length(trim(MessageMem.Lines.Text)) > 0);
|
||||
|
||||
CreateRouteBtn.Enabled := not(TerminateRouteBtn.Enabled) and
|
||||
(length(trim(SourceURNEdt.Text)) > 0) and
|
||||
(length(trim(SourceURNCbx.Text)) > 0) and
|
||||
(SinksLbx.ItemIndex >= 0) and
|
||||
(SinksLbx.Items.Count > 0);
|
||||
end;
|
||||
|
@ -6,7 +6,7 @@
|
||||
<MainSource>PopupBrowser.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
<TargetedPlatforms>3</TargetedPlatforms>
|
||||
<AppType>Application</AppType>
|
||||
</PropertyGroup>
|
||||
|
@ -232,6 +232,8 @@ begin
|
||||
GlobalCEFApp.EnableHighDPISupport := True;
|
||||
GlobalCEFApp.TouchEvents := STATE_ENABLED;
|
||||
//GlobalCEFApp.EnableGPU := True;
|
||||
GlobalCEFApp.LogFile := 'debug.log';
|
||||
GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO;
|
||||
|
||||
// If you need transparency leave the GlobalCEFApp.BackgroundColor property
|
||||
// with the default value or set the alpha channel to 0
|
||||
|
2
demos/Lazarus/MediaRouter/00-Delete.bat
Normal file
2
demos/Lazarus/MediaRouter/00-Delete.bat
Normal file
@ -0,0 +1,2 @@
|
||||
rmdir /S /Q lib
|
||||
rmdir /S /Q backup
|
91
demos/Lazarus/MediaRouter/MediaRouter.lpi
Normal file
91
demos/Lazarus/MediaRouter/MediaRouter.lpi
Normal file
@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<MainUnitHasUsesSectionForAllUnits Value="False"/>
|
||||
<MainUnitHasCreateFormStatements Value="False"/>
|
||||
<MainUnitHasTitleStatement Value="False"/>
|
||||
<MainUnitHasScaledStatement Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<Title Value="MediaRouter"/>
|
||||
<UseAppBundle Value="False"/>
|
||||
<ResourceType Value="res"/>
|
||||
</General>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<UseFileFilters Value="True"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
<Modes Count="0"/>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="CEF4Delphi_Lazarus"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="MediaRouter.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="uMediaRouterFrm.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="MediaRouterFrm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="..\..\..\bin\MediaRouter"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<SyntaxMode Value="Delphi"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<Linking>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CustomOptions Value="-dBorland -dVer150 -dDelphi7 -dCompiler6_Up -dPUREPASCAL"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
72
demos/Lazarus/MediaRouter/MediaRouter.lpr
Normal file
72
demos/Lazarus/MediaRouter/MediaRouter.lpr
Normal file
@ -0,0 +1,72 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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 © 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.
|
||||
*
|
||||
*)
|
||||
|
||||
program MediaRouter;
|
||||
|
||||
{$MODE Delphi}
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
uses
|
||||
{$IFDEF DELPHI16_UP}
|
||||
Vcl.Forms,
|
||||
WinApi.Windows,
|
||||
{$ELSE}
|
||||
Windows,
|
||||
Forms,
|
||||
LCLIntf, LCLType, LMessages, Interfaces,
|
||||
{$ENDIF }
|
||||
uCEFApplication,
|
||||
uMediaRouterFrm in 'uMediaRouterFrm.pas' {MediaRouterFrm};
|
||||
|
||||
{.$R *.res}
|
||||
|
||||
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
|
||||
|
||||
begin
|
||||
CreateGlobalCEFApp;
|
||||
|
||||
if GlobalCEFApp.StartMainProcess then
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.MainFormOnTaskbar := True;
|
||||
Application.CreateForm(TMediaRouterFrm, MediaRouterFrm);
|
||||
Application.Run;
|
||||
end;
|
||||
|
||||
DestroyGlobalCEFApp;
|
||||
end.
|
44
demos/Lazarus/MediaRouter/MediaRouter.lps
Normal file
44
demos/Lazarus/MediaRouter/MediaRouter.lps
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectSession>
|
||||
<PathDelim Value="\"/>
|
||||
<Version Value="11"/>
|
||||
<BuildModes Active="Default"/>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="MediaRouter.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<TopLine Value="42"/>
|
||||
<CursorPos X="37" Y="66"/>
|
||||
<UsageCount Value="20"/>
|
||||
<Loaded Value="True"/>
|
||||
<DefaultSyntaxHighlighter Value="Delphi"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="uMediaRouterFrm.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="MediaRouterFrm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<IsVisibleTab Value="True"/>
|
||||
<EditorIndex Value="1"/>
|
||||
<TopLine Value="553"/>
|
||||
<CursorPos X="29" Y="49"/>
|
||||
<UsageCount Value="20"/>
|
||||
<Loaded Value="True"/>
|
||||
<LoadedDesigner Value="True"/>
|
||||
<DefaultSyntaxHighlighter Value="Delphi"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
<JumpHistory Count="1">
|
||||
<Position1>
|
||||
<Filename Value="MediaRouter.lpr"/>
|
||||
<Caret Line="49" Column="11" TopLine="42"/>
|
||||
</Position1>
|
||||
</JumpHistory>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
<Modes Count="0" ActiveMode=""/>
|
||||
</RunParams>
|
||||
</ProjectSession>
|
||||
</CONFIG>
|
409
demos/Lazarus/MediaRouter/cef.inc
Normal file
409
demos/Lazarus/MediaRouter/cef.inc
Normal file
@ -0,0 +1,409 @@
|
||||
// ************************************************************************
|
||||
// ***************************** CEF4Delphi *******************************
|
||||
// ************************************************************************
|
||||
//
|
||||
// CEF4Delphi is based on DCEF3 which uses CEF3 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 © 2017 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.
|
||||
*
|
||||
*)
|
||||
|
||||
// The complete list of compiler versions is here :
|
||||
// http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Compiler_Versions
|
||||
|
||||
{$DEFINE DELPHI_VERSION_UNKNOW}
|
||||
|
||||
// Delphi 5
|
||||
{$IFDEF VER130}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi 6
|
||||
{$IFDEF VER140}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi 7
|
||||
{$IFDEF VER150}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi 8
|
||||
{$IFDEF VER160}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi 2005
|
||||
{$IFDEF VER170}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER180}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
// Delphi 2007
|
||||
{$IFDEF VER185}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
// Delphi 2006
|
||||
{$ELSE}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi 2009
|
||||
{$IFDEF VER200}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$ENDIF}
|
||||
|
||||
//Delphi 2010
|
||||
{$IFDEF VER210}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE
|
||||
{$IFDEF VER220}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE2 (First FireMonkey and 64bit compiler)
|
||||
{$IFDEF VER230}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE3
|
||||
{$IFDEF VER240}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE4
|
||||
{$IFDEF VER250}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE5
|
||||
{$IFDEF VER260}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE6
|
||||
{$IFDEF VER270}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE7
|
||||
{$IFDEF VER280}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Delphi XE8
|
||||
{$IFDEF VER290}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$ENDIF VER290}
|
||||
|
||||
// Rad Studio 10 - Delphi Seattle
|
||||
{$IFDEF VER300}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$DEFINE DELPHI23_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Rad Studio 10.1 - Delphi Berlin
|
||||
{$IFDEF VER310}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$DEFINE DELPHI23_UP}
|
||||
{$DEFINE DELPHI24_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Rad Studio 10.2 - Delphi Tokyo
|
||||
{$IFDEF VER320}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$DEFINE DELPHI23_UP}
|
||||
{$DEFINE DELPHI24_UP}
|
||||
{$DEFINE DELPHI25_UP}
|
||||
{$ENDIF}
|
||||
|
||||
// Rad Studio 10.3 - Delphi Rio
|
||||
{$IFDEF VER330}
|
||||
{$UNDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$DEFINE DELPHI23_UP}
|
||||
{$DEFINE DELPHI24_UP}
|
||||
{$DEFINE DELPHI25_UP}
|
||||
{$DEFINE DELPHI26_UP}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$DEFINE SUPPORTS_INLINE}
|
||||
{$ELSE}
|
||||
{$IFDEF DELPHI_VERSION_UNKNOW}
|
||||
{$DEFINE DELPHI5_UP}
|
||||
{$DEFINE DELPHI6_UP}
|
||||
{$DEFINE DELPHI7_UP}
|
||||
{$DEFINE DELPHI8_UP}
|
||||
{$DEFINE DELPHI9_UP}
|
||||
{$DEFINE DELPHI10_UP}
|
||||
{$DEFINE DELPHI11_UP}
|
||||
{$DEFINE DELPHI12_UP}
|
||||
{$DEFINE DELPHI14_UP}
|
||||
{$DEFINE DELPHI15_UP}
|
||||
{$DEFINE DELPHI16_UP}
|
||||
{$DEFINE DELPHI17_UP}
|
||||
{$DEFINE DELPHI18_UP}
|
||||
{$DEFINE DELPHI19_UP}
|
||||
{$DEFINE DELPHI20_UP}
|
||||
{$DEFINE DELPHI21_UP}
|
||||
{$DEFINE DELPHI22_UP}
|
||||
{$DEFINE DELPHI23_UP}
|
||||
{$DEFINE DELPHI24_UP}
|
||||
{$DEFINE DELPHI25_UP}
|
||||
{$DEFINE DELPHI26_UP}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF DELPHI9_UP}
|
||||
{$DEFINE SUPPORTS_INLINE}
|
||||
{$ENDIF}
|
||||
|
316
demos/Lazarus/MediaRouter/uMediaRouterFrm.lfm
Normal file
316
demos/Lazarus/MediaRouter/uMediaRouterFrm.lfm
Normal file
@ -0,0 +1,316 @@
|
||||
object MediaRouterFrm: TMediaRouterFrm
|
||||
Left = 363
|
||||
Height = 757
|
||||
Top = 75
|
||||
Width = 1029
|
||||
Caption = 'Media Router'
|
||||
ClientHeight = 757
|
||||
ClientWidth = 1029
|
||||
Color = clBtnFace
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Tahoma'
|
||||
OnCloseQuery = FormCloseQuery
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
OnShow = FormShow
|
||||
Position = poScreenCenter
|
||||
LCLVersion = '2.0.8.0'
|
||||
object CEFWindowParent1: TCEFWindowParent
|
||||
Left = 184
|
||||
Height = 0
|
||||
Top = 56
|
||||
Width = 0
|
||||
TabOrder = 0
|
||||
Visible = False
|
||||
Enabled = False
|
||||
end
|
||||
object MainPnl: TPanel
|
||||
Left = 0
|
||||
Height = 757
|
||||
Top = 0
|
||||
Width = 1029
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 757
|
||||
ClientWidth = 1029
|
||||
TabOrder = 1
|
||||
object SinksGbx: TGroupBox
|
||||
Left = 0
|
||||
Height = 757
|
||||
Top = 0
|
||||
Width = 250
|
||||
Align = alLeft
|
||||
Caption = ' Sinks on this network '
|
||||
ClientHeight = 739
|
||||
ClientWidth = 246
|
||||
TabOrder = 0
|
||||
object SinksLbx: TListBox
|
||||
Left = 0
|
||||
Height = 679
|
||||
Top = 0
|
||||
Width = 246
|
||||
Align = alClient
|
||||
ItemHeight = 0
|
||||
OnClick = SinksLbxClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object SinksButtonsPnl: TPanel
|
||||
Left = 0
|
||||
Height = 60
|
||||
Top = 679
|
||||
Width = 246
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 60
|
||||
ClientWidth = 246
|
||||
TabOrder = 1
|
||||
object CreateRouteBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 246
|
||||
Align = alTop
|
||||
Caption = 'Create route'
|
||||
Enabled = False
|
||||
OnClick = CreateRouteBtnClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object NotifySinksBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 33
|
||||
Width = 246
|
||||
Align = alBottom
|
||||
Caption = 'Notify sinks'
|
||||
OnClick = NotifySinksBtnClick
|
||||
TabOrder = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
object CentralPnl: TPanel
|
||||
Left = 250
|
||||
Height = 757
|
||||
Top = 0
|
||||
Width = 529
|
||||
Align = alClient
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 757
|
||||
ClientWidth = 529
|
||||
TabOrder = 1
|
||||
object SourcePnl: TPanel
|
||||
Left = 0
|
||||
Height = 21
|
||||
Top = 0
|
||||
Width = 529
|
||||
Align = alTop
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 21
|
||||
ClientWidth = 529
|
||||
TabOrder = 0
|
||||
object SourceLblPnl: TPanel
|
||||
Left = 0
|
||||
Height = 21
|
||||
Top = 0
|
||||
Width = 65
|
||||
Align = alLeft
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 21
|
||||
ClientWidth = 65
|
||||
TabOrder = 0
|
||||
object SourceURNLbl: TLabel
|
||||
Left = 0
|
||||
Height = 21
|
||||
Top = 0
|
||||
Width = 65
|
||||
Align = alClient
|
||||
Caption = 'Source URN'
|
||||
Layout = tlCenter
|
||||
ParentColor = False
|
||||
end
|
||||
end
|
||||
object SourceURNCbx: TComboBox
|
||||
Left = 65
|
||||
Height = 21
|
||||
Top = 0
|
||||
Width = 464
|
||||
Align = alClient
|
||||
ItemHeight = 13
|
||||
ItemIndex = 1
|
||||
Items.Strings = (
|
||||
'cast:<appId>?clientId=<clientId>'
|
||||
'cast:CC1AD845?clientId=123456789'
|
||||
'cast:4F8B3483?clientId=123456789'
|
||||
)
|
||||
TabOrder = 1
|
||||
Text = 'cast:CC1AD845?clientId=123456789'
|
||||
end
|
||||
end
|
||||
object MessageGbx: TGroupBox
|
||||
Left = 0
|
||||
Height = 430
|
||||
Top = 327
|
||||
Width = 529
|
||||
Align = alClient
|
||||
Caption = ' Message '
|
||||
ClientHeight = 412
|
||||
ClientWidth = 525
|
||||
TabOrder = 1
|
||||
object SendMessagePnl: TPanel
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 385
|
||||
Width = 525
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 27
|
||||
ClientWidth = 525
|
||||
TabOrder = 0
|
||||
object SendMsgBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 525
|
||||
Align = alClient
|
||||
Caption = 'Send message'
|
||||
OnClick = SendMsgBtnClick
|
||||
TabOrder = 0
|
||||
end
|
||||
end
|
||||
object MessageMem: TMemo
|
||||
Left = 0
|
||||
Height = 385
|
||||
Top = 0
|
||||
Width = 525
|
||||
Align = alClient
|
||||
OnChange = MessageMemChange
|
||||
ScrollBars = ssBoth
|
||||
TabOrder = 1
|
||||
end
|
||||
end
|
||||
object LogGbx: TGroupBox
|
||||
Left = 0
|
||||
Height = 296
|
||||
Top = 21
|
||||
Width = 529
|
||||
Align = alTop
|
||||
Caption = ' Log '
|
||||
ClientHeight = 278
|
||||
ClientWidth = 525
|
||||
TabOrder = 2
|
||||
object LogMem: TMemo
|
||||
Left = 0
|
||||
Height = 251
|
||||
Top = 0
|
||||
Width = 525
|
||||
Align = alClient
|
||||
ReadOnly = True
|
||||
ScrollBars = ssBoth
|
||||
TabOrder = 0
|
||||
end
|
||||
object ClearLogPnl: TPanel
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 251
|
||||
Width = 525
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 27
|
||||
ClientWidth = 525
|
||||
TabOrder = 1
|
||||
object ClearLogBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 525
|
||||
Align = alClient
|
||||
Caption = 'Clear log'
|
||||
OnClick = ClearLogBtnClick
|
||||
TabOrder = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
object SpacerPnl: TPanel
|
||||
Left = 0
|
||||
Height = 10
|
||||
Top = 317
|
||||
Width = 529
|
||||
Align = alTop
|
||||
BevelOuter = bvNone
|
||||
TabOrder = 3
|
||||
end
|
||||
end
|
||||
object RoutesGbx: TGroupBox
|
||||
Left = 779
|
||||
Height = 757
|
||||
Top = 0
|
||||
Width = 250
|
||||
Align = alRight
|
||||
Caption = ' Established routes '
|
||||
ClientHeight = 739
|
||||
ClientWidth = 246
|
||||
TabOrder = 2
|
||||
object RoutesLbx: TListBox
|
||||
Left = 0
|
||||
Height = 679
|
||||
Top = 0
|
||||
Width = 246
|
||||
Align = alClient
|
||||
ItemHeight = 0
|
||||
OnClick = RoutesLbxClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object RoutesButtonPnl: TPanel
|
||||
Left = 0
|
||||
Height = 60
|
||||
Top = 679
|
||||
Width = 246
|
||||
Align = alBottom
|
||||
BevelOuter = bvNone
|
||||
ClientHeight = 60
|
||||
ClientWidth = 246
|
||||
TabOrder = 1
|
||||
object TerminateRouteBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 0
|
||||
Width = 246
|
||||
Align = alTop
|
||||
Caption = 'Terminate route'
|
||||
Enabled = False
|
||||
OnClick = TerminateRouteBtnClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object NotifyRoutesBtn: TButton
|
||||
Left = 0
|
||||
Height = 27
|
||||
Top = 33
|
||||
Width = 246
|
||||
Align = alBottom
|
||||
Caption = 'Notify routes'
|
||||
OnClick = NotifyRoutesBtnClick
|
||||
TabOrder = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
object Chromium1: TChromium
|
||||
OnMediaRouteCreateFinished = Chromium1MediaRouteCreateFinished
|
||||
OnAfterCreated = Chromium1AfterCreated
|
||||
OnBeforeClose = Chromium1BeforeClose
|
||||
OnClose = Chromium1Close
|
||||
OnSinks = Chromium1Sinks
|
||||
OnRoutes = Chromium1Routes
|
||||
OnRouteStateChanged = Chromium1RouteStateChanged
|
||||
OnRouteMessageReceived = Chromium1RouteMessageReceived
|
||||
left = 72
|
||||
top = 56
|
||||
end
|
||||
object Timer1: TTimer
|
||||
Enabled = False
|
||||
Interval = 300
|
||||
OnTimer = Timer1Timer
|
||||
left = 72
|
||||
top = 136
|
||||
end
|
||||
end
|
774
demos/Lazarus/MediaRouter/uMediaRouterFrm.pas
Normal file
774
demos/Lazarus/MediaRouter/uMediaRouterFrm.pas
Normal file
@ -0,0 +1,774 @@
|
||||
// ************************************************************************
|
||||
// ***************************** 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 © 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;
|
||||
|
||||
{$MODE Delphi}
|
||||
|
||||
{$I cef.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLIntf, LCLType, LMessages, Messages, SysUtils, Variants, Classes, Graphics, Menus,
|
||||
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd,
|
||||
ActiveX, ShlObj, SyncObjs,
|
||||
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);
|
||||
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;
|
||||
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 *.lfm}
|
||||
|
||||
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';
|
||||
if (route <> nil) then TempID := 'Route ID : ' + route.ID;
|
||||
end
|
||||
else
|
||||
TempMsg := error;
|
||||
finally
|
||||
FMediaCS.Release;
|
||||
if (length(TempMsg) > 0) then AddLogEntry(TempID, TempMsg);
|
||||
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
|
||||
TempID := 'Route ID : ' + route.ID;
|
||||
|
||||
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
|
||||
if (route <> nil) then TempID := 'Route ID : ' + route.ID;
|
||||
|
||||
case state of
|
||||
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;
|
||||
|
||||
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
|
||||
TempID := 'Route ID : ' + FRoutes[RoutesLbx.ItemIndex].RouteIntf.ID;
|
||||
FRoutes[RoutesLbx.ItemIndex].RouteIntf.SendRouteMessage(TempMsg);
|
||||
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;
|
||||
|
||||
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;
|
||||
AppendPendingLogStrings;
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.RoutesLbxClick(Sender: TObject);
|
||||
begin
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.RefreshRoutesMsg(var aMessage : TMessage);
|
||||
begin
|
||||
if FClosing then exit;
|
||||
|
||||
UpdateAvailableRoutes;
|
||||
AppendPendingLogStrings;
|
||||
UpdateButtons;
|
||||
end;
|
||||
|
||||
procedure TMediaRouterFrm.UpdateButtonsMsg(var aMessage : TMessage);
|
||||
begin
|
||||
if FClosing then exit;
|
||||
|
||||
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;
|
||||
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;
|
||||
begin
|
||||
try
|
||||
FMediaCS.Acquire;
|
||||
SinksLbx.Items.Clear;
|
||||
|
||||
if (FSinks <> nil) then
|
||||
begin
|
||||
i := 0;
|
||||
while (i < length(FSinks)) do
|
||||
begin
|
||||
case FSinks[i].SinkType of
|
||||
mtCast : SinksLbx.Items.Add(FSinks[i].Name + ' (CAST)');
|
||||
mtDial : SinksLbx.Items.Add(FSinks[i].Name + ' (DIAL)');
|
||||
else SinksLbx.Items.Add(FSinks[i].Name + ' (UNKNOWN)');
|
||||
end;
|
||||
|
||||
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.
|
@ -22,8 +22,8 @@
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
<IsVisibleTab Value="True"/>
|
||||
<EditorIndex Value="1"/>
|
||||
<TopLine Value="544"/>
|
||||
<CursorPos X="38" Y="555"/>
|
||||
<TopLine Value="22"/>
|
||||
<CursorPos X="37" Y="48"/>
|
||||
<UsageCount Value="21"/>
|
||||
<Bookmarks Count="3">
|
||||
<Item0 Y="840" ID="1"/>
|
||||
|
@ -15,7 +15,7 @@ object MiniBrowserFrm: TMiniBrowserFrm
|
||||
OnDestroy = FormDestroy
|
||||
OnShow = FormShow
|
||||
Position = poScreenCenter
|
||||
LCLVersion = '2.0.6.0'
|
||||
LCLVersion = '2.0.8.0'
|
||||
object Splitter1: TSplitter
|
||||
Left = 1179
|
||||
Height = 663
|
||||
|
@ -45,7 +45,7 @@ uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Menus,
|
||||
Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd, ActiveX, ShlObj,
|
||||
uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants,
|
||||
uCEFWinControl, uCEFChromiumEvents, uCEFSentinel;
|
||||
uCEFWinControl, uCEFChromiumEvents;
|
||||
|
||||
const
|
||||
MINIBROWSER_SHOWDEVTOOLS = WM_APP + $101;
|
||||
|
@ -21,7 +21,7 @@
|
||||
</CompilerOptions>
|
||||
<Description Value="CEF4Delphi is an open source project created by Salvador Díaz Fau to embed Chromium-based browsers in applications made with Delphi or Lazarus/FPC."/>
|
||||
<License Value="MPL 1.1"/>
|
||||
<Version Major="81" Minor="2" Release="22"/>
|
||||
<Version Major="81" Minor="2" Release="24"/>
|
||||
<Files Count="154">
|
||||
<Item1>
|
||||
<Filename Value="..\source\uCEFAccessibilityHandler.pas"/>
|
||||
|
@ -62,7 +62,7 @@ uses
|
||||
const
|
||||
CEF_SUPPORTED_VERSION_MAJOR = 81;
|
||||
CEF_SUPPORTED_VERSION_MINOR = 2;
|
||||
CEF_SUPPORTED_VERSION_RELEASE = 22;
|
||||
CEF_SUPPORTED_VERSION_RELEASE = 24;
|
||||
CEF_SUPPORTED_VERSION_BUILD = 0;
|
||||
|
||||
CEF_CHROMEELF_VERSION_MAJOR = 81;
|
||||
|
@ -1276,8 +1276,8 @@ end;
|
||||
|
||||
procedure TChromiumCore.DestroyMediaObserver;
|
||||
begin
|
||||
FRegistration := nil;
|
||||
FMediaObserver := nil;
|
||||
FRegistration := nil;
|
||||
end;
|
||||
|
||||
procedure TChromiumCore.CreateMediaObserver;
|
||||
|
@ -2,9 +2,9 @@
|
||||
"UpdateLazPackages" : [
|
||||
{
|
||||
"ForceNotify" : true,
|
||||
"InternalVersion" : 124,
|
||||
"InternalVersion" : 125,
|
||||
"Name" : "cef4delphi_lazarus.lpk",
|
||||
"Version" : "81.2.22.0"
|
||||
"Version" : "81.2.24.0"
|
||||
}
|
||||
],
|
||||
"UpdatePackageData" : {
|
||||
|
Loading…
Reference in New Issue
Block a user