Jul 8 2010

Silverlight proof points: Smooth Streaming Technology, NBC Online Video Monetization and Highlights Creation for the 2010 Winter Olympics

It’s now available a great technical whitepaper that highlights the usage of Silverlight Smooth streaming technology to stream live and on demand content for the 2010 Winter Olympics.

This Whitepaper goes into the technical details on how NBC in US inserted midstream ads and monetized the online content.

This is a follow on to the 4 case studies that were published in May 2010 on how NBC USA, CTV Canada, France TV, and NRK Norway  have used Silverlight and Smooth Streaming technologies during the Winter Olympics.

OlympicsWorkflow

The Technical Whitepaper covers the following topics:

- A Solution Overview;

- Clip Creation and Ad Insertion;

- Rough Cut Editor;

- Inserting Ads, Ad Templates, Ad Logic;

- Ads delivered in VOD;

- Monitoring Ads.

 

 

Click here to read the article and… Happy Silverlighting!


Oct 10 2009

IIS Media Services 3.0 released: Silverlight and Live Smooth Streaming

“IIS Media Services, an integrated HTTP-based media delivery platform, delivers true HD (720p+) streaming and provides real-time logging to measure media investments. By offering a complete media delivery platform together with a traditional Web server, rich dynamic Web sites can now be managed and administered from a single Web platform: IIS”

These extensions are now available:

  • Live Smooth Streaming: live adaptive streaming to Silverlight;
  • Smooth Streaming: adaptive streaming to Silverlight;
  • Advanced Logging;
  • Bit Rate Throttling;
  • Web Playlists.

Useful links:


Aug 14 2009

Silverlight 3 / Expression 3 behaviors for enabling Multi-touch gestures

In the previous post, I’ve described a basic example of WPF custom control for reusing multi-touch functionalities across applications. The same task can be achieved in Silverlight 3 using the new touch apis (check out this great article by Tim Heuer to get started), in addition we can use the new behaviors in order to write and simply reuse the code (a quick note: at this stage Silverlight 3 only supports basic touch events, gesture messages are not available).

To start I’ve added two simple behaviors named TouchDrag and TouchZoom to the Multi-Touch Codeplex project.

These new objects can be used in xaml by inserting the following code (the System.Windows.Interactivity namespace can be imported from the Expression Blend 3 SDK, already available if Blend 3 is installed):

<UserControl x:Class="SilverlightMultiTouch.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/ presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d= "http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/ markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" Width="1280" Height="800"
    xmlns:myControls="clr-namespace:MultiTouch.Controls.Silverlight; assembly=MultiTouch.Controls.Silverlight"
    xmlns:behaviors="clr-namespace: MultiTouch.Controls.Silverlight.Behaviors; assembly=MultiTouch.Controls.Silverlight"
    xmlns:interactivity="clr-namespace: System.Windows.Interactivity; assembly=System.Windows.Interactivity"
             >
    <Canvas Background="Black">
        <!-- Example using Behaviors -->
        <Canvas>
            <interactivity:Interaction.Behaviors>
                <behaviors:TouchDrag TouchDragEnabled="True"/>
                <behaviors:TouchZoom TouchZoomEnabled="True"/>
            </interactivity:Interaction.Behaviors>
            <Image Source="Images/image.png" Height="597" Width="448" Canvas.Left="404" Canvas.Top="96"/>
        </Canvas>
    </Canvas>
</UserControl>

Have you seen the previous lines of code? The touch features are simply associated to the Image object using this xaml:

            <interactivity:Interaction.Behaviors>
                <behaviors:TouchDrag TouchDragEnabled="True"/>
                <behaviors:TouchZoom TouchZoomEnabled="True"/>
            </interactivity:Interaction.Behaviors>

The TouchDrag and TouchZoom behaviors can be defined in code-behind in this way:

TouchDrag.cs

    public class TouchDrag : Behavior<FrameworkElement>
    {
        //Dependency property for enabling the TouchDrag
        public static readonly DependencyProperty TouchDragEnabledProperty =
            DependencyProperty.Register("TouchDragEnabled", typeof(bool), typeof(TouchDrag), new PropertyMetadata(false));

        [Category("Target Properties")]
        public bool TouchDragEnabled { get; set; }

        //Occurs when the primary point is touched down
        private bool _touchDown = false;

        //Origin point
        private Point _ptOrigin;

        //Translate Transform
        TranslateTransform _translateTransform;

        /// Initialize the behavior
        protected override void OnAttached()
        {
            base.OnAttached();
            Touch.FrameReported += AssociatedObjectTouchFrameReported;
        }

        /// Occurs when detaching the behavior
        protected override void OnDetaching()
        {
            base.OnDetaching();
            Touch.FrameReported -= AssociatedObjectTouchFrameReported;
        }

        /// Touch Frame Handler
        private void AssociatedObjectTouchFrameReported(object sender, TouchFrameEventArgs e)
        {
            //Handler for the Touch events
            if (this.TouchDragEnabled)
            {
                if (e.GetPrimaryTouchPoint(AssociatedObject) != null)
                {
                    switch (e.GetPrimaryTouchPoint( AssociatedObject).Action)
                    {
                        case TouchAction.Up:
                            this.AssociatedObjectTouchUp(sender, e);
                            break;
                        case TouchAction.Move:
                            this.AssociatedObjectTouchMove(sender, e);
                            break;
                        case TouchAction.Down:
                            this.AssociatedObjectTouchDown(sender, e);
                            break;
                    }
                }
            }
        }

        /// Touch Down Handler
        private void AssociatedObjectTouchDown(object sender, TouchFrameEventArgs e)
        {
            this._touchDown = true;
            this.AssociatedObject.Opacity = .75;
            this._ptOrigin = e.GetPrimaryTouchPoint(AssociatedObject).Position;

            //Initialize the Translate transform and the TransformGroup
            if (this._translateTransform == null)
            {
                this._translateTransform = new TranslateTransform();
                if ((this.AssociatedObject.RenderTransform == null) || !(this.AssociatedObject.RenderTransform is TransformGroup))
                    this.AssociatedObject.RenderTransform = new TransformGroup();
                if (this.AssociatedObject.RenderTransform is TransformGroup)
                    (this.AssociatedObject.RenderTransform as TransformGroup).Children.Add( this._translateTransform);
            }

            //Suspend Mouse promotion
            e.SuspendMousePromotionUntilTouchUp();
        }

        /// Handle the Touch movement
        private void AssociatedObjectTouchMove(object sender, TouchFrameEventArgs e)
        {
            if (this._touchDown)
            {
                //Find the new position
                Point newPosition = e.GetPrimaryTouchPoint(AssociatedObject.Parent as FrameworkElement).Position;

                //Drag the Control using the TranslateTransform
                this._translateTransform.X = (newPosition.X - _ptOrigin.X); this._translateTransform.Y = (newPosition.Y - _ptOrigin.Y);
            }
        }

        /// Touch Up Handler
        private void AssociatedObjectTouchUp(object sender, TouchFrameEventArgs e)
        {
            // turn off drag
            this._touchDown = false;
            AssociatedObject.Opacity = 1;
        }
    }

TouchZoom.cs:

    public class TouchZoom : Behavior<FrameworkElement>
    {
        //Dependency property for enabling the TouchZoom
        public static readonly DependencyProperty TouchDragEnabledProperty =
            DependencyProperty.Register("TouchZoomEnabled", typeof(bool), typeof(TouchZoom), new PropertyMetadata(false));

        [Category("Target Properties")]
        public bool TouchZoomEnabled { get; set; }

        //Occurs when the primary point is touched down
        private bool _touchDown = false;

        //Origin points
        private TouchPointCollection _tpInitialPoints;

        //ScaleTransform
        ScaleTransform _scaleTransform;

        /// Calculate the distance between two points
        private double Distance(Point point1, Point point2)
        {
            try
            {
                return Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y));
            }
            catch { return double.NaN; }
        }

        /// Calculate the MidPoint
        private Point MidPoint(Point point1, Point point2)
        {
            return new Point((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
        }

        /// Initialize the behavior
        protected override void OnAttached()
        {
            base.OnAttached();
            Touch.FrameReported += AssociatedObjectTouchFrameReported;
        }

        /// Occurs when detaching the behavior
        protected override void OnDetaching()
        {
            base.OnDetaching();
            Touch.FrameReported -= AssociatedObjectTouchFrameReported;
        }

        /// Touch Frame Handler
        private void AssociatedObjectTouchFrameReported(object sender, TouchFrameEventArgs e)
        {
            if (this.TouchZoomEnabled)
            {
                TouchPointCollection tpCollection = e.GetTouchPoints(this.AssociatedObject);
                tpCollection.ToList().ForEach(tp =>
                    {
                        switch (tp.Action)
                        {
                            case TouchAction.Up:
                                this.AssociatedObjectTouchUp(sender, e);
                                break;
                            case TouchAction.Move:
                                this.AssociatedObjectTouchMove(sender, e);
                                break;
                            case TouchAction.Down:
                                this.AssociatedObjectTouchDown(sender, e);
                                break;
                        }
                    });
            }
        }

        /// Touch Down Handler
        private void AssociatedObjectTouchDown(object sender, TouchFrameEventArgs e)
        {
            //Initialize the parameters
            this._touchDown = true;
            this.AssociatedObject.Opacity = .75;
            this._tpInitialPoints = e.GetTouchPoints(this.AssociatedObject);

            //Initialize the Scale transform
            if (this._scaleTransform == null)
            {
                this._scaleTransform = new ScaleTransform();
                if ((this.AssociatedObject.RenderTransform == null) || !(this.AssociatedObject.RenderTransform is TransformGroup))
                    this.AssociatedObject.RenderTransform = new TransformGroup();
                if (this.AssociatedObject.RenderTransform is TransformGroup)
                    (this.AssociatedObject.RenderTransform as TransformGroup).Children.Add( this._scaleTransform);
            }
            //TODO: e.SuspendMousePromotionUntilTouchUp();
        }

        /// Handle the Touch movement
        private void AssociatedObjectTouchMove(object sender, TouchFrameEventArgs e)
        {
            if (this._touchDown)
            {
                //Find the new points
                TouchPointCollection newPoints = e.GetTouchPoints(AssociatedObject.Parent as FrameworkElement);
                if (newPoints!=null && this._tpInitialPoints!=null)
                    if (this._tpInitialPoints.Count == 2 && newPoints.Count == 2)
                    {
                        //Zoom the Control using the ScaleTransform
                        double ratio = this.Distance( newPoints.First().Position, newPoints.Last().Position) /
                            this.Distance( this._tpInitialPoints.First().Position, this._tpInitialPoints.Last().Position);
                        if (ratio != double.NaN)
                        {
                            Point midPoint = this.MidPoint( newPoints.First().Position, newPoints.Last().Position);
                            this._scaleTransform.CenterX = midPoint.X; this._scaleTransform.CenterY = midPoint.Y;
                            this._scaleTransform.ScaleX = ratio; this._scaleTransform.ScaleY = ratio;
                        }
                    }
            }
        }

        /// Touch Up Handler
        private void AssociatedObjectTouchUp(object sender, TouchFrameEventArgs e)
        {
           // turn off Zoom mode
           this._touchDown = false;
           this.AssociatedObject.Opacity = 1;
        }
    }

The behavior approach is very powerful, in this way you can share functionalities between Visual Studio and Expression Blend 3 in a simple way, making the code maintainable and simply reusable in different projects.

The source code is available for download on http://multitouch.codeplex.com.

If you have a multi-touch enabled devices, the demo application is available on-line here, featuring Drag and Zoom gestures.

Hope this helps and… happy Silverlighting!


Aug 14 2009

A WPF custom control for enabling Windows 7 Multi-touch gestures

Windows 7 is now available, it’s time to build new user experiences using the new stuff, like multi-touch!

To play with this new feature, I have started a Codeplex project at http://multitouch.codeplex.com containing a first WPF custom control (and some Silverlight 3 behaviors, check out the next posts for more info) to enable touch drag, zoom and rotation gestures using the .NET wrapper classes available on http://code.msdn.microsoft.com/WindowsTouch (see also my other post about the same topic).

The touch events are managed in the ApplyTemplate method:

       public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (Windows7.Multitouch.TouchHandler. DigitizerCapabilities.IsMultiTouchReady)
            {
                //Find the Window containing the CustomControl
                DependencyObject dpParent = this;
                do { dpParent = LogicalTreeHelper.GetParent(dpParent); } while (dpParent.GetType().BaseType != typeof(Window));
                //Enable Stylus events
                if (dpParent != null) Factory.EnableStylusEvents(dpParent as Window);

                //Get the touch Area
                UIElement touchArea = (UIElement)GetTemplateChild("_touchArea");

                //Handle Stylus events
                if (touchArea != null)
                {
                   this.StylusDown += (s, e) => { _processor.ProcessDown((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };
                   this.StylusUp += (s, e) => { _processor.ProcessUp((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };
                   this.StylusMove += (s, e) => { _processor.ProcessMove((uint)e.StylusDevice.Id, e.GetPosition(touchArea).ToDrawingPointF()); };

                   //Handle the ManipulationDelta and the gestures
                   this._processor.ManipulationDelta += ProcessManipulationDelta;
                   this._processor.PivotRadius = 2;
                }
            }
        }

When the ManipulationDelta event occurs, the ProcessManipulationDelta handler applies the Rotate, Translate and Scale transforms:

        private void ProcessManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            if (this.MultiTouchEnabled)
            {
                TranslateTransform _translate = (TranslateTransform)GetTemplateChild("_translate");
                if (_translate != null)
                {
                    _translate.X += e.TranslationDelta.Width;
                    _translate.Y += e.TranslationDelta.Height;
                }

                RotateTransform _rotate = (RotateTransform)GetTemplateChild("_rotate");
                if (_rotate != null)
                    _rotate.Angle += e.RotationDelta * 180 / Math.PI;

                ScaleTransform _scale = (ScaleTransform)GetTemplateChild("_scale");
                if (_scale != null)
                {
                    _scale.ScaleX *= e.ScaleDelta;
                    _scale.ScaleY *= e.ScaleDelta;
                }
            }
        }

A dependency property named MultiTouchEnabled is also defined in order to enable and disable the touch features directly using XAML:

        public bool MultiTouchEnabled
        {
            get { return (bool)GetValue(MultiTouchEnabledProperty); }
            set { SetValue(MultiTouchEnabledProperty, value); }
        }

        public static readonly DependencyProperty MultiTouchEnabledProperty =
            DependencyProperty.Register("MultiTouchEnabled", typeof(bool), typeof(MultiTouchView), null);

The usage of this custom control is very simple, just wrap the code you want to touch-enable in this way:

<Window x:Class="WpfMultiTouch.MultiTouchWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/ presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WPF Multi Touch gestures example" Width="1280" Height="800"
    xmlns:myControls="clr-namespace:MultiTouch.Controls.WPF; assembly=MultiTouch.Controls.WPF"
        >
    <Canvas Background="Black">
        <myControls:MultiTouchView MultiTouchEnabled="True">
            <myControls:MultiTouchView.Template>
                <ControlTemplate>
                    <Canvas x:Name="_touchArea">
                        <Viewbox RenderTransformOrigin="0.5, 0.5">
                            <Image Source="Images/image.png" Width="500"/>
                            <Viewbox.RenderTransform>
                                <TransformGroup>
                                    <RotateTransform x:Name="_rotate" Angle="0"/>
                                    <ScaleTransform x:Name="_scale" ScaleX="1" ScaleY="1"/>
                                    <TranslateTransform x:Name="_translate" X="0" Y="0"/>
                                </TransformGroup>
                            </Viewbox.RenderTransform>
                        </Viewbox>
                    </Canvas>
                </ControlTemplate>
            </myControls:MultiTouchView.Template>
        </myControls:MultiTouchView>
    </Canvas>
</Window>

This approach is very powerful, it’s possible to enable multi-touch gestures by simply wrapping the objects inserted in the XAML code inside the MultiTouchView custom control.

The source code is available on Codeplex, including a basic Silverlight 3 implementation using the new touch APIs and behaviors.


Jun 30 2009

Multi Touch enabling your WPF application

Recently I had the possibility to work on some multi-touch stuffs using the .NET wrappers for the touch APIs included in Windows 7 RC.

Do you remember Simon? As described by Wikipedia:

Simon is an electronic game of rhythm and memory skill invented by Ralph H. Baer and Howard J. Morrison,[1] with the software programming being done by Lenny Cope and manufactured and distributed by Milton Bradley. Simon was launched in 1978 at Studio 54 in New York City and became an immediate success. It became a pop culture symbol of the 1980s.”

And… here we go, let’s connect to http://simon.codeplex.com and play with the Silverlight on-line version built by David J Kelley:

Simon

How to add basic multi touch gestures (rotation, scale and transform) to the WPF version? It’s quite impressive to look at the amount of code required using the Windows 7 Multitouch .NET Interop Sample Library: just insert some transforms in the User Control XAML

<Viewbox x:Name="_simon" RenderTransformOrigin="0.5, 0.5">
<uc:Simon/>
<Viewbox.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="_rotate" Angle="0"/>
<ScaleTransform x:Name="_scale" ScaleX="1" ScaleY="1"/>
<TranslateTransform x:Name="_translate" X="0" Y="0"/>
</TransformGroup>
</Viewbox.RenderTransform>
</Viewbox>

And then use this code to control the TransformGroup using the Multi touch engine:

using System;
using System.Windows;
using Windows7.Multitouch.Manipulation;
using Windows7.Multitouch.WPF;

namespace SimonWPF
{
public partial class MultiTouchWindow1 : Window
{
ManipulationProcessor _processor = new ManipulationProcessor(ProcessorManipulations.ALL);

public MultiTouchWindow1()
{
InitializeComponent();

Loaded += (s, e) => { Factory.EnableStylusEvents(this); };

StylusDown += (s, e) => { _processor.ProcessDown((uint)e.StylusDevice.Id,
e.GetPosition(_canvas).ToDrawingPointF()); };

StylusUp += (s, e) => { _processor.ProcessUp((uint)e.StylusDevice.Id,
e.GetPosition(_canvas).ToDrawingPointF()); };

StylusMove += (s, e) => { _processor.ProcessMove((uint)e.StylusDevice.Id,
e.GetPosition(_canvas).ToDrawingPointF()); };

_processor.ManipulationDelta += ProcessManipulationDelta;
_processor.PivotRadius = 2;
}

private void ProcessManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
_translate.X += e.TranslationDelta.Width;
_translate.Y += e.TranslationDelta.Height;

_rotate.Angle += e.RotationDelta * 180 / Math.PI;

_scale.ScaleX *= e.ScaleDelta;
_scale.ScaleY *= e.ScaleDelta;
}
}
}

It’s also possible to verify if your hardware supports multi touch:

if (Windows7.Multitouch.TouchHandler.
DigitizerCapabilities.IsMultiTouchReady)
{
//MultiTouch is available
this.StartupUri = new Uri("MultiTouchWindow1.xaml", UriKind.Relative);
}
else this.StartupUri = new Uri("Window1.xaml", UriKind.Relative);

The complete code is available on CodePlex: http://simon.codeplex.com.

Enjoy Windows 7 Multi touch! And now… waiting for Silverlight 3 :)

The multi touch library is governed by this license.


May 27 2009

Running Silverlight 3 apps on Windows Embedded Standard 2009 using Windows 7 RC and Virtual PC

Silverlight 3 on Windows Embedded Standard 2009

When I read this thread on the Silverlight forum, I wanted to test the possibility to run Rich Internet Applications built using Silverlight 3 on an embedded device powered by the last version of Windows Embedded, Windows Embedded Standard 2009 (WES).

To rapidly deploy the image, I decided to use Windows Virtual PC Beta and the .VHD file support available on Windows 7.

These are the steps:

1 – Install Windows 7 RC on the test PC

2 – Install Windows Virtual PC and Virtual Windows XP

3 - Install Windows Embedded Standard 2009 Studio (the trial is available here)

4 – Run the utility “tap.exe” in a command prompt of Virtual Windows XP in order to obtain a list of the devices

5 - Generate a WES 2009 image in the directory “c:\WES2009Img” using the WES utility “Target designer” by importing the file obtained in the preceding step. It’s important to enable the “Silverlight 1.0” component in order to install the files required for the Silverlight installation

6 – Create a new Virtual Machine to host the generated image

7 – Mount, format and make active the .vhd by using the “Disk Management” utility of Windows 7

8 – Copy the files and folders of the Windows Embedded image (contained in “c:\WES2009Img”) in the .vhd by assigning a drive letter to the virtual disk file

9 – Boot the Virtual Machine from Windows Virtual PC

10 – Install the Silverlight 3 plug-in and enjoy Rich Internet Applications on your Windows Embedded Standard virtual machine ;)


May 20 2009

Media Center SDK for Windows 7 RC now available for public download

Just found the news on the Aaron Stebner‘s blog, with some useful links:


May 12 2009

Media Streaming with Windows 7

Check out this great article by Engineering Windows 7.


May 12 2009

Windows 7 multi-touch programming

Some useful resources about this topic:


Mar 19 2009

IdentityMine Introduces the IdentityMine Gesture Engine to Support Advanced Multi-Touch Development

Read the complete articles here and here.

Direct link: http://www.identitymine.com/windows7/

YouTube videos: