Migrating Extensions

IceLink 2 has a number of ways in which you can extend the capabilities of the core SDK. With IceLink 3, you have even more flexibility to extend the SDK. Before you can get started on that though, you need to port your existing modifications over to version 3. This section will help you with that.

Customizing the Layout Manager

In IceLink 2, you can provide your own layout manager implementation to customize the way in which video feeds are drawn to the screen. To do so, you create a class that inherits from BaseLayoutManager, and you implement its four abstract methods.

// IceLink 2
public class LayoutManager : FM.IceLink.BaseLayoutManager
{
    public override void AddToContainer(object control) { ... }
    public override void RemoveFromContainer(object control) { ... }
    public override void RunOnUIThread(FM.DoubleAction<object, object> action, object arg1, object arg2) { ... }
    public override void ApplyLayout() { ... }
}
// IceLink 2
public class LayoutManager : fm.icelink.BaseLayoutManager {
    @Override public void addToContainer(Object control) { ... }
    @Override public void removeFromContainer(Object control) { ... }
    @Override public void runOnUIThread(fm.DoubleAction<Object, Object> action, Object arg1, Object arg2) { ... }
    @Override public void applyLayout() { ... }
}
// IceLink 2
@interface LayoutManager : FMIceLinkBaseLayoutManager
@end

@implementation LayoutManager
- (void)addToContainer(NSObject* control) { ... }
- (void)removeFromContainer(NSObject* control) { ... }
- (void)runOnUIThread(FMDoubleAction* action, NSObject* arg1, NSObject* arg2) { ... }
- (void)applyLayout() { ... }
@end
// IceLink 2
public class LayoutManager : FMIceLinkLayoutManager {
    override func addToContainer(control:UIView) { ... }
    override func removeFromContainer(control:UIView) { ... }
    override func runOnUIThread(action:FMDoubleAction, arg1:NSObject, arg2:NSObject) { ... }
    override func applyLayout() { ... }
}
// IceLink 2
function LayoutManager(container) {
    fm.icelink.LayoutManager.call(this, container);
}

LayoutManager.prototype.addToContainer = function(control) { ... }
LayoutManager.prototype.removeFromContainer = function(control) { ... }
LayoutManager.prototype.runOnUIThread = function(action, arg1, arg2) { ... }
LayoutManager.prototype.applyLayout = function() { ... }


In IceLink 3, you instead inherit from LayoutManager<T>. You must specify the type of view control that you intend to use in advance, using the generic type parameter. As well, the names of the abstract methods have changed slightly:

  • AddToContainer is now AddView.
  • RemoveFromContainer is now RemoveView.
  • RunOnUIThread is now DispatchToMainThread.
  • ApplyLayout is now Layout.

The changes are shown below:

// IceLink 3
public class LayoutManager : FM.IceLink.LayoutManager<System.Windows.Controls.Image>
{
    protected override void AddView(System.Windows.Controls.Image view) { ... }
    protected override void RemoveView(System.Windows.Controls.Image view) { ... }
    protected override void DispatchToMainThread(FM.IceLink.Action2<object, object> action, object arg1, object arg2) { ... }
    protected override void Layout() { ... }
}
// IceLink 3
public class LayoutManager : fm.icelink.LayoutManager<java.awt.Component> {
    @Override protected void addView(java.awt.Component view) { ... }
    @Override protected void removeView(java.awt.Component view) { ... }
    @Override protected void dispatchToMainThread(fm.icelink.Action2<Object, Object> action, Object arg1, Object arg2) { ... }
    @Override protected void layout() { ... }
}
// IceLink 3
@interface LayoutManager : FMIceLinkLayoutManager<UIView>
@end

@implementation LayoutManager
- (void)addView(UIView* view) { ... }
- (void)removeView(UIView* view) { ... }
- (void)dispatchToMainThread(FMIceLinkAction2* action, NSObject* arg1, NSObject* arg2) { ... }
- (void)layout() { ... }
@end
// IceLink 3
public class LayoutManager : FMIceLinkLayoutManager {
    override func addView(view:UIView) { ... }
    override func removeView(view:UIView) { ... }
    override func dispatchToMainThread(action:FMIceLinkAction2, arg1:NSObject, arg2:NSObject) { ... }
    override func layout() { ... }
}
// IceLink 3
function LayoutManager(container) {
    fm.icelink.LayoutManager.call(this, container);
}

LayoutManager.prototype.addView = function(view) { ... }
LayoutManager.prototype.removeView = function(view) { ... }
LayoutManager.prototype.dispatchToMainThread = function(action, arg1, arg2) { ... }
LayoutManager.prototype.layout = function() { ... }


Migration Steps

  • Specify your view type as the generic parameter.
  • Rename AddToContainer to AddView.
  • Rename RemoveFromContainer to RemoveView.
  • Rename RunOnUIThread to DispatchToMainThread.
  • Rename ApplyLayout to Layout.

More Information

Migrating Audio Capture Providers

In IceLink 3, AudioSource has replaced AudioCaptureProvider.

// IceLink 2
public class MyAudioCaptureProvider : AudioCaptureProvider
{
    public override string[] GetDeviceNames() { ... }
    public override string GetLabel() { ... }

    public override void Initialize(AudioCaptureInitializeArgs captureArgs) { ... }
    public override void Destroy() { ... }

    public override bool Start() { ... }
    public override void Stop() { ... }
}


// IceLink 3
public class MyAudioSource : AudioSource
{
    public override SourceInput[] Inputs { get { ... } } // optional
    public override string Label { get { ... } }

    public MyAudioSource(AudioFormat outputFormat) : base(format) { ... }
    public override DoDestroy() { ... } // optional

    protected override Future<object> DoStart() { ... }
    protected override Future<object> DoStop() { ... }
}


Migration Steps

  • Replace GetLabel with the Label property.
  • Replace GetDeviceNames with the Inputs property (or remove it entirely).
  • Replace Start and Stop with DoStart and DoStop, noting that they must return a Future, even if the operation is resolved synchronously.
  • Remove Initialize and Destroy, moving code into the constructor and DoDestroy methods.

More Information

Migrating Video Capture Providers

In IceLink 3, VideoSource has replaced VideoCaptureProvider.

// IceLink 2
public class MyVideoCaptureProvider : VideoCaptureProvider
{
    public override string[] GetDeviceNames() { ... }
    public override string GetLabel() { ... }

    public override void Initialize(VideoCaptureInitializeArgs captureArgs) { ... }
    public override void Destroy() { ... }

    public override bool Start() { ... }
    public override void Stop() { ... }
}

// IceLink 3
public class MyVideoSource : VideoSource
{
    public override SourceInput[] Inputs { get { ... } } // optional
    public override string Label { get { ... } }

    public MyVideoSource(VideoFormat outputFormat) : base(format) { ... }
    public override DoDestroy() { ... } // optional

    protected override Future<object> DoStart() { ... }
    protected override Future<object> DoStop() { ... }
}


Migration Steps

  • Replace GetLabel with the Label property.
  • Replace GetDeviceNames with the Inputs property (or remove it entirely).
  • Replace Start and Stop with DoStart and DoStop, noting that they must return a Future, even if the operation is resolved synchronously.
  • Remove Initialize and Destroy, moving code into the constructor and DoDestroy methods.

More Information

Migrating Audio Render Providers

In IceLink 3, AudioSink has replaced AudioRenderProvider.

// IceLink 2
public class MyAudioRenderProvider : AudioRenderProvider
{
    public override void Initialize(AudioRenderInitializeArgs renderArgs) { ... }
    public override void Destroy() { ... }

    public override void Render(AudioBuffer buffer) { ... }
}

// IceLink 3
public class MyAudioSink : AudioSink
{
    public override string Label { get { ... } }
    protected override void DoDestroy() { ... }
    protected override void DoProcessFrame(AudioFrame frame, AudioBuffer inputBuffer) { ... }
}


Migration Steps

  • Add the new Label property.
  • Remove Initialize and Destroy, moving code into the constructor and DoDestroy methods.

More Information

Migrating Video Render Providers

In IceLink 3, VideoSink has replaced VideoRenderProvider.

// IceLink 2
public class MyVideoRenderProvider : VideoRenderProvider
{
    public override void Initialize(VideoRenderInitializeArgs renderArgs) { ... }
    public override void Destroy() { ... }

    public override void Render(VideoBuffer buffer) { ... }
}

// IceLink 3
public class MyVideoSink : VideoSink
{
    public override string Label { get { ... } }
    protected override void DoDestroy() { ... }
    protected override void DoProcessFrame(VideoFrame frame, VideoBuffer inputBuffer) { ... }
}

Migration Steps

  • Add the new Label property.
  • Remove Initialize and Destroy, moving code into the constructor and DoDestroy methods.

More Information

Wrapping Up

By now you have converted most of your application to IceLink 3. There may still be some niche features you are using, that you do not know how to convert properly. The next section is catch-all for anything that remains, so read on if you are still having trouble.