Usage of UCTX Component

Introduction
UCTX allows using of audio/video/screen share communication between clients
written on almost any language that supports Microsoft COM technology.
Client side of UCTX is a single DLL COM library.
Most of UCTX functionality is asynchronous.
It means UCTX receives your commands, but response will be some time later.
Any execution of command will not be blocked, but enqueued for processing.

COM Interface
UCTX has command line like interface to manipulate internal objects.
Main UCTX object has name of “Console” with main function “Execute”.
This function executes internal commands asynchronously.
Other COM objects have following meaning.
UIControl – internal objects visualization – displays picture of video and screen objects.
Console.ConnectExternal is used to connect UIControl to internal object.
UI – factory for UIFilter window. UIFilter is used to limit screen publisher by UIFilter
window bounds.
Util – provide set of synchronous queries to get helping data such as a list of audio
devices in system, video cameras etc.

Console
“Console” is main object of UCTX COM library.
All internal obajects are created stored and destroyed inside “Console” internal container.
“Console” has following COM interface.
interface IConsole : IBaseObject
{
	HRESULT Execute( [in] BSTR msg );
	HRESULT ConnectExternal( [in] BSTR oid, [in] IBaseObject* ext );
	HRESULT WaitForStopped( [in] long period );
};
dispinterface _IConsoleEvents
{
properties:
methods:
	void OnMessage( [in] BSTR oid, [in] BSTR cmd, [in] BSTR value );
};
Almost all work with “Console” performs through “Execute” function and “OnMessage” callback.
“Execute” enqueues commands which can execute callbacks by “OnMessage”.
Common way to start work with UCTX is following:
1. Create “Console” object.
2. Subscribe to “OnMessage” callback.
3. Call console.Execute(“\n.Start”) to initialize console.
Console starts internal thread and returns callback.
4. Handle first callback.
“Oid”, “cmd” and “value” should be “”, “OnStatusChanged” and “ready” respectively.
This callback is the important point where we can start creating internal objects
and starting to perform our application logic.
To finish UCTX work “\n.Destroy” command should be called.
Console before destroying itself calls “destroy” for every internal object,
so “OnMessage” will be called many times and last call will be with
“”, “OnStatusChanged” and “destroyed” parameters.

Connection to server
“Console” can create “Connection” internal object used to communicate with
UCTX conference server.
Server connection needs several parameters to be passed before “Connect” command queued.
console.Execute
	( "\n.Set connect_timeout_seconds=1"
	+ "\n.Set proxy.settings=DIRECT"
	+ "\n.Set autodetect_sequence=tcp; tcp socks4 config; http_tunnel; http_tunnel socks4 config;"
	+ "\n.Set server.host=localhost"
	+ "\n.Set server.port=85"
	+ "\n.Set server.port_ssl=447"
	+ "\n.Set server.port_http=90"
	+ "\n.Set protocol.key=test"
	+ "\n.Set id.conference=1"
	+ "\n.Set id.user=1"
	+ "\n.Set protocol.is_master=1"
	+ "\n.Set protocol.purpose=3"
	+ "\n.New con=Connection"
	);
Server should receive following group of parameters to use them as connection id:
1. “protocol.key” – key of conference group.
Server can handle multiple conferences from multiple type of software clients.
It means that clients with different keys will not share conference with same id.
2. “id.conference” – Conference identifier.
3. “protocol.purpose” – Conference subidentifier.
Used to have possibility to open multiple connections with same conference id
in order to have separate connections for video and audio for example.
4. “id.user” – Each connection in conference should have unique user id.
5. “protocol.is_master” – Flag to destinguish master and non-master connections.
Conference can have single master and multiple non-master connections.
Master connection sends data to all non-master connections,
but non-master can send only to master.
All parameters description can be found in API reference document.
Common way to start connection is following:
1. Create connection object.
2. Set connection parameters.
3. Call console.Execute(“\ncon.Connect”) command to enqueue connection sequence.
4. Handle callback. Successfull connection will produce callback with parameters:
(connection_object_name), “OnStatusChanged” and “active”.
At this point publisher and subscriber objects can be created.

Publishing and subscribing
Audio, video and screen data sending are implemented by publish-subscribe model.
In order to send data connection should create publisher object and start it.
In order to receive data connection should create subscriber object and start it too.
If publisher’s and subscriber’s “id.channel” are the same and
publisher’s connection user.id and subscriber’s “id.channel_user” are the same too,
both objects turn status to “active” and are going to perform data transfer.

UI Control
UI Control is used to show video or screen objects data in UI window.
To show UI data:
1. Create source object.
It can be screen publisher or subscriber, video source or video subscriber.
2. Create UIControl ActiveX.
3. Call console.ConnectExternal( “src”, ui_control ), where “src” is the name of the
source object.
4. Start source object.
UIControl should show object’s internal picture.
Multiple UIControls can be connected to single source object.

Chat Example
Example contains single C# application.
Application gets a “id.user” parameter from command line.
It will be zero by default. Zero user will be master. Otherwise non-master.
To show chat work 2 or more applications should be started.
First with 0, second with 1 in arguments, and so on.
Then you can type something and press “enter” to send message.
Received message should appear in other application(s).
CHAT code:
using System;

namespace uctx_vidp
{
	class CHAT
	{
		WyeCom.Console wye_console;
		string status_con;
		int id;

		void Log( string msg )
		{
			Console.WriteLine( msg );
		}

		internal void Execute( string msg )
		{
			Log( "-> " + msg );
			wye_console.Execute( msg );
		}

		void Main( int id )
		{
			this.id = id;
			wye_console = new WyeCom.ConsoleClass();
			wye_console.OnMessage += new WyeCom._IConsoleEvents_OnMessageEventHandler( wye_console_OnMessage );
			Execute( "\n.Start" );

			for( ; ; )
			{
				string msg = Console.ReadLine();
				if( string.IsNullOrEmpty( msg ) ) break;
				if( status_con != "active" ) break;
				Execute( "\ncon.SendEvent " + msg );
			}

			Execute( "\n.Destroy" );

			// wait for wye_console "destroyed" message to safely close main thread
			lock( wye_console )
			{
				System.Threading.Monitor.Wait( wye_console );
			}
		}

		static void Main( string[] args )
		{
			int id = 0;
			if( args.Length > 0 )
				int.TryParse( args[ 0 ], out id );
			new CHAT().Main( id );
		}

		void wye_console_OnMessage( string oid, string cmd, string value )
		{
			Log( string.Format( "<- {0}.{1}({2})", oid, cmd, value ) );

			if( string.IsNullOrEmpty( oid ) )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "ready" )
					{
						Execute
							( "\n.Set connect_timeout_seconds=1"
							+ "\n.Set proxy.settings=DIRECT"
							+ "\n.Set autodetect_sequence=tcp; http_tunnel;"
							+ "\n.Set server.host=localhost"
							+ "\n.Set server.port=85"
							+ "\n.Set server.port_ssl=447"
							+ "\n.Set server.port_http=90"
							+ "\n.Set protocol.key=test"
							+ "\n.Set id.conference=1"
							+ "\n.Set id.user=" + id
							+ "\n.Set protocol.is_master=" + ( id == 0 ? "1" : "0" )
							+ "\n.Set protocol.purpose=3"
							+ "\n.New con=Connection"
							);
					}
					else if( value == "destroyed" )
					{
						// signal to Main
						lock( wye_console )
						{
							System.Threading.Monitor.Pulse( wye_console );
						}
					}
				}
			}
			else if( oid == "con" )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "off" && status_con == null )
					{
						Execute( "\ncon.Connect" );
					}

					status_con = value;
				}
			}
		}
	}
}
CHAT does following:
1. Creates console, subscribes on callback, calls “\n.Start”
and waiting for message typing.
2. On (“”,”OnStatusChanged”,”ready”) sets parameters
and creates connection.
UCTX connection parameters are protocol.key=test, id.conference=1, protocol.purpose=3,
id.user=(got from application argument), protocol.is_master=(1 if id.user=0).
3. On (“con”,”OnStatusChanged”,”off”) initiates connecting sequence.
5. On user typed message calls “\n.SendEvent” with this message.
6. On user entered empty message calls “\n.Destroy” and waits before destroy will complete.
Now UCTX starts to destroy all internal objects with corresponding notifications.
7. On (“”,”OnStatusChanged”,”destroyed”) ends main thread waiting.

Video Publishing Example
Example contains 2 C# applications – video publisher (VIDP) and video subscriber (VIDS).
VIDP is capturing video camera and sends it to VIDS.
VIDS opens simple window with UIControl to show received video.
VIDP code:
using System;

namespace uctx_vidp
{
	class VIDP
	{
		WyeCom.Console wye_console;
		string status_con;
		string status_vp8;

		void Log( string msg )
		{
			Console.WriteLine( msg );
		}

		internal void Execute( string msg )
		{
			Log( "-> " + msg );
			wye_console.Execute( msg );
		}

		void Main()
		{
			wye_console = new WyeCom.ConsoleClass();
			wye_console.OnMessage += new WyeCom._IConsoleEvents_OnMessageEventHandler( wye_console_OnMessage );
			Execute( "\n.Start" );

			Console.ReadLine();

			Execute( "\n.Destroy" );

			// wait for wye_console "destroyed" message to safely close main thread
			lock( wye_console )
			{
				System.Threading.Monitor.Wait( wye_console );
			}
		}

		static void Main( string[] args )
		{
			new VIDP().Main();
		}

		void wye_console_OnMessage( string oid, string cmd, string value )
		{
			Log( string.Format( "<- {0}.{1}({2})", oid, cmd, value ) );

			if( string.IsNullOrEmpty( oid ) )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "ready" )
					{
						Execute
							( "\n.Set connect_timeout_seconds=1"
							+ "\n.Set proxy.settings=DIRECT"
							+ "\n.Set autodetect_sequence=tcp; http_tunnel;"
							+ "\n.Set server.host=localhost"
							+ "\n.Set server.port=85"
							+ "\n.Set server.port_ssl=447"
							+ "\n.Set server.port_http=90"
							+ "\n.Set protocol.key=test"
							+ "\n.Set id.conference=1"
							+ "\n.Set id.user=1"
							+ "\n.Set protocol.is_master=1"
							+ "\n.Set protocol.purpose=3"
							+ "\n.Set vds.id.device=0"
							+ "\n.Set vds.width=176"
							+ "\n.Set vds.height=144"
							+ "\n.Set vds.time_per_frame=2000000"
							+ "\n.Set vp8p.bitrate=256"
							+ "\n.Set vp8p.keyframe=4"
							+ "\n.Set vidp.id.channel=1"
							+ "\n.Set vidp.source=vsds"
							+ "\n.New vsds=VideoSource"
							+ "\n.New con=Connection"
							);
					}
					else if( value == "destroyed" )
					{
						// signal to Main
						lock( wye_console )
						{
							System.Threading.Monitor.Pulse( wye_console );
						}
					}
				}
			}
			else if( oid == "con" )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "off" && status_con == null )
					{
						Execute( "\ncon.Connect" );
					}
					else if( value == "active" )
					{
						Execute( "\ncon.New vp8=VideoPublisherVP8" );
					}

					status_con = value;
				}
			}
			else if( oid == "vp8" )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "off" && status_vp8 == null )
					{
						Execute
							( "\nvp8.Start"
							);
					}

					status_vp8 = value;
				}
			}
		}
	}
}
VIDP does following:
1. Creates console, subscribes on callback, calls “\n.Start”.
2. On (“”,”OnStatusChanged”,”ready”) sets parameters
and creates connection and video source.
Note that source for video publisher is video source (vidp.source=vsds).
UCTX connection parameters are protocol.key=test, id.conference=1, protocol.purpose=3,
id.user=1, protocol.is_master=1.
3. On (“con”,”OnStatusChanged”,”off”) initiates connecting sequence.
4. On (“con”,”OnStatusChanged”,”active”) creates video publisher with “vidp.id.channel=1″.
5. On (“vp8″,”OnStatusChanged”,”off”) starts video publisher.
After (“vp8″,”OnStatusChanged”,”ready”) application will wait
for started subscriber handshake.
6. On connected subscriber, publisher starts sending data.
7. On user pressed enter key calls “\n.Destroy” and waits before destroy will complete.
Now UCTX starts to destroy all internal objects with corresponding notifications.
8. On (“”,”OnStatusChanged”,”destroyed”) ends main thread waiting.
VIDS code:
using System;
using System.Windows.Forms;

namespace uctx_vids
{
	class VIDS
	{
		internal interface IView
		{
			WyeCom.IBaseObject GetUIControl();
			void Destroy();
		}

		WyeCom.Console wye_console;
		string status_con;
		string status_vids;
		IView view;
		bool was_destroyed;

		void Log( string msg )
		{
			Console.WriteLine( msg );
		}

		void Execute( string msg )
		{
			Log( "-> " + msg );
			wye_console.Execute( msg );
		}

		void Main()
		{
			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault( false );

			FormUIC form = new FormUIC( this );
			view = form;

			wye_console = new WyeCom.ConsoleClass();
			wye_console.OnMessage += new WyeCom._IConsoleEvents_OnMessageEventHandler( wye_console_OnMessage );

			Application.Run( form );

			// wait for wye_console "destroyed" message to safely close main thread
			lock( wye_console )
			{
				if( was_destroyed ) return;
				System.Threading.Monitor.Wait( wye_console );
			}
		}

		[STAThread]
		static void Main( string[] args )
		{
			new VIDS().Main();
		}

		void wye_console_OnMessage( string oid, string cmd, string value )
		{
			Log( string.Format( "<- {0}.{1}({2})", oid, cmd, value ) );

			if( string.IsNullOrEmpty( oid ) )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "ready" )
					{
						Execute
							( "\n.Set connect_timeout_seconds=1"
							+ "\n.Set proxy.settings=DIRECT"
							+ "\n.Set autodetect_sequence=tcp; http_tunnel;"
							+ "\n.Set server.host=localhost"
							+ "\n.Set server.port=85"
							+ "\n.Set server.port_ssl=447"
							+ "\n.Set server.port_http=90"
							+ "\n.Set protocol.key=test"
							+ "\n.Set id.conference=1"
							+ "\n.Set id.user=2"
							+ "\n.Set protocol.is_master=0"
							+ "\n.Set protocol.purpose=3"
							+ "\n.Set vids.id.channel=1"
							+ "\n.Set vids.id.channel_user=1"
							+ "\n.New con=Connection"
							);
					}
					else if( value == "destroyed" )
					{
						// signal to Main
						lock( wye_console )
						{
							was_destroyed = true;
							System.Threading.Monitor.Pulse( wye_console );
						}
					}
				}
			}
			else if( oid == "con" )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "off" && status_con == null )
					{
						Execute( "\ncon.Connect" );
					}
					else if( value == "active" )
					{
						Execute( "\ncon.New vids=VideoSubscriber" );
					}

					status_con = value;
				}
			}
			else if( oid == "vids" )
			{
				if( cmd == "OnStatusChanged" )
				{
					if( value == "off" && status_vids == null )
					{
						wye_console.ConnectExternal( "vids", view.GetUIControl() );

						Execute
							( "\nvids.Start"
							);
					}
					else if( value == "destroyed" )
					{
						view.Destroy();
					}

					status_vids = value;
				}
			}
		}

		internal void UIC_Init()
		{
			Execute( "\n.Start" );
		}

		internal void UIC_OnClick_Close()
		{
			Execute( "\n.Destroy" );
		}
	}
}
VIDS does following:
1. Creates console, subscribes on callback and shows form.
Form contains single UIControl on it.
2. On form started calls “\n.Start”.
3. On (“”,”OnStatusChanged”,”ready”) sets parameters and creates connection.
UCTX connection parameters are protocol.key=test, id.conference=1, protocol.purpose=3,
id.user=2, protocol.is_master=0.
4. On (“con”,”OnStatusChanged”,”off”) initiates connecting sequence.
5. On (“con”,”OnStatusChanged”,”active”) creates video subscriber
with “vids.id.channel=1″ and “vids.id.channel_user=1″.
6. On (“vids”,”OnStatusChanged”,”off”) connects UIControl to “vids” object
and starts video subscriber.
After (“vids”,”OnStatusChanged”,”ready”) application will wait
for started publisher response.
7. On active publisher, subscriber starts receiving data.
8. On user closed form window calls “\n.Destroy” and waits before destroy will complete.
Now UCTX starts to destroy all internal objects with corresponding notifications.
9. On (“”,”OnStatusChanged”,”destroyed”) ends main thread waiting.

More examples
Other examples are available in UCTX SDK.


Designed by Ucentrik Inc.
©2017 Ucentrik