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!

Microsoft Surface Toolkit for Windows Touch Beta available for download

The Microsoft Surface Toolkit for Windows Touch Beta is a set of controls, APIs, templates, sample applications and documentation currently available for Surface developers.

With the .NET Framework 4.0, Windows Presentation Framework 4.0 (WPF), and this toolkit, Windows Touch developers can quickly and consistently create advanced multitouch applications for Windows Touch PCs.

This toolkit also provides a jump-start for Surface application developers to prepare for the next version of Microsoft Surface. Use it to take advantage of the innovative Surface technology and user interface to develop your own rich and intuitive multitouch experiences for a variety of Windows Touch devices.”

Links:

Enjoy!

A Silverlight / Expression Blend behavior to add Multi-Touch Manipulation and Inertia

I’ve updated the behavior available in the Expression Community gallery adding Multi-Touch manipulation (translation, rotation and zoom) and inertia effects using code from the Surface Manipulations and Inertia Sample for Microsoft Silverlight.

To enable Multi-Touch in your code simply download the behavior from here, add the project “MultiTouch.Behaviors.Silverlight” to a Visual Studio solution and then enable the gestures in XAML:

<UserControl x:Class="SilverlightMultiTouch.MainPage"
...
xmlns:interactivity="clr-namespace:System.Windows.Interactivity; assembly=System.Windows.Interactivity"
xmlns:behaviors="clr-namespace:MultiTouch.Behaviors.Silverlight; assembly=MultiTouch.Behaviors.Silverlight"
...
>

<Canvas>
  <Image Source="Images/Desert.jpg">
     <interactivity:Interaction.Behaviors>
         <behaviors:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True" TouchTranslateEnabled="True" TouchScaleEnabled="True"/>
     </interactivity:Interaction.Behaviors>
  </Image>

  <Image Source="Images/Jellyfish.jpg">
     <interactivity:Interaction.Behaviors>
         <behaviors:MultiTouchManipulationBehavior InertiaEnabled="True" TouchRotateEnabled="True" TouchTranslateEnabled="True" TouchScaleEnabled="True"/>
     </interactivity:Interaction.Behaviors>
  </Image>
</Canvas>

The MultiTouchManipulationBehavior also contains some dependency properties (TouchRotateEnabled, TouchTranslateEnabled, TouchScaleEnabled and InertiaEnabled) to enable the corresponding gestures.

The example contains Multi-Touch manipulations applied to some Image controls and a Smooth streaming player of the Silverlight Media Framework.

I’ve also posted to CodePlex a sample using WPF 4 based on the article “Introduction to WPF 4 Multitouch” by Jaime Rodriguez.

Hope this helps and Happy Silverlighting!

Microsoft Surface Manipulations and Inertia Sample for Silverlight available for download

Just to point out this [awesome!] download available from the Microsoft Surface team, intended only for educational purposes.

From the main site:

"Multitouch support in Windows 7 allows applications to blur the lines between computers and the real world. Touch-optimized applications entice users to touch the objects on the screen, drag them across the screen, rotate and resize them, and flick them across the screen by using their fingers. The manipulations and inertia processor classes allow graphical user interface (GUI) components to move in a natural and intuitive way. Manipulations enable users to move, rotate, and resize components by using their fingers. Inertia enables users to move components by applying forces on the components, such as flicking the component across the screen. The contents of this sample are covered by the Microsoft Surface SDK 1.0 SP1 license agreement, with any additional restrictions noted in the Readme file. The purpose of this download is educational use only and is made available "as-is" without support."

Thanks to Jesse Bishop and SilverlightShow for the link!

Having fun with Silverlight 4 Beta and the Speech APIs

Silverlight 4 Beta is now available, one of the more interesting features is the ability to use Late Binding for automation APIs via the new dynamic keyword and the ComAutomationFactory class.

A great example is already available on the official http://silverlight.net site, using automation to control Excel in trusted applications.

With the same approach it’s possible to control any object exposed via COM so I’ve coded a (very simple) example to demonstrate the usage of the Speech APIs using this new automation bridge (thanks to Justin Angel on Twitter for the inspiration :)).

Just reference in your Silverlight 4 Beta project the dll Microsoft.CSharp.dll contained in the SDK folder to enable the usage of the dynamic keyword.

Then enable elevated-trust by activating the Out of Browser mode and clicking on the “Require elevated trust when running out of browser” checkbox:

ElevatedTrustOOB

The code used is very simple, just create an instance of the COM object using the ComAutomationFactory.CreateObject() method:

dynamic speech = ComAutomationFactory.CreateObject("Sapi.SpVoice");

Then use the Speak method to make Silverlight speak (sorry, no code completion here, we’re using late binding):

speech.Speak("Hi Guys! This is Silverlight 4 Beta speaking!");

The complete Silverlight 4 Beta project is available for download here.

SpeechCapture

Have fun and happy Silverlighting!

My Twitter Lists

Twitter has just enabled a new feature named “Lists” which permits to organize in categories the people you are following and make their tweets available to others. In this way it’s very simple to navigate the various subjects, follow the lists created by other people and subscribe to them.

I’ve tried this new functionality and created my own lists about Silverlight-related stuff, feel free to subscribe here if you find useful:

http://twitter.com/davidezordan/lists

Happy Silverlighting!

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!

Silverlight on iPhone? MonoTouch!

MonoTouch is the Mono edition for iPhone and iPod. It will enable developers to compile for these devices taking advantage of the iPhone APIs and reusing .NET skills.

As reported in the roadmap, version 2.0 should contain a Silverlight to iPhone compiler :)

Check out the project site: http://mono-project.com/MonoTouch

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.