Wednesday, March 18, 2009

XAML PT community lauched

Today we lauch a new community that aims at Microsoft's Presentation Technologies: XAML PT. Namely the development of Silverlight, WPF and Surface applications that use XAML. The community is intended for Portuguese speaking people and will be formally released at the same time as the Keynote of MIX09 this afternoon (GMT).

I would like to thank Fullsix Portugal for sponsoring this community.

Saturday, February 21, 2009

Web site frontend performance

This week I presented at DevDays09 the session WUX303 – Optimização de Performance de Web Sites. This session had great feedback. It was ranked number 7 of the overall 75 sessions of the event.

It was an overview of the book “High Performance Web Sites” by Steve Souders. I presented the 14 rules and showed some demos and tools that help on optimizing your website.

Here are some of the tools I used:

Here are the slides of the presentation and the demos.

Sunday, February 15, 2009

Changing sound frequency for game

Hi!
I wanted to be able to change a sound frequency according to the strength applied to a element inside a game. Based on this thread I changed the sample to allow to change at real time the frequency of the sound being played.

The code that does the thing is:

   1: BufferDescription d = new BufferDescription();


   2: d.ControlFrequency = true;


   3: sound = new SecondaryBuffer("C:\\Windows\\Media\\ding.wav", d, applicationDevice);


   4: sound.Frequency = 0; //The default frequency


   5: sound.Play(0, BufferPlayFlags.Looping);


   6: if you want to change the frequency:


   7: sound.Frequency = <some value>;




Here is the complete code:



(you need to add a reference to Microsoft.DirectX.DirectSound)






   1: using System;


   2: using System.IO;


   3: using System.Drawing;


   4: using System.Collections;


   5: using System.ComponentModel;


   6: using System.Windows.Forms;


   7: using System.Data;


   8:  


   9: using Microsoft.DirectX.DirectSound;


  10:  


  11: namespace Noisey


  12: {


  13:     /// <summary>


  14:     /// Very simple test form


  15:     /// </summary>


  16:     public class MainForm : System.Windows.Forms.Form


  17:     {


  18:         private System.Windows.Forms.Button btnPlay;


  19:         /// <summary>


  20:         /// Required designer variable.


  21:         /// </summary>


  22:         private System.ComponentModel.Container components = null;


  23:  


  24:         Device applicationDevice;


  25:         SecondaryBuffer sound;


  26:         private BufferDescription d;


  27:  


  28:         private TrackBar trackBar1;


  29:         private TextBox txtFreq;


  30:         private Label label1;


  31:         private Label label2;


  32:         private Button btnStop;


  33:         private OpenFileDialog openFileDialog1;


  34:         private Button btnNewFile;


  35:         private Label lblFile;


  36:         private Label label3;


  37:         


  38:         


  39:  


  40:         public MainForm()


  41:         {


  42:             //


  43:             // Required for Windows Form Designer support


  44:             //


  45:             InitializeComponent();


  46:  


  47:             //


  48:             // Add any constructor code after InitializeComponent call


  49:             //


  50:             applicationDevice = new Device();


  51:             applicationDevice.SetCooperativeLevel(this, CooperativeLevel.Normal);


  52:             


  53:             d = new BufferDescription();


  54:             // Set descriptor’s flags


  55:             d.ControlPan = true;


  56:             d.ControlVolume = false;


  57:             d.ControlFrequency = true;


  58:             d.ControlEffects = false;


  59:  


  60:             //Load a default file


  61:             sound = new SecondaryBuffer("C:\\Windows\\Media\\ding.wav", d, applicationDevice);


  62:             sound.Frequency = 0; //The default frequency


  63:  


  64:             //Disable stop button because it's not playing yet.


  65:             btnStop.Enabled = false;


  66:         }


  67:  


  68:         /// <summary>


  69:         /// Clean up any resources being used.


  70:         /// </summary>


  71:         protected override void Dispose(bool disposing)


  72:         {


  73:             if (disposing)


  74:             {


  75:                 if (components != null)


  76:                 {


  77:                     components.Dispose();


  78:                 }


  79:             }


  80:             base.Dispose(disposing);


  81:         }


  82:  


  83:         #region Windows Form Designer generated code


  84:         /// <summary>


  85:         /// Required method for Designer support - do not modify


  86:         /// the contents of this method with the code editor.


  87:         /// </summary>


  88:         private void InitializeComponent()


  89:         {


  90:             this.btnPlay = new System.Windows.Forms.Button();


  91:             this.trackBar1 = new System.Windows.Forms.TrackBar();


  92:             this.txtFreq = new System.Windows.Forms.TextBox();


  93:             this.label1 = new System.Windows.Forms.Label();


  94:             this.label2 = new System.Windows.Forms.Label();


  95:             this.btnStop = new System.Windows.Forms.Button();


  96:             this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();


  97:             this.btnNewFile = new System.Windows.Forms.Button();


  98:             this.lblFile = new System.Windows.Forms.Label();


  99:             this.label3 = new System.Windows.Forms.Label();


 100:             ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();


 101:             this.SuspendLayout();


 102:             // 


 103:             // btnPlay


 104:             // 


 105:             this.btnPlay.Location = new System.Drawing.Point(18, 64);


 106:             this.btnPlay.Name = "btnPlay";


 107:             this.btnPlay.Size = new System.Drawing.Size(87, 20);


 108:             this.btnPlay.TabIndex = 0;


 109:             this.btnPlay.Text = "Play Sound";


 110:             this.btnPlay.Click += new System.EventHandler(this.btnPlay_Click);


 111:             // 


 112:             // trackBar1


 113:             // 


 114:             this.trackBar1.Location = new System.Drawing.Point(37, 124);


 115:             this.trackBar1.Maximum = 50000;


 116:             this.trackBar1.Minimum = 1000;


 117:             this.trackBar1.Name = "trackBar1";


 118:             this.trackBar1.Size = new System.Drawing.Size(190, 45);


 119:             this.trackBar1.TabIndex = 1;


 120:             this.trackBar1.Value = 30000;


 121:             this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);


 122:             // 


 123:             // txtFreq


 124:             // 


 125:             this.txtFreq.Enabled = false;


 126:             this.txtFreq.Location = new System.Drawing.Point(43, 185);


 127:             this.txtFreq.Name = "txtFreq";


 128:             this.txtFreq.Size = new System.Drawing.Size(100, 20);


 129:             this.txtFreq.TabIndex = 2;


 130:             // 


 131:             // label1


 132:             // 


 133:             this.label1.AutoSize = true;


 134:             this.label1.Location = new System.Drawing.Point(40, 108);


 135:             this.label1.Name = "label1";


 136:             this.label1.Size = new System.Drawing.Size(100, 13);


 137:             this.label1.TabIndex = 3;


 138:             this.label1.Text = "Frequency Change:";


 139:             // 


 140:             // label2


 141:             // 


 142:             this.label2.AutoSize = true;


 143:             this.label2.Location = new System.Drawing.Point(43, 166);


 144:             this.label2.Name = "label2";


 145:             this.label2.Size = new System.Drawing.Size(97, 13);


 146:             this.label2.TabIndex = 4;


 147:             this.label2.Text = "Current Frequency:";


 148:             // 


 149:             // btnStop


 150:             // 


 151:             this.btnStop.Location = new System.Drawing.Point(111, 61);


 152:             this.btnStop.Name = "btnStop";


 153:             this.btnStop.Size = new System.Drawing.Size(88, 21);


 154:             this.btnStop.TabIndex = 5;


 155:             this.btnStop.Text = "Stop";


 156:             this.btnStop.UseVisualStyleBackColor = true;


 157:             this.btnStop.Click += new System.EventHandler(this.btnStop_Click);


 158:             // 


 159:             // openFileDialog1


 160:             // 


 161:             this.openFileDialog1.FileName = "openFileDialog1";


 162:             this.openFileDialog1.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog1_FileOk);


 163:             // 


 164:             // btnNewFile


 165:             // 


 166:             this.btnNewFile.Location = new System.Drawing.Point(205, 61);


 167:             this.btnNewFile.Name = "btnNewFile";


 168:             this.btnNewFile.Size = new System.Drawing.Size(75, 23);


 169:             this.btnNewFile.TabIndex = 6;


 170:             this.btnNewFile.Text = "Open";


 171:             this.btnNewFile.UseVisualStyleBackColor = true;


 172:             this.btnNewFile.Click += new System.EventHandler(this.btnNewFile_Click);


 173:             // 


 174:             // lblFile


 175:             // 


 176:             this.lblFile.AutoSize = true;


 177:             this.lblFile.Location = new System.Drawing.Point(23, 30);


 178:             this.lblFile.Name = "lblFile";


 179:             this.lblFile.Size = new System.Drawing.Size(148, 13);


 180:             this.lblFile.TabIndex = 7;


 181:             this.lblFile.Text = "C:\\Windows\\Media\\ding.wav";


 182:             // 


 183:             // label3


 184:             // 


 185:             this.label3.AutoSize = true;


 186:             this.label3.Location = new System.Drawing.Point(23, 9);


 187:             this.label3.Name = "label3";


 188:             this.label3.Size = new System.Drawing.Size(63, 13);


 189:             this.label3.TabIndex = 8;


 190:             this.label3.Text = "Current File:";


 191:             // 


 192:             // MainForm


 193:             // 


 194:             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);


 195:             this.ClientSize = new System.Drawing.Size(292, 260);


 196:             this.Controls.Add(this.label3);


 197:             this.Controls.Add(this.lblFile);


 198:             this.Controls.Add(this.btnNewFile);


 199:             this.Controls.Add(this.btnStop);


 200:             this.Controls.Add(this.label2);


 201:             this.Controls.Add(this.label1);


 202:             this.Controls.Add(this.txtFreq);


 203:             this.Controls.Add(this.trackBar1);


 204:             this.Controls.Add(this.btnPlay);


 205:             this.Name = "MainForm";


 206:             this.Text = "Sound Frequency Changer";


 207:             ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();


 208:             this.ResumeLayout(false);


 209:             this.PerformLayout();


 210:  


 211:         }


 212:         #endregion


 213:  


 214:         /// <summary>


 215:         /// The main entry point for the application.


 216:         /// </summary>


 217:         [STAThread]


 218:         static void Main()


 219:         {


 220:             Application.Run(new MainForm());


 221:         }


 222:  


 223:         private void btnPlay_Click(object sender, System.EventArgs e)


 224:         {


 225:             


 226:             sound.Play(0, BufferPlayFlags.Looping);


 227:             btnPlay.Enabled = false;


 228:             btnStop.Enabled = true;


 229:         }


 230:  


 231:         private void trackBar1_ValueChanged(object sender, EventArgs e)


 232:         {


 233:             txtFreq.Text = trackBar1.Value.ToString();


 234:             sound.Frequency = trackBar1.Value;


 235:             btnPlay.Enabled = true;


 236:         }


 237:  


 238:         private void btnNewFile_Click(object sender, EventArgs e)


 239:         {


 240:             openFileDialog1.Filter = "wav files (*.wav)|*.wav|All files (*.*)|*.*";


 241:             openFileDialog1.ShowDialog();


 242:         }


 243:  


 244:         private void openFileDialog1_FileOk(object sender, CancelEventArgs e)


 245:         {


 246:             sound.Stop();


 247:             btnPlay.Enabled = true;


 248:             btnStop.Enabled = false;


 249:             lblFile.Text = openFileDialog1.FileName;


 250:             sound = new SecondaryBuffer(openFileDialog1.FileName, d, applicationDevice);


 251:             sound.Frequency = 0; //The default frequency


 252:  


 253:         }


 254:  


 255:         private void btnStop_Click(object sender, EventArgs e)


 256:         {


 257:             sound.Stop();


 258:             btnStop.Enabled = false;


 259:             btnPlay.Enabled = true;


 260:         }


 261:     }


 262: }


 263:  


 264:  







This will allow me to use a beam or phaser sound to create the appearance of strength applied on a element.

Monday, January 19, 2009

Dynamic Loading Expression Media Player Template and passing parameters by code

Following my previous post on How to pass parameters to the Expression MediaPlayer component by code, here is a solution that builds upon this post to Dynamicaly load the Media Player inside your app and pass parameters to it.

You can test loading of the player here. The source code can also be downloaded here.

The loading and costumization of the parameters is done like this:

// Download the Media Player using WebClient
private void downloadVideoPlayer()
{
WebClient downloader = new WebClient();
downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(onDownloadVideoPlayerCompleted);
downloader.OpenReadAsync(new Uri("MediaPlayerTemplate.xap", UriKind.Relative));
lblLoadPlayer.Text = "Downloading Media Player";
}

// Once the Media Player is downloaded
private void onDownloadVideoPlayerCompleted(object sender, OpenReadCompletedEventArgs args)
{
try
{
string appManifest = new StreamReader(Application.GetResourceStream(new StreamResourceInfo(args.Result, null), new Uri("AppManifest.xaml",UriKind.Relative)).Stream).ReadToEnd();

XElement deploymentRoot = XDocument.Parse(appManifest).Root;
List<XElement> deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
select assemblyParts).ToList();

Assembly asm = null;
foreach (XElement xElement in deploymentParts)
{
string source = xElement.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(args.Result, "application/binary"), new Uri(source, UriKind.Relative));
if (source == "MediaPlayerTemplate.dll")
{
asm = asmPart.Load(streamInfo.Stream);
}
else asmPart.Load(streamInfo.Stream);
}



MediaPlayerTemplate.Page myPlayer = asm.CreateInstance("MediaPlayerTemplate.Page") as MediaPlayerTemplate.Page;
Dictionary<string,string> dic = new Dictionary<string, string>();
dic.Add("autoplay", "true");
dic.Add("enablecaptions", "true");
dic.Add("muted", "false");
dic.Add("stretchmode", "0");
dic.Add("displaytimecode", "false");
dic.Add("playlist", "<playList><playListItems><playListItem title=\"\" description=\"\" mediaSource=\"silverlight.wmv\" adaptiveStreaming=\"False\" thumbSource=\"\" frameRate=\"23.9760431376968\" width=\"512\" height=\"284\" ><chapters><chapter position=\"11.256\" title=\"MYMARKER01\" /><chapter position=\"20.033\" thumbnailSource=\"silverlight_20.033.jpg\" title=\"Capitulo%201\" /><chapter position=\"45.585\" thumbnailSource=\"silverlight_45.585.jpg\" title=\"Chapter%202\" /><chapter position=\"58.646\" thumbnailSource=\"silverlight_58.646.jpg\" title=\"Chapter%203\" /><chapter position=\"72.199\" thumbnailSource=\"silverlight_72.199.jpg\" title=\"Chapter%204\" /></chapters></playListItem></playListItems></playList>");
myPlayer.StartUp(dic);

cnvMediaPlayer.Children.Add(myPlayer);
lblLoadPlayer.Text = "";
LayoutRoot.UpdateLayout();

}
catch (Exception e)
{
lblLoadPlayer.Text = "Download Error: " + e.Message;
}
}



If you download the source code you will need to create your own playlist that points to a a movie of your own and set the thumbnails and chapters as you wish. Check the following line of code inside VideoPlayerHoster, Page.xaml.cs



dic.Add("playlist", "<playList>...



The Dynamic loading was implemented by looking at these 2 posts:



http://www.silverlighthack.com/post/2008/09/29/Silverlight-2-(RC0-RTM)-Dynamic-Assembly-Loading.aspx



http://silverlight.net/learn/learnvideo.aspx?video=65687



Using Expression Encoder 2 MediaPlayer Templates in your application

Microsoft Expression Encoder 2 SP1 now includes a set of Silverlight 2 Output Templates:

clip_image002

After installing SP1 you'll have a some Silverlight 2 templates in "C:\Program Files\Microsoft Expression\Encoder 2\Templates\en".

The Templates use 2 controls that implement most of the logic that we need on our media apps: MediaPlayer and ExpressionPlayer. These controls take care of all basic media handling functionalities but also Video Marker handling, Chapters and chapter thumbnails, playlists, cpations, etc.

Out-of-the-box the templates can be hosted in a html or aspx page and the parameters passed when loading the XAP. Here is the html of the page that is created when running your template:




<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="MediaPlayerTemplate.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="initparams" value='autoplay=&lt;$=TemplateParameter.AutoPlay$>,autoload=<$=TemplateParameter.AutoLoad$>,enablecaptions=<$=TemplateParameter.EnableCaptions$>,muted=<$=TemplateParameter.Muted$>,stretchmode=<$=TemplateParameter.StretchMode$>,displaytimecode=<$=TemplateParameter.DisplayTimecode$>,playlist=<$=PlayListParam(TemplateParameter.AllowedCodecs)$>' />

All customization is made via the initparams.If you want to use the MediaPlayer inside your own Silverlight application (that happens to use a media player) you need to make same changes in order to pass the parameters by code and not by the initparams of the silverlight object command in HTML as the template does.



When Silverlight loads the XAP via HTML it calls:




        public Page(object sender, StartupEventArgs e)

        {

            InitializeComponent();

            myPlayer.OnStartup(sender, e);

        }


Since you cannot create a StartupEventArgs class because it is marked as internal we need another way to pass our parameters from code.



Here are the changes:



1. In ExpressionPlayerControl.cs change the OnStartup method to receive a Dictionary<string, string> instead of StartupEventArgs:




public override void OnStartup(object sender, StartupEventArgs e)

replace by


public override void OnStartup(object sender, Dictionary<string, string> e)


2. Inside the OnStartup method replace "e.InitParams" for InitParams.



3. Since ExpressionPlayer derives from MediaPlayer and OnStartup is overrided we also need to update the OnStartup method in MediaPayer.cs:



public override void OnStartup(object sender, StartupEventArgs e)


replace by


public override void OnStartup(object sender, Dictionary<string, string> e)


4. Since you changed the method signature you also need to update the call to it on Page.xaml.cs and cast it to Dictionary<string, string>:




public Page(object sender, StartupEventArgs e)

{

    InitializeComponent();

    myPlayer.OnStartup(sender, (Dictionary<string, string>) e.InitParams);

}




5. Create a new method that will allow your code to costumize the player:



public void StartUp(Dictionary<string, string> InitParams)

{

    myPlayer.OnStartup(this, InitParams);

}


6. Now you are ready to costumize your mediaplayer from code:





   1:  MediaPlayerTemplate.Page myPlayer = asm.CreateInstance("MediaPlayerTemplate.Page") as MediaPlayerTemplate.Page;

   2:  Dictionary<string,string> dic = new Dictionary<string, string>();

   3:  dic.Add("autoplay", "true");

   4:  dic.Add("enablecaptions", "true");

   5:  dic.Add("muted", "false");

   6:  dic.Add("stretchmode", "0");

   7:  dic.Add("displaytimecode", "false");

   8:  dic.Add("playlist", "<playList><playListItems><playListItem title=\"\" description=\"\" mediaSource=\"silverlight.wmv\" adaptiveStreaming=\"False\" thumbSource=\"\" frameRate=\"23.9760431376968\" width=\"512\" height=\"284\" ><chapters><chapter  position=\"11.256\" title=\"MYMARKER01\" /><chapter  position=\"20.033\" thumbnailSource=\"silverlight_20.033.jpg\" title=\"Capitulo%201\" /><chapter  position=\"45.585\" thumbnailSource=\"silverlight_45.585.jpg\" title=\"Chapter%202\" /><chapter  position=\"58.646\" thumbnailSource=\"silverlight_58.646.jpg\" title=\"Chapter%203\" /><chapter  position=\"72.199\" thumbnailSource=\"silverlight_72.199.jpg\" title=\"Chapter%204\" /></chapters></playListItem></playListItems></playList>");

   9:   

  10:  myPlayer.StartUp(dic);





(assuming myPlayer was defined in your Xaml)

Saturday, December 13, 2008

Host Deep Zoom project on Silverlight Streaming

It is possible to host a Deep Zoom project with all it's images on silverlight.live.com
It doesn't seem possible at first because the interface asks you to upload only the xap file. So ... where do we put the images ? You just need to do some "magic" as explained here

Here is a sample project hosted there.

Unexpected browser crash with Silverlight 2

I'm developing a Silverlight application that uses the MultiScaleImage control and also some text overlays that i'm scaling according to the Deep Zoom scale. Very often the browser (Internet Explorer, Firefox and Chrome) crashes.

It seems there is an issue mixing ScaleTransform and MultiScaleImage control as also posted on the Silverlight Forums

The Application that has this problem is this one when you enable the checkbox useScaleTransform, but with a different Deep Zoom output. with the one shown here does not seem to reproduce the problem :(

Here is the entry on the event viewer:

Faulting application IEXPLORE.EXE, version 7.0.6000.16764, time stamp 0x48f6a2ed, faulting module ntdll.dll, version 6.0.6000.16386, time stamp 0x4549bdf8, exception code 0xc0000029, fault offset 0x000675fc, process id 0xf18, application start time 0x01c95d5ad4de2d60.