Outlook on my PC and Phone and Keeping Organized

This message has nothing to do with Silverlight  Feel free to skip it.

I have been struggling since I joined Microsoft to ensure that

  • I don’t miss any messages that are important
  • I spend less time managing my 600+ daily emails *
  • I file everything away in case I need it later
  • I can find things quickly

(* I archive frequently, and read feverishly, but a quick search found 2300 unread emails as I wrote this).

This is made much more complicated because I look at my email through three views: on my desktop, via the web (rare) and via my phone (frequent).  Set aside the web; when I’m looking via my desktop I don’t mind if new messages show up in a folder, and folders help keep me organized.

FuzeMy new phone is the AT&T Fuze which I’m coming to love.  but like the Dash before it, it is designed  to strongly favor the inbox. It will synchronize with any folders I want, but the tilt towards the inbox is strong enough that messages elsewhere are easy to miss.

 

 


(NB: I don’t use the "touch flow" interface shown here)

 

 

Solving All My Outlook Issues At Once

I have tried various solutions, but I’ve finally hit on one I really like, and I thought I’d write it up briefly in case it might simplify your life.  The key, or me, is to

  1. make sure that everything I care to see goes to my inbox
  2. I don’t have to file (nearly) anything
  3. Things I don’t need to see do not go to my inbox.

This is all accomplished with a couple very simple rules.  First, I created a category called "Filed"  Then, for nearly every person or group that I care to see, I created a rule that told Outlook to make a copy of the message and file it on arrival and to mark the original (in the inbox) as in the category filed.  Thus, when looking at my inbox, I see this:

Filed 

As you can see, all but one of the messages is already marked filed. I can then tick through the messages, deleting them as I read them, knowing that they are already filed away where I want them.

(I could use different categories rather than just "filed" to indicate where they are filed, but since I have a couple hundred folders that would get tricky).

Most important, since all the messages now go to the inbox (and are not "moved" by a rule but rather copied) I know I’m seeing them on the phone.

Here are my basic rules:

Anything I want to see:

Rule1

Anything I want to file but don’t want to see

rule2

Outlook

Posted in z Silverlight Archives | Comments Off on Outlook on my PC and Phone and Keeping Organized

Report on CodeMash 2009

CodeMashLogo This year I had the incredible pleasure of speaking at CodeMash 2009 (last year I missed it by breaking my glenoid just before going. This was better).

The organizers asked for feedback, and I realized that my feedback (slightly edited) made for a reasonable field report as well.  Here it is…

You can find the complete program for this conference here.

 

About Your Sessions

I had two sessions. The first was on Hypervideo. Unfortunately, despite having rehearsed just hours before, a critical piece of software fell off my computer and wasn’t there when needed. Fortunately,  John Stockton was there with just what I needed, and I had the presentation backed up on thumb drive (and, for that matter, my entire disk backed up as well just in case), so only 10 minutes was lost.

The presentation went well, I thought, and the Q&A was good. I did get one flame later on Twitter, but a follow-up email to the writer produced a terrific exchange and he was quite gracious and had good suggestions.

The second session was on Templating controls and (a) it should have come before the first and (b) I should have realized the wide variety of experience in the room and chosen a topic that assumed less familiarity with Silverlight. That said, it went well and people were into it and asked good probing questions.

Who did you have great conversations with?

More people than I have had with at any similar conference. Truly excellent conversations with very motivated, very interesting and very bright programmers.  That was great.   I talked to about 2 dozen people at length and another dozen briefly. Could have been more but I spent a lot of time sleeping and rehearsing.  Great atmosphere, lots of fun but very serious about the technology. It was a blast.

What value did you get out of being at CodeMash?

A bit of a  breakthrough in my role as a Technical Evangelist, defined by me as a techie (coder/ developer) who is sufficiently excited about a technology that I want to talk about it, share it, show it, and teach it. I’d been fighting that role a bit, and many things at CodeMash contributed to my embracing it.

What did you get out of the Ask The Experts panel?

It was a blast.  The .NET Rocks guys do and the panel was an opportunity to listen to a  different perspective and see clearly how much sense it made in its context.  I hope to follow up with James Ward and maintain contact. Great guy, very smart. 

Plus, every time I come within 6 meters of Josh Holmes I learn something about how to do my job. 

Must mention that Jim Holmes has an incredible knack for making everything easy. 

A great time, hope I get to go again.

 

Next Article

More: .NET Rocks RIA Panel


This work is licensed under a Creative Commons Attribution By license.
Posted in z Silverlight Archives | Comments Off on Report on CodeMash 2009

Help Wanted

I have some ideas about improving this blog that will require going through past messages and adding forward/backward references and FAQ indicators and more.  If you are willing to work for “recognition” and eternal gratitude, please send email to jliberty@microsoft.com  with Blog Slog in the subject line!  Thanks.

Wow! What a response!  Thank you all; I have so many volunteers I hardly know what to do.  Can’t thank you all enough.

 

-jesse

Silverlight

Posted in z Silverlight Archives | Comments Off on Help Wanted

Drag and Drop with Managed Code

 

The last time I looked at Drag and Drop was with Silverlight version 1 and now seemed like a good time to see how one might accomplish this seemingly straight forward task with managed code.

The experience was interesting. Once I had it working, it was hard to explain why it had been difficult, though it did seem that the documentation took you right up to what you needed to know and then stopped short. I’m not certain that is true, but I know I struggled longer than I expected to.  In any case, now that it is working, it is easy to demonstrate.

This blog entry will make short work of it. To keep things simple, we’ll just draw a circle and a square and drag them around the surface of the larger canvas (we’ll use canvas because it uses absolute positioning which makes positioning the shape much easier). I’ve added color to the canvas so you can see where its boundaries are.

DragAndDropRunning
(Composite image of dragging circle)

  
The Xaml file is very simple,

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="DragDrop.Page"
Width="800"
Height="600"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Canvas Background="AntiqueWhite">
<Ellipse
x:Name="Circle"
Height="150"
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Fill="#FFFFFF00"
Stroke="#FF000000"
Canvas.Left="10"
Canvas.Top="25" />

<Rectangle
x:Name="Square"
Height="100"
Width="100"
Canvas.Left="200"
Canvas.Top="50"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Fill="Red"
Stroke="Black"
StrokeThickness="1"
Opacity="0.75" />
</Canvas>
</UserControl>

The Supporting Code

All of the code for this example is in Page.xaml.cs.  We want to implement three event handlers for each shape:

  1. MouseLeftButtonDown – the user has started to drag
  2. MouseMove – the user is dragging
  3. MouseLeftButtonUp – the user has stopped dragging

The key to understanding how this works is that these events are fired by the shapes themselves, not by the mouse or the canvas. Once that is clear, the rest follows naturally.

To make for easier-to-maintain code, we’ll share event handlers between the Square and the Circle.

public partial class Page : UserControl
{




// are we currently tracking the mouse?
private bool isTracking = false;
  // constructor
public Page()
{
InitializeComponent();

Circle.MouseLeftButtonDown +=
new MouseButtonEventHandler( Shape_MouseLeftButtonDown );
Square.MouseLeftButtonDown +=
new MouseButtonEventHandler( Shape_MouseLeftButtonDown );

Circle.MouseLeftButtonUp +=
new MouseButtonEventHandler( Shape_MouseLeftButtonUp );
Square.MouseLeftButtonUp +=
new MouseButtonEventHandler( Shape_MouseLeftButtonUp );

Circle.MouseMove +=
new MouseEventHandler( Shape_MouseMove );
Square.MouseMove +=
new MouseEventHandler( Shape_MouseMove );
}

 

MouseLeftButtonDown

Clicking the left mouse button acts as a signal to begin dragging. We’ll set the member flag to indicate that we are tracking, and then we’ll want to set a few properties on the shape.

Unfortunately, we have only the sender (type object) and the MouseButtonEventArgs OriginalSource property (also of type object). This is not a problem, however, as we know that any object firing this event is of type shape, so we are safe to cast accordingly,

void Shape_MouseLeftButtonDown( 
object sender,
MouseButtonEventArgs e )
{
isTracking = true;
Shape s = e.OriginalSource as Shape;


// For robust code, you should test that s is not null

With a reference to the shape, you can now set the opacity to half its current value. We won’t set it to a fixed value (e.g., 0.5) as that would break any shape whose initial opacity is not 1 (such as our square!).

s.Opacity *= 0.5;

(We’ll restore this later by doubling the value, returning it to whatever it was, without the need to cache the original value)

When the user is dragging, it is possible that the mouse will move off the shape which will cause the MouseMove event to stop firing (the technical term for this is “bad“). To prevent that, we’ll capture the mouse:

s.CaptureMouse();

MouseMove

Each time the user moves the mouse a MouseMove event is fired. We test for whether we are tracking the mouse (the IsTracking private member variable is set in ButtonDown and cleared in ButtonUp) and if so we get the current position of the mouse from the MouseEventArgs,

void Shape_MouseMove( object sender, MouseEventArgs e )
{
if ( isTracking )
{
double currentMouseX = e.GetPosition( null ).X;
double currentMouseY = e.GetPosition( null ).Y;

These values will be the new position for the Left and Top values of our shape. While this works okay for a square, it is counter intuitive for a Circle as a Circle’s top-left corner is actually that of the invisible bounding rectangle, as illustrated here (with the bounding rectangle filled in artificially in turquoise),

BoundingRect1

Since the bounding rectangle is actually invisible however, the user is forced to drag from a point to the north-west of the circle, a disconcerting and odd experience,

BoundingRect2

To eliminate that, we’ll reposition to the center of the shape,

    Shape s = e.OriginalSource as Shape;
    Canvas.SetLeft( s, currentMouseX  – s.Width / 2);
    Canvas.SetTop( s, currentMouseY – s.Height / 2);

MouseLeftButtonUp

When the left mouse button is released, we’re done dragging, we can release our capture of the mouse and set IsTracking to false, remembering to restore the opacity to its original value

void Shape_MouseLeftButtonUp( 
object sender,
MouseButtonEventArgs e )
{
isTracking = false;
Shape s = e.OriginalSource as Shape;
s.Opacity *= 2;
s.ReleaseMouseCapture();
}

 

Here is the complete Page.xaml.cs in one place for easy copying:

using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;

namespace DragDrop
{
public partial class Page : UserControl
{
private bool isTracking = false;

public Page()
{
InitializeComponent();
Circle.MouseLeftButtonDown +=
new MouseButtonEventHandler( Shape_MouseLeftButtonDown );
Square.MouseLeftButtonDown +=
new MouseButtonEventHandler( Shape_MouseLeftButtonDown );

Circle.MouseLeftButtonUp +=
new MouseButtonEventHandler( Shape_MouseLeftButtonUp );
Square.MouseLeftButtonUp +=
new MouseButtonEventHandler( Shape_MouseLeftButtonUp );

Circle.MouseMove +=
new MouseEventHandler( Shape_MouseMove );
Square.MouseMove +=
new MouseEventHandler( Shape_MouseMove );
}

// ** Button down **
void Shape_MouseLeftButtonDown(
object sender,
MouseButtonEventArgs e )
{
isTracking = true;
Shape s = e.OriginalSource as Shape;
s.Opacity *= 0.5;
s.CaptureMouse();
}


// ** Mouse Move **
void Shape_MouseMove(
object sender,
MouseEventArgs e )
{
if ( isTracking )
{
// get the mouse position
double currentMouseX = e.GetPosition( null ).X;
double currentMouseY = e.GetPosition( null ).Y;

// center the shape at the mouse position
Shape s = e.OriginalSource as Shape;
Canvas.SetLeft( s, currentMouseX - s.Width / 2);
Canvas.SetTop( s, currentMouseY - s.Height / 2);
}
}

// ** Button up **
void Shape_MouseLeftButtonUp(
object sender,
MouseButtonEventArgs e )
{
isTracking = false;
Shape s = e.OriginalSource as Shape;
s.Opacity *= 2;
s.ReleaseMouseCapture();
}
} // end class
} // end namespace
 
Try it: 

 

 

-j

Posted in z Silverlight Archives | Comments Off on Drag and Drop with Managed Code

Navigating threads

For the past couple weeks I’ve been ironing out a new navigation feature that I’ve added to my blog. The goal is to allow you to follow a topic as it threads through the blog, skipping over intervening messages, or going back to see previous messages on the topic.

While tags help with this, they are not efficient for following a series of messages that build on one another. Thus I’ve settled on this convention: when I add a message that builds on a previous message, even obliquely, I add a backward pointer to the new message and a forward pointer to the old message.

Previous: Name of previous entry    Next: Name of next entry

The goal is that you will be able to follow a discussion thread through the blog, skipping over the intervening messages as you desire, without this system getting in your way if you wish to ignore it.

Posted in z Silverlight Archives | Comments Off on Navigating threads

Pie Chart and Column Chart videos post

NewPieChartVideoI’m pleased to announce that my videos on the Silverlight Toolkit PieChart and Columns chart are now available. 

What is very nice is that once you understand how one of these charts works, working with the other becomes almost self-evident.

 

 

 

 

 

 

 

Posted in z Silverlight Archives | Comments Off on Pie Chart and Column Chart videos post

Tag + Phone = Contact

This excellent idea from Microsoft UX Evangelist René de Paula Jr arrived just 1/2 a day too late for me to try it out at Code Mash, but I will do so at my next opportunity. He suggests placing a Microsoft Tag encoding my VCard as the final slide in my presentation; which I think is nothing short of brilliant.

ContactMe

(note, using the gettag phone application on the image above will, in fact, add my contact information to your contacts).

It will be interesting to think about how these tags might be integrated into Silverlight applications.

Posted in z Silverlight Archives | Comments Off on Tag + Phone = Contact

Building A HyperVideo Player – 1

 

 

 

In a previous posting, I began a fast and furious mini-tutorial on building a hyper-video player. In this segment, I’ll demonstrate how to:

  • Use Encoder to add markers to a video
  • Use Encoder to create a player
  • Modify the player Encoder creates using templates
  • Have the player respond to each marker as it is encountered

To begin, you’ll need a bit of video. I downloaded the 4th segment of the video on Building a Skinnable Custom Control and then cut out the middle to create a very abridged version that runs just over a minute.

AbridgedMovie

I then imported that video into Encoder, and added markers as shown in the earlier blog entry.

Use Encoder to create a player

With the markers in place I turned to creating my player. Again, this is reviewed in the previous blog entry so I won’t repeat that here, but now we’re ready to actually make the changes.  For today’s exercise, this is a process of eliminating those controls that we don’t need. We’ll start by opening the player in Expression Blend and as with any custom control you may now ask to edit a copy of the template,

EditPlayerTemplate

You are prompted, as usual to pick a name and to choose whether to put the template into the file or into App.xaml (for the entire application). We’ll choose the latter. Once these choices are made you are dropped into the template editor, the view states are revealed as are the parts of the media player.

TemplatedPlayer

This allows you to drill down into the player and simply delete those controls we won’t need, including the entire set of “miscControls,”

miscControls

 

 

 

 

which are conveniently highlighted on the player to indicate which controls you are about to assassinate,

image

In the same way, I proceeded to eliminate the buttons used for rapid navigation

NavButtons

Once these were deleted the player was simplified and ready for use.

SimplifiedPlayer

 

 

Responding to the Markers

I’d like to tell you that responding to the markers that we added to the video involves a bit of tricky programming, and you’re lucky you found my blog because I can show you how to do it right….

Opening the project in Visual Studio reveals otherwise. You’ll remember that what we’ve created is a template for the ExpressionPlayer class that was emitted by Encoder and that is found in ExpressionPlayerClass.cs:

namespace ExpressionMediaPlayer
{
public class ExpressionPlayer : MediaPlayer

Stripping out the using statements and comments reveals that the class created by Encoder is just a specialization of Media Player. MediaPlayer’s source is provided as well. Opening MediaPlayer.cs and scrolling down to the Events region reveals this:

public event TimelineMarkerRoutedEventHandler MarkerReached;

That is the event we want to respond to; it is fired every time the player encounters a marker in the video.

The EventArgs type that we are passed is well documented in the standard Silverlight documentation, which includes among other things sample code that makes our work embarrassingly easy,

public void OnMarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
{
timeTextBlock.Text = e.Marker.Time.Seconds.ToString();
typeTextBlock.Text = e.Marker.Type.ToString();
valueTextBlock.Text = e.Marker.Text.ToString();
}

All we need is a TextBlock to display the values we’ll receive when we hit the marker. Open Page.xaml and add two rows to the grid, and a TextBlock in the second row,

  <Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition
Height="9*" />
<RowDefinition
Height="0.5*" />
</Grid.RowDefinitions>
<ExpressionPlayer:ExpressionPlayer
Margin="0,0,0,0"
x:Name="myPlayer"
Style='{StaticResource ExpressionPlayerBlogVersion }'
Grid.Row='0' />
<TextBlock
x:Name='Message'
Grid.Row='1' />
</Grid>

You can now implement the event handler in Page.xaml.cs,

public partial class Page : UserControl
{

public Page( object sender, StartupEventArgs e )
{
InitializeComponent();
myPlayer.OnStartup( sender, e );
myPlayer.MarkerReached +=
new TimelineMarkerRoutedEventHandler( myPlayer_MarkerReached );
}

void myPlayer_MarkerReached( object sender,
TimelineMarkerRoutedEventArgs e )
{
Message.Text = e.Marker.Text + " at " + e.Marker.Time.Seconds.ToString() +
" seconds."
}
}

The result, as we hoped, is that the player shows the video and when it encounters a marker, it shows the name of the marker and the time the marker was hit. The easiest way to test this is to navigate to the output directory you designated in encoder,

EnodedDirectory

and pick up a copy of the the Default.html and the .wmv file output by encoder.  Drop these in the debug directory of the encoder folder

TestingFromDebug

Double click on Default.html and “let ‘er rip!”

WorkingHyperVideo

Note the marker indicated at just below the (cropped) player.  Be careful when you recompile, the default.html in the Encoder project will be over-written.

 

Previous: HyperVideo: Getting Started       Next: HyperVideo Put To Work

Posted in z Silverlight Archives | Comments Off on Building A HyperVideo Player – 1

Silverlight Toolkit WrapPanel

The Silverlight Toolkit includes a couple new panels, one of which is the incredibly handy WrapPanel.

[ Updated Jan. 4 to include working example ] 

In its most straight forward use, the WrapPanel allows you to add UIElements which it positions sequentially (typically left to right) until there is insufficient space, at which time it creates a new row beneath the most recent; that is, it wraps.

Creating a simple test program reveals a few interesting aspects about the wrap panel. To do this, open Visual Studio and create a new Silverlight Application. Be sure to add a reference to the Microsoft Windows Controls.dll that came with the Toolkit (the trick is remembering where you’ve put them!)

AddRefToMicrosoftWindowsControls

You’ll also need to create a namespace at the top of Page.xaml, but Intellisence is prepared to be of some assistance,

AddNameSpace

That done, my sample program creates a wrap panel with a single button in it; here’s the complete Xaml listing:

<UserControl x:Class="WrapPanel.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:controls="clr-namespace:Microsoft.Windows.Controls;
assembly=Microsoft.Windows.Controls" Width="800" Height="600"> <Grid x:Name="LayoutRoot" Background="White"> <controls:WrapPanel x:Name="WPanel" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Orientation="Horizontal"> <Button x:Name="Add" Content="Add!" FontFamily="Georgia" FontSize="24" Width="Auto" Height="Auto" Background="#FF0000FF" Margin="5" /> </controls:WrapPanel> </Grid> </UserControl>

 

The goal of the code that supports this page is that when the user clicks on the add button one of four controls is randomly chosen, created and added to the panel. 

using System;
using System.Windows;
using System.Windows.Controls;

namespace WrapPanel
{
  public partial class Page : UserControl
  {
    private Random rand = new Random();

    public Page()
    {
      InitializeComponent();
      Add.Click += new RoutedEventHandler( Add_Click );

    }

To support that goal, a private member variable of type Random is added as is an event handler for the "Add" button that was created in the Xaml.

All the interesting work happens in the event handler. If you start by creating controls all of the same size,

 void Add_Click( object sender, RoutedEventArgs e )
 {
   Button b = new Button();
   b.Content = DateTime.Now.ToLocalTime().ToString();
   b.Width = 120;
   b.Height = 35;
   b.Margin = new Thickness( 5 );
   this.WPanel.Children.Add( b );
}

you get a very uniform appearance as each control is added until there is not enough room and then a new row is begun. (in the example shown I’ve made the control somewhat smaller and the Add button the same size as the buttons I’m creating):

UnifromSizes

If,  instead, you create different objects, then different things begin to happen. In the next example I’ll create one of four types of objects

void Add_Click( object sender, RoutedEventArgs e )
{
  int choice = rand.Next( 0, 4 );
  Control c;
  switch ( choice )
  {
    case 0:
      // make a button
    case 1:
      // make a text box
    case 2:
      // make a short list
    case 3:
    default:
     // make a password control
  }

 // set the font size
 // set the width and height and margin
 // add the control to the wrap panel
  
}

A few interesting questions arise. What if I set their font size randomly and what if I set the height to auto (you do this programmatically by setting it to the value double.Nan).

void Add_Click( object sender, RoutedEventArgs e )
{
  /*
  Button b = new Button();
  b.Content = DateTime.Now.ToLocalTime().ToString();
  b.Width = 120;
  b.Height = 35;
  b.Margin = new Thickness( 5 );
  this.WPanel.Children.Add( b );
  */

  
  int choice = rand.Next( 0, 4 );
  Control c;
  switch ( choice )
  {
    case 0:
      Button b = new Button();
      b.Content = DateTime.Now.ToLocalTime().ToString();
      c = b;
      break;
    case 1:
      TextBox t = new TextBox();
      t.Text = rand.Next(0,int.MaxValue-1).ToString();
      c = t;
      break;
    case 2:
      ItemsControl i = new ItemsControl();
      i.Items.Add( "Cormac McCarthy" );
      i.Items.Add( "Neal Stephenson" );
      i.Items.Add( "Marcel Proust" );
      i.Items.Add( "Virginia Woolfe" );
      c = i;
      break;
    case 3:
    default:
      PasswordBox p = new PasswordBox();
      p.Height = 35;
      p.Password = "Secret";
      c = p;
      break;
  }

  c.FontSize = rand.Next( 6, 18 );
  if ( c is ItemsControl )
  {
    c.FontSize = Math.Max( c.FontSize, 10 );
  }
  c.Width = Double.NaN;
  c.Height = Double.NaN;
  c.Margin = new System.Windows.Thickness( 5 );
  
  this.WPanel.Children.Add( c );
 
}

AutoSizedWrapPanel

I find the results interesting, though not necessarily what I want.  One approach is to fix the height of the buttons, which gives another, also interesting effect. A quick way to try this is to make a small code modification:

if ( c is ItemsControl )
{
  c.FontSize = rand.Next( 8, 18 );
  c.Height = Double.NaN;
  //c.FontSize = Math.Max( c.FontSize, 10 );
}
else
{
  c.FontSize = 12;
  c.Height = 30;
}

This causes the other controls not to resize but to center on the larger list.

CenteredOnList

By using panels within panels, you can of course get just about any effect you like.

(I’ve not posted the source code because it’s all here)

Here is a working example in an iframe:

 

 

Previous  The Wrap Panel


This work is licensed under a Creative Commons Attribution By license.
Posted in z Silverlight Archives | Comments Off on Silverlight Toolkit WrapPanel

Hypervideo – Getting Started

 

 

 

 

For those of you who want to get started with hypervideo and don’t want to wait for the videos or the full tutorial, here is the first of a series of fast mini-tutorials.

The first step is to pick a video you’d like to use as your “source.” The source will be the video you’ll link from.

If you don’t have it already, you’ll need to download Encoder by going to the Expression Web Site and clicking on Encoder in the lower right hand corner as shown in the cut-down image below

MicrosoftExpression

3. Buy (or try) Encoder, and be sure to download Service Pack 1 and the Encoder SDK

GetEncoder

Once you are set up, you are ready to use Encoder to add markers to your video and to ask Encoder to emit a player for you that you will modify.

Importing The Video

 

Open Encoder and choose File->Import

EncoderImport

and navigate to the video you want to import.  It will appear in the Media content window of Encoder and you can watch it by pressing the play button.

VideoPlayingInEncoder

The area I marked A represents the imported video. On the control toolbar you can see the elapsed time (area B). Above that, in the area marked C is the “playhead.”

MetaData

The right side of Encoder has four tabs:

  • Encode
  • Enhance
  • MetaData
  • Output

For now, we care only about the last two.  The Metadata tab offers the ability to name the output video (and add an enormous amount of metadata such as copyright, genre, etc.) and to add markers,

MetaDataTab

 

There are many ways to add markers, but one of the easiest is to move the playhead to the place in the video you want the marker, and then to press the Add button. 

Four editable fields are made available for each marker:

  • Time (Elapsed time into the video in thousandths of a second)
  • Value (any arbitrary value that will serve as a name for the marker)
  • Thumbnail (a boolean indicating whether or not a thumbnail should be created)
  • Keyframe (a boolean indicating whether or not a keyframe should be created)

MarkerDetail

The thumbnail is used when creating chapters (as for a DVD movie) to show an image indicating what is in that scene of the film.

Creating a keyframe instructs Encoder to put an IFrame at that location. The documentation notes that this can shorten seek time for the marker” but again is not relevant for the work we’ll be doing.

For our purposes Thumbnail and Keyframe should be unchecked

What To Put In Value

Traditionally, the Value field is filled with some indication of what is happening in the video at that time location, though see my previous blog entry for a discussion of why that may or my not be desirable.

Once You’ve Added The Markers

Once you’ve added all the markers that you wish to add, and adjusted their exact timing to whatever level of precision you choose, you are ready to encode the video and to enlist Encoder in creating a player for you.

MarkersReadyToEncode

Creating The Player

Switch to the output panel, where you will pick a Silverlight 2 player and you want to click on the white dot (shown surrounded in red here)

OutputPanel

When you choose the Silverlight 2 Default player template an image of the player will appear.

EditControlInBlend

Clicking on the white dot and choosing Edit Copy in Expression Blend will open a dialog box asking you for a name for the template. Give it a name and click OK and Blend will open with a security warning. You can click Yes and Blend will fully open and inform you that you must build the project to work with it. Click Project->Build Solution and when it completes you should see the player in the art board and the Objects and Timeline will indicate that within the Layout Root is a single object: myPlayer.

Encoding the Video

Before you go any further, don’t forget to return to Encoder and finish encoding the video! Make sure the output tab is active and examine the Media File Name and the Directory,

JobOutput

The default name for your new encoded video is created by appending the default extension (wmv) to the original file name. You can change either or both parts of this.  You can also pick the directory you’d like to place the encoded video into.  There are some checkboxes below that can be helpful as well.

Once you have this set as you like, click the Encode button in the lower left hand corner and your video will begin encoding, with a countdown clock telling you how much time remains. If you checked “Preview in Browser” when you finish a browser will open and your video will display (though there may be a short delay).

Files, Files, Who Has The Files?

At this point you have two sets of important files:

  • The encoded video and some helper files to look at it
  • The emitted player and the source code for modifying it

The encoded video should be in the directory you chose (in the example shown above, the files would be in c:\demo\HyperVideo Blog 1\VISTA64DT 12-30-2008 12.45.51 PM\ where VISTA64DT is the name of my machine and the rest of the name is a time stamp.

Inside that directory will be a copy of the .xap file for the emitted player, a .dat file that contains a great deal of information about the video and the markers, a default.html and the encoded wmv file. Double clicking on the html file will bring up your video in the emitted video player.

Where is the Player?

The player itself is in the default output location unless you took steps to put it elsewhere. On my machine that is C:\Users\Jesse\Documents\Expression\Expression Encoder\Templates

Under that directory I will find a directory with the name of the template, in this case, Silverlight 2 Blog Version inside of which is another Default.html and copy of the .xap file, but more important, is also a Source directory. In that directory is the complete source for the custom control player that I will want to modify.

Spec’ing the Player

The player that is emitted by encoder is a good start, but it encourages use of markers in exactly the wrong way for our purposes. We are not interested in chapters, we are interested in providing metadata and reacting to embedded markers as events. Thus, there is much we want to strip away: specifically everything circled in red in this next image:

PlayerSpec

You can see, however, why we wanted Encoder to create the player; it is far easier to start with this and remove what we don’t want than to create all the functionality from scratch.

Working With The Project

If you open this project in Blend and Visual Studio (and I recommend opening it in both) there is a fleeting temptation to panic when you look in page.xaml:

<UserControl x:Class="MediaPlayerTemplate.Page"
    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"
    xmlns:ExpressionPlayer="clr-namespace:ExpressionMediaPlayer;
          assembly=ExpressionPlayer"
    mc:Ignorable="d"
    Width="Auto" 
    Height="Auto">
    <Grid x:Name="LayoutRoot">
    <ExpressionPlayer:ExpressionPlayer
      Margin="0,0,0,0"
      x:Name="myPlayer" />
  </Grid>
</UserControl>

 

 

 

 

 

All that you have is a single, monolithic control. How are you going to modify that??

It’s Just A Skinnable Custom Control

Great news!  What Encoder has provided to you is a skinnable custom control, exactly as described in these four videos:

What encoder has done is to create a custom class, ExpressionPlayer that derives from MediaPlayer.

public class ExpressionPlayer : MediaPlayer

Rather than providing ExpressionPlayer with a default look, they rely on MediaPlayer for that, but wonderfully, MediaPlayer’s source is also included, and as you’d expect there is a Themes folder with a generic.xaml file that does contain the default appearance.

In addition, MediaPlayer.cs provides the attributes that constitute the Parts and States contract

(excerpt)

[TemplatePart(Name=MediaPlayer.StretchBox, Type=typeof(FrameworkElement))]
[TemplatePart(Name=MediaPlayer.VideoWindow, Type=typeof(FrameworkElement))]
[TemplatePart(Name=MediaPlayer.TextblockErrorMessage, Type = typeof(TextBlock))]
[TemplatePart(Name=MediaPlayer.ClosedCaptionBackground, Type = typeof(Rectangle))]

which makes skinning (templating) the Expression player far easier.

What We’ll Do In the Next Installment

Having encoded the video and emitted a player, and having explored enough to see that we have the resources to template that player we’ve reached a good stopping point.

Next time we’ll modify the player to strip it down and we’ll teach it to respond to markers by placing the name of the marker just below the player. Once we can do that, we’ll have established the fundamental architecture and we can begin to enhance the player to respond in more meaningful ways.

Previous:  Hypervideo- Continuing the Dialog      Next: Building a Hyper-Video Player: Phase I

 

 

 

 

 

Posted in z Silverlight Archives | 1 Comment

HyperVideo Continuing the dialog

 

 

Ben wrote that he hopes I will dive deep into decoupling the type or name of the markers from the data-driven information, and I want to respond that this is an important part of decoupling the link from the response to that link, though I’m not sure it is totally required.

The case for unnamed Markers

The argument in favor starts with the observation that there is a natural tendency to think of the source video and the target (linked-to) video as a single unit.

For example, assume you are working with the video shown in the upper left corner in the figure below and you note that at this point the user is assumed to understand how to handle  events in a templated control, but may need more information. It is natural to assume that the hyper-video link would that issue, and would “of course” lead to a video (or blog post or article) to provide that background information.

SingleLink

It would be natural to name the marker placed here “ClickEventForTemplatedControl.” The simple act of changing the name of the marker to  (e.g.,) Marker7 might free you in some ways to think about linking to lots of other supporting material as well.

Circular Error Probability (C.E.P.)

Weapons experts talk about Circular Error Probability, which Wikipedia describes as “an intuitive measure of a  weapon system’s accuracy… defined as a circle, centered about the mean, whose boundary is expected to include 50% of the population within it.

 

A key difference between a hyper-link in hyper-text and a hyperlink in video is that in hypertext I can create a link with exact placement, down to a punctuation mark!  Video, by its nature, does not easily lend itself to such precision. Thus you are left with two options:

  1. You indicate to the user that there is more information, but leave some inevitable uncertainty (CEP) about what it is that you are linking from or

image

or 2. You add text to indicate precisely what the hyper-video link will provide.

image

There are advantages in the very imprecision of the first example that I’m not sure we’ve all had time to think about, let alone explore, but I intuit that this is an area rich in possibilities, both for creating infuriating and frustrating user experiences and, possibly, for creating wondrously flexible creative interfaces.

Videos and Blogs and Cabbages and Kings

I’m actively recording these videos but they’ll take a while to post (especially because of the holidays), but that gives us all an opportunity to explore some of the ramifications before we settle into the details of how to implement.

Meanwhile, another special request: so far all the documentation I’ve found on modifying the player that encoder emits assumes that you will choose a Silverlight 1 version of the player and work in script. My example uses a Silverlight 2 player and work in C#. If you run across any examples or documentation of someone else doing that (modifying a Silverlight 2 player emitted from encoder) I’d love a link.  Thanks!

Enjoy your holidays and stay tuned, much to come.

 Previous: Hypervideo      Next: Hypervideo – Getting Started

Posted in z Silverlight Archives | Comments Off on HyperVideo Continuing the dialog

HyperVideo

 

This posting will reintroduce the concept of Hyper-video, the subject of a series of forthcoming videos.

The concept of HyperVideo is most easily explained by a series of examples.

  • MugabeYou are watching the news and the anchor person says “Robert Mugabe, president of Zimbabwe, today announced…” you click on the question mark on the screen and are presented with a menu:
    1. Zimbabwe History (Web link)
    2. Zimbabwe Government and Politics (Article)
    3. President Mugabe Biography (Video)
    4. Go to Wikipedia/Zimbabwe
  • You are watching a video on how to use a Silverlight Toolkit control and you realize that you don’t know how to install the Toolkit. You click on Help — the video pauses and a second video opens that provides the background information you need.

  • You are watching a HR training video and the person in the video mentions investing in a 401K. The word 401K appears on the screen and when you click on it, the first video pauses and a second video begins detailing your retirement plan options. But here’s the kicker:  the supplemental video you are seeing is quite different from the 401K video your manager would see. The system chooses which video to display based your management level and years of service.
What have you already seen about this? Please email to me:

  • Anything you’ve seen where the idea of Hypervide has been explored
  • Any documentation on modifying an Encoder-emitted video player using managed code
  •  

    Much to Explore

    Building hypervideo will cause us to consider a number of interesting aspects of Silverlight and related technologies.

    As a start, Markers Expression Encoder can simplify creating the “markers” in the video.

    The Media Element (or a control derived from the Media Element) will fire an event each time a marker is encountered. There are numerous traditional and non-traditional ways to respond to that event. EncoderOutput

    Encoder will also create a working player to get us started.

    At its heart, the player is a control or a set of controls that can be skinned to change its appearance and can be subclassed to change its behavior

    Interpretation of the markers can be decoupled from the type or name of the markers, and can be data driven based on information obtained (e.g.,) through a web service

    iStock_InjectionRedXSmall

    Note that for complete decoupling, markers can be injected into the video at run time, rather than permanently encoded into the video.

    Whither Hypervideo?

     

     

     

     

     

     

     

    I am reminded that the value of hypertext was not fully realized for quite a while after it was first introduced. (Wikipedia estimates that it was at least 20 years from invention to widespread use). It will be interesting to see if hypervideo turns out to have lasting value or is yet another technology in search of a need.

     

     

    More: Hypervideo – Continuing the Dialog

    Posted in z Silverlight Archives | Tagged | Comments Off on HyperVideo