Free open source UI toolkits you should check out for your Windows Phone / Windows Store apps

<This post will be updated in time. Kindly check back for newer entries>

When windows phone hit it’s 8.1 upgrade from Windows Phone 8 version, it shifted itself up from silverlight to WinRT kernel. Some of the hardcore Windows Phone fanatics like me was pretty sad because we lost access to our favourite UI toolkits by then. Although a lot of the expected UI controls came through in the sdk itself, still something was missing. This is a log of a set of UI toolkits you should discover when you are making your Windows Phone/Universal Apps.

1. SlideView: A Facebook like panel for Windows Phone: Ever wonder how a android like SlideView would look like in your native Windows Phone? Check this toolkit out Today!

2. WinRT XAML Toolkit:  The perfect set of helpers, extensions and mostly all of the controls from Windows Phone Toolkit has been ported here. It has Calendar, Gauge and other data visualization tool too.

3. MyToolkit for .NET:  Are you a big fan Windows App Studio? Do you know what has been used inside to facilitate all that? Meet MyToolkit. From MVVM toolkit to DataGrid everything is here, possibly everything. It even supports Xamarin projects too. 🙂

4.ExpanderRT: ExpanderRT is the ExpanderView port from Windows Phone 8 to WinRT. Missing the great control, don’t! 😉

I will continuously keep updating this blog post as soon as I find a new toolkit to add. 😉

Saving a SpeechSynthesis Audio in a windows store/phone app

Usually after doing a little speech synthesizing in our phone we usually stumble on one question, can I save this stream?
Luckily you can! All you gotta do is pull this out of your sleeve. 🙂

 


var synth = Windows.Media.SpeechSynthesis.SpeechSynthesizer();

SpeechSynthesisStream speechstream = await synth.SynthesizeTextToStreamAsync("Hello People");

using(var reader = new DataReader(speechstream))
{

await reader.LoadAsync((uint)stream.Size);

IBuffer buffer = reader.ReadBuffer((uint)stream.Size);

await FileIO.WriteBufferAsync(outputFile, buffer);

}

And, you’re done! Your file would be a .wav file of course.

Windows Phone 8.1 for Newbies – Navigation of Windows Phone 8.1 – Frame, Page and SuspensionManager

Windows Phone for Newbies সিরিজে এবার আমাদের বিষয় Windows Phone 8.1 এর নেভিগেশন মডেল। আমরা আজকে দেখবো আপনি একটি নতুন একটি অ্যাপ এ নেভিগেশন কিভাবে handle করবেন। আরো দেখবো আসলে নেভিগেশন কি করে হয়।

শুরুতে আমাদের দরকার একটি নতুন অ্যাপ। তো চলে যান আপনার Visual Studio তে। আমি ব্যবহার করছি Visual Studio 2013 Community Edition. আসুন খুলে নেই নতুন একটি প্রজেক্ট। চলে যান ফাইল -> নিউ প্রজেক্ট

Navigation-1

এখানে দেখতে পাবেন আপনার জন্যে বেশ কয়েকটি প্রজেক্ট টেমপ্লেট আছে। Blank, Pivot, Hub app এই তিনটি টেমপ্লেট আছে। আপনি যদি Pivot অথবা hub টেমপ্লেট সিলেক্ট করেন তাহলে NavigationHelper, SuspensionManager এর মতো Helper Class গুলো পেয়ে যাবেন। কিন্তু এখনকার জন্যে সেগুলো আপনার জন্যে একটু বেশি হয়ে যাবে। আসুন আমরা blank template নিয়ে এগিয়ে যাই।

তো তৈরী করে ফেলুন একটি Blank App. আমি আগেই বলেছি আমরা কিছু Helper Class পাবোনা এই টেমপ্লেট এ। একটি ছোট হ্যাক আছে সেগুলো এই টেমপ্লেট এ নিয়ে আসার। প্রথমে আপনি MainPage.xaml পেজটি Solution explorer থেকে delete করে দিন। এবার Solution Explorer এ সলুশ্যন এর নাম এর ওপরে right click করে Add-> New Item এ চলে যান।

Navigation-2

এরপর সিলেক্ট করুন Basic Page. দেখবেন নিচের মতো একটি পপ আপ ভেসে উঠবে।

Navigation-3

Navigation-4

এখন দেখবেন আপনার প্রজেক্টের Common Folder এ নিচের class গুলো যোগ হয়ে গিয়েছে।

Navigation-5

আমাদের আজকের বিষয় যেহেতু Navigation আমরা শুধু NavigationHelper আর SuspensionManager নিয়ে কথা বলবো।

SuspensionManager এবং Frame:

Windows Phone 8.1 এ আপনার UI টি আসলে বসে থাকে একটি Frame UI control এর উপর এবং এই Frame টি জানে কিভাবে এক Page হতে অন্য Page এ নেভিগেট করতে হয়। এখানেই উইন্ডোজ ফোন ৮.১ উইন্ডোজ ফোন ৮ থেকে আলাদা। এখানে একটি page এ একাধিক Frame থাকতে পারে। আপনি চাইলেই পারেন একটি Single Page Application বানাতে। এবং যেহেতু একটি Frame এ আপনার Navigation History (কোন পেইজ থেকে কোন পেইজে গিয়েছেন তার লিস্ট) থাকে সেহেতু একটি Page এ multiple frame থাকলে multiple navigation history ও থাকতে পারে। তবে তার কথায় এখন যাচ্ছিনা।

আসুন আমরা দেখি Frame কোথায় তৈরী হয়। এটি তৈরী হয় Application.OnLaunched (app.xaml.cs) এ। এটি Window.content property তে দেখে যে main UI টি তৈরী হয়েছে কিনা। না হলে তৈরী করে নেয়। এভাবেই আপনার root frame তৈরী হয়।

protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                // TODO: change this value to a cache size that is appropriate for your application
                rootFrame.CacheSize = 1;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    // TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // Removes the turnstile navigation for startup.
                if (rootFrame.ContentTransitions != null)
                {
                    this.transitions = new TransitionCollection();
                    foreach (var c in rootFrame.ContentTransitions)
                    {
                        this.transitions.Add(c);
                    }
                }

                rootFrame.ContentTransitions = null;
                rootFrame.Navigated += this.RootFrame_FirstNavigated;

                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
            }

            // Ensure the current window is active
            Window.Current.Activate();
        }

এখন একটু ভালোমতো খেয়াল করে দেখবেন frame একটি content control (এর একটি content property) আছে আর কি। এর বেশ কিছু method আছে যেমন (Navigate, CanNavigate) এবং এটি আপনার Navigation BackStack manage করে। কিন্তু যে দুটো ফাংশন নিয়ে আমি কথা বলতে চাই তা হচ্ছে

  • GetNavigationState
  • SetNavigationState

মনে করি আমাদের অ্যাপ এ ৩টি পেইজ আছে, প্রত্যেক পেইজে navigate করার সময় একটি param পাঠানো যায়। তাহলে navigation stack টা দাঁড়ায় এরকম Page 1 ( param 1 ) –> Page 2 ( param 2 ) –> Page 3 ( param 3 )

এখন আমরা যদি চাই কোন Page এর Frame এর state জানতে আমরা GetNavigationState() ব্যবহার করতে পারি। আমরা চাইলে Frame টি destroy করতে পারি এবং নতুন করে recreate করতে পারি। এবং চাইলে Frame টি যেখানে ছিলো সেইখানে তাকে রেখে আসতে পারি SetNavigationState() ফাংশনটি ব্যবহার করে।

যদি আমাদের navigation parameter এ সব দেয়া থাকে (যেটা navigate করার সময় আমরা পাঠিয়েছিলাম) তাহলে আমরা যে কোন Frame যে কোন অবস্থা থেকে পুনরায় তৈরী করতে পারবো। এটি কাজে লাগে তখন যখন আমাদের কোন অ্যাপ OS থেকে terminate হয়ে যায় এবং আমরা অ্যাপটিকে ঠিক আগের জায়গা থেকে শুরু করাতে চাই। আর এই কাজটি করতে পারে SuspensionManager class.

এখন SuspensionManager এ আমাদের Frame restore করতে চাইলে একে জানতে হবে Frame কোনটি। তাই Grid, Hub এইসব প্রজেক্ট টেমপ্লেট এ SuspensionManager এ Frame register করা থাকে। আপনি যদি blank template ব্যবহার করে থাকেন তাহলে আপনার OnLaunched মেথডে নিচের কোডটুকু যোগ করে ফেলুন।


Frame rootFrame = Window.Current.Content as Frame;

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();

// MT: Register the Frame with the SuspensionManager.
SuspensionManager.RegisterFrame(rootFrame, "rootFrameKey");

তাহলে আসুন দেখি আমরা এতোক্ষণ কি দেখলাম।

navigation -5

এই register করার মাধ্যমে SuspensionManager জেনে নেয় এই Frame টি তে প্রয়োজনের সময় সে ফেরত আসতে পারবে।

SuspensionManager কিভাবে Frame restore করে

আসুন দেখি কিভাবে app terminate হয়ে যাবার পর ও আমরা একই Frame এ ফেরত যেতে পারি। আপনার Application.OnLaunched override এ এই কোডটুকু already আছে:


if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}

সাথে এইটুকু যোগ করে নিলেই হলো। এখন আপনার অ্যাপ Terminate হয়ে গেলেও user তার আগের Frame এ ফেরত যেতে পারবে। News app এর feature হিসেবে চমৎকার।


if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
await SuspensionManager.RestoreAsync();
}

এটি একটি async call কারণ SuspensionManager আপনার ফোনের Storage এ গিয়ে Frame navigation history খুঁজে বের করে এবং Frame টি কে SetNavigationState method এর মাধ্যমে তার পুরনো জায়গায় ফেরত দিয়ে আসে।

navigation - 6

মনে রাখবেন সব সময় এই কাজটি করবার দরকার নেই । অনেক আগে একটি অ্যাপ বন্ধ হয়ে গেলে সেটিকে আবার সেই পুরনো স্টেট এ নিয়ে যাবার দরকার নেই। আপনি চাইলেই এরকম একটি কোড সেগমেন্ট রাখতে পারেন যেখানে একটি নির্দিষ্ট সময় বা ইউজার বললে অ্যাপটি আর Frame restore করবেনা।

মজার ব্যাপার হচ্ছে restore করতে হলে state save করতে হয়। আমরা register এবং restore করেছি। save করিনি। state save না করলে restore কি করে হবে বলুন? 🙂

SuspensionManager কিভাবে App Suspension এর সময় State save করে

যখনি আপনার অ্যাপ টি Suspend হচ্ছে (terminate নয়) তখন ই আপনার অ্যাপটির SuspensionManager এর state disk এ save করলে পরে আপনি অ্যাপটি চালু করলে সে আবার পুনরায় আগের অবস্থায় Frame টি কে নিয়ে যাবে।

navigation - 7

যেহেতু এটি Suspension এর ইস্যু তাই আমাদের Application.OnSuspending handler লিখতে হবে এবং এটিতে আপনি Frame State save করতে পারেন এভাবে:


private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();

await SuspensionManager.SaveAsync();

deferral.Complete();
}

উপরের ছবিটি খেয়াল করে দেখলে বুঝবেন SuspensionManager একটি Global set of state রাখে নিজের কাছে যেটি আপনি SuspensionManager.SessionState হতে ব্যবহার করতে পারেন। এই Global State এর মধ্যে থাকে একটি Dictionary থাকে যাতে প্রতিটি Frame থাকে এবং তার মধ্যে প্রতিটি Page এর State এর একটি Dictionary থাকে যা NavigationHelper class ব্যবহার করে। আমরা এটি নিয়ে একটু পরে দেখবো।

কিছু নতুন Page যোগ করা:

আমি জানি অনেকেই সরাসরি এই জিনিসটি দেখতে চান কিন্তু যেহেতু Windows Phone 8.1 একটু আলাদা Windows Phone 8 থেকে তাই Frame এবং Page এর ব্যপারে কিছু না বললে ই নয়। আপনি যদি পুরোটা আগে পড়ে থাকেন তাহলে আপনি অবশ্যই উইন্ডোজ ফোন ৮.১ এর নেভিগেশন মডেল বেশ ভালোভাবে জানেন।

আমরা চলে যাই আবার Visual Studio 2013 এ। আমরা উপরে লেখা উপায়ে আরো দুটি Basic Page (Blank page নয়) যোগ করবো। প্রতিটি ক্ষেত্রেই আমি Add New Item dialog টি ব্যবহার করেছি।

আমার যোগ করা Page গুলোর নাম SecondPage এবং ThirdPage

আমার MainPage.xaml টি নিচের মতো:


<Page x:Name="pageRoot"
x:Class="BlankApp.SecondPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlankApp"
xmlns:common="using:BlankApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="Green">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock x:Name="pageTitle"
Style="{StaticResource HeaderTextBlockStyle}"
Grid.Column="1"
IsHitTestVisible="false"
TextWrapping="NoWrap"
VerticalAlignment="Bottom"
Margin="0,0,30,40" />
</Grid>
<StackPanel Grid.Row="1"
Margin="120,0,0,0">
<TextBox x:Name="txtMainPageOne"
Text="Not Set" />
<Button Content="Navigate Second Page"
Click="OnNavigateSecondPage" />
</StackPanel>
</Grid>
</Page>

সবচেয়ে কাজে লাগার Method টি হচ্ছে OnNavigateSecondPage যেটি আপনাকে Second Page এ নিয়ে যাবে।


private void OnNavigateSecondPage(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(SecondPage), this.txtMainPageOne.Text);
}

খেয়াল করে দেখবেন txtMainPageOne টেক্সটবক্স এ যা ছিলো তা আমি parameter হিসেবে SecondPage.xaml এ পাঠিয়ে দিয়েছি।

SeondPage.xaml দেখতে এরকম:


<Page x:Name="pageRoot"
x:Class="BlankApp.SecondPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlankApp"
xmlns:common="using:BlankApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="Green">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock x:Name="pageTitle"
Style="{StaticResource HeaderTextBlockStyle}"
Grid.Column="1"
IsHitTestVisible="false"
TextWrapping="NoWrap"
VerticalAlignment="Bottom"
Margin="0,0,30,40" />
</Grid>
<StackPanel Grid.Row="1"
Margin="120,0,0,0">
<TextBox x:Name="txtSecondPageOne"
Text="Not Set" />
<Button Content="Navigate Thid Page"
Click="OnNavigateThirdPage" />
</StackPanel>
</Grid>
</Page>

তার মানে MainPage থেকে পাঠানো parameter আমি access করতে পারবো navigationHelper_LoadState method এ।


private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
this.pageTitle.Text = (string)e.NavigationParameter;
}

private void OnNavigateThirdPage(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(ThirdPage), this.txtSecondPageOne.Text);
}

দেখতেই পাচ্ছেন SeconPage থেকে ThirdPage এও যাবার সময় আমি একটি parameter পাঠিয়ে দিচ্ছি যা txtSecondPageOne textbox এ লেখা। এবং NavigationHelper class এখন আমাদের কাজে লাগলো কারণ এটি মাত্রই আমাদের Navigation Parameter e হতে MainPage.xaml হতে পাঠানো parameter টি লোড করলো।

আমাদের ThirdPage.xaml টি হলো:


<Page x:Name="pageRoot"
x:Class="BlankApp.ThirdPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlankApp"
xmlns:common="using:BlankApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="Orange">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock x:Name="pageTitle"
Style="{StaticResource HeaderTextBlockStyle}"
Grid.Column="1"
IsHitTestVisible="false"
TextWrapping="NoWrap"
VerticalAlignment="Bottom"
Margin="0,0,30,40" />
</Grid>
</Grid>

</Page>

এখন খেয়াল করে দেখবেন আপনার অ্যাপটি নেভিগেট করার সময় প্যারামিটার ঠিকমতো পাস করে নিয়ে যাচ্ছে কিন্তু ব্যাক বাটন চাপলে অ্যাপটি বন্ধ হয়ে যাচ্ছে।

navigation - 8

 

এর কারণ এবং বের হবার উপায় আমরা দেখবো পরের পোস্ট এ। সেখানে আরো দেখবো কিভাবে পেজ ক্যাশ করতে হয়। 🙂

 

 

Making a game controller out of your Windows Phone using VJoy – Part 1.

I know the title sounds really intriguing. Truth to be told it is indeed intriguing. And as it goes the outcome is pretty intriguing too.

The whole tutorial would take a bit time to get inside your head, so Im going to take it step by step.

Step 1: The Bluetooth Server

To have this whole thing going we will need a bluetooth server going. To facilitate a very very simple bluetooth server we are going to use a Windows Store app. So I jotted down a very very simple GUi for the server first.


<Page
    x:Class="BluetoothServer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BluetoothServer"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel VerticalAlignment="Bottom" Margin="0,0,0,150" >
            <TextBlock Name="StatusText" FontSize="25" Margin="35,0,35,57" TextAlignment="Center"></TextBlock>
            <Button Content="Initiate Server"  Name="ServerToggleButton" HorizontalAlignment="Center" Click="Button_Click" />
            
        </StackPanel>
    </Grid>
</Page>

The only input mechanism I have in here is a textbox and a button. You pick the button to initiate a server and that’s it. All the code that has been used here are actually very very raw and coded in a hurry. So try to get the gist of the idea first so you can get yourself started.

The first method we are going to put in the back is an Initialization method for the server. This would actually Initialize the Bluetooth server we are going to use.


private StreamSocket socket;

private DataWriter writer;
private RfcommServiceProvider rfcommProvider;
private StreamSocketListener socketListener;

public async void InitializeRfCommServer()
{
            try
            {
                rfcommProvider = await RfcommServiceProvider.CreateAsync(RfcommServiceId.FromUuid(RfcommServiceUuid));

                // Create a listener for this service and start listening
                socketListener = new StreamSocketListener();
                socketListener.ConnectionReceived += OnConnectionReceived;

                await socketListener.BindServiceNameAsync(rfcommProvider.ServiceId.AsString(),
                   SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);

                 // Set the SDP attributes and start Bluetooth advertising
                InitializeServiceSdpAttributes(rfcommProvider);
                rfcommProvider.StartAdvertising(socketListener);

                StatusText.Text="Listening for incoming connections";
                ServerInitiated = true;

            }
            catch(Exception e)
            {
                StatusText.Text = e.Message;
                
                ServerInitiated = false;
            }
}

Here, Windows.Devices.Bluetooth.Rfcomm comes in extremely handy as RfcommServiceProvider is the prefect class to start a RFComm session. But before all that you are going to need some basic stuff. First you will need a service GUID. You can make a GUID from any place but I suggest to try make an unique one. Here I used something I generated from a site online but you can definitely try your way. Then you are going to need a SdpServiceNameAttributeId and SdpServiceNameAttributeType. SdpServiceNameAttributeType is actually a 8 bit scenario where the least significant 3 bits contains attribute size and the most significant 5 bits contains the attribute type value. And last but not the least you will need a service name too.


        private static readonly Guid RfcommServiceUuid = Guid.Parse("482af5ed-3faf-4a51-9dd0-718c85aa64d0");
        private const UInt16 SdpServiceNameAttributeId = 0x100;
        private const byte SdpServiceNameAttributeType = (4 << 3) | 5;
        private const string SdpServiceName = "Bluetooth Rfcomm Listening Service for VJoy";

Please keep these in mind because we are going to need these in the client too. And you also have to define these in your Package.appxmanifest too to make the server authorized to use the bluetooth in your pc.


<m2:DeviceCapability Name="bluetooth.rfcomm">
      <m2:Device Id="any">
        <m2:Function Type="serviceId:34B1CF4D-1069-4AD6-89B6-E161D79BE4D8"/>
      </m2:Device>
    </m2:DeviceCapability>

After all these are done and dusted, let’s move on with initializing the bluetooth server. The next thing that comes is a StreamSocketListener. And it’s job is kind of explained in it’s name. It will serve as our stream listener that would be recieved from the clients. Thus it has a ConnectionReceived event that has to be populated too.

The next thing to do would be bind the service name. Our StreamSocketListener object has a BindServiceNameAsync method to do so with serviceID and an option to take as a parameter. I defined SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication because I didnt want much security over the communication. You can explore other options if you want to impose some security measures.

Next comes InitializeServiceSdpAttributes(rfcommProvider) and he looks like the following:


        private void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider)
        {
            var sdpWriter = new DataWriter();

            // Write the Service Name Attribute.

            sdpWriter.WriteByte(SdpServiceNameAttributeType);

            // The length of the UTF-8 encoded Service Name SDP Attribute.
            sdpWriter.WriteByte((byte)SdpServiceName.Length);

            // The UTF-8 encoded Service Name value.
            sdpWriter.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
            sdpWriter.WriteString(SdpServiceName);

            // Set the SDP Attribute on the RFCOMM Service Provider.
            rfcommProvider.SdpRawAttributes.Add(SdpServiceNameAttributeId, sdpWriter.DetachBuffer());   
        }

The purpose of this method is definitely putting the SdpRawAttributes in place by using a DataWriter. Here we put in possibly everything we defined before for our bluetooth device.

The only thing we need to do just before calling StartAdvertising, we need to define our ConnectionReceived event.


private async void OnConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            try
            {
                socketListener.Dispose();
                socketListener = null;

                socket = args.Socket;

                writer = new DataWriter(socket.OutputStream);

                var reader = new DataReader(socket.InputStream);
                bool remoteDisconnection = false;

                bool res;
                while (true)
                {
                    uint readLength = await reader.LoadAsync(sizeof(uint));
                    if (readLength < sizeof(uint))
                    {
                        remoteDisconnection = true;
                        break;
                    }
                    uint currentLength = reader.ReadUInt32();

                    readLength = await reader.LoadAsync(currentLength);
                    if (readLength < currentLength)
                    {
                        remoteDisconnection = true;
                        break;
                    }
                    string message = reader.ReadString(currentLength);
                }

                reader.DetachStream();
                if (remoteDisconnection)
                {
                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        Disconnect();
                    });
                }

            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }

This is where the server keeps looping for message and Im not kidding. You will find a while(true) inside and what it does is it keeps reading data from the socket until someone pulls the trigger or somehow the connection gets jeopardized. You will see even a basic check on buffer length triggers the server to stop. And in any case of an exception an async Disconnect() is due.

And Disconect() is nothing but as simple as the following:


        private void Disconnect()
        {
            if (rfcommProvider != null)
            {
                rfcommProvider.StopAdvertising();
                rfcommProvider = null;
            }

            if (socketListener != null)
            {
                socketListener.Dispose();
                socketListener = null;
            }

            if (writer != null)
            {
                writer.DetachStream();
                writer = null;
            }

            if (socket != null)
            {
                socket.Dispose();
                socket = null;
            }

            ServerInitiated = false;
        }

Now , we can trigger this one from a toggle button like the following:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (ServerInitiated)
            {
                Disconnect();
                ServerToggleButton.Content = "Initiate Server";
            }
            else
            {
                InitializeRfCommServer();
                ServerToggleButton.Content = "Disconnect Server";
               
            }
        }

But the thing is that’s just a bluetooth server. To test it out you will need a bluetooth client too.

Step 2: The Bluetooth Client

The bluetooth client is essentially a Windows Phone app. I couldve showed the XAML here but that wouldn’t look that simple. In spite of doing that, let’s break down what do we have to do now. We have to:

1. Connect to a paired device. (Yes, you have to have your devices paired)

2. Search the bluetooth service we are looking for and if we find any, we’d give a list to pick

3. Use that selected device and send data to it .

Here, definitely the paired device is a device that has our server running.

Let’s assume we have a run button that starts the search for the paired devices with the desired service. Remember I said that we will need our service GUID and other identifications to make this work even from the client side because it has to know which service it is feeding itself to.

Thus, this definitions first come in place:

private static readonly Guid RfcommChatServiceUuid = Guid.Parse("482af5ed-3faf-4a51-9dd0-718c85aa64d0");

// The Id of the Service Name SDP attribute
private const UInt16 SdpServiceNameAttributeId = 0x100;
private const byte SdpServiceNameAttributeType = (4 << 3) | 5;

private StreamSocket chatSocket;
private DataWriter chatWriter;
private RfcommDeviceService chatService;
private DeviceInformationCollection chatServiceInfoCollection;

and the run method looks like the following:


private StreamSocket chatSocket;
private DataWriter chatWriter;
private RfcommDeviceService chatService;
private DeviceInformationCollection chatServiceInfoCollection;

private async void RunButton_Click(object sender, RoutedEventArgs e)
{
// Find all paired instances of the Rfcomm chat service
chatServiceInfoCollection = await DeviceInformation.FindAllAsync(
RfcommDeviceService.GetDeviceSelector(RfcommServiceId.FromUuid(RfcommChatServiceUuid)));

if (chatServiceInfoCollection.Count > 0)
{
List<string> items = new List<string>();
foreach (var chatServiceInfo in chatServiceInfoCollection)
{
items.Add(chatServiceInfo.Name);
}
cvs.Source = items;
ServiceSelector.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
else
{
Debug.WriteLine("No chat services were found. Please pair with a device that is advertising the chat service.");

}
}

You can definitely understand DeviceInformationCollection does all the hard work here finding the device and the next thing to do would be selecting one and using it. After selecting we will start our chat session and indulge ourselves on a loop so we can keep receiving messages sent from the server, actually in our case thats not necessary, but still it’s nicer to have it on the place.


private async void ServiceList_Tapped(object sender, TappedRoutedEventArgs e)
{
try
{
RunButton.IsEnabled = false;
ServiceSelector.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

var chatServiceInfo = chatServiceInfoCollection[ServiceList.SelectedIndex];
chatService = await RfcommDeviceService.FromIdAsync(chatServiceInfo.Id);

if (chatService == null)
{
Debug.WriteLine(
"Access to the device is denied because the application was not granted access",
);
return;
}

var attributes = await chatService.GetSdpRawAttributesAsync();
if (!attributes.ContainsKey(SdpServiceNameAttributeId))
{
Debug.WriteLine(
"The Chat service is not advertising the Service Name attribute (attribute id=0x100). " +
"Please verify that you are running the BluetoothRfcommChat server.",
);
return;
}

var attributeReader = DataReader.FromBuffer(attributes[SdpServiceNameAttributeId]);
var attributeType = attributeReader.ReadByte();
if (attributeType != SdpServiceNameAttributeType)
{
Debug.WriteLine(
"The Chat service is using an unexpected format for the Service Name attribute. " +
"Please verify that you are running the BluetoothRfcommChat server.",);
return;
}

var serviceNameLength = attributeReader.ReadByte();

// The Service Name attribute requires UTF-8 encoding.
attributeReader.UnicodeEncoding = UnicodeEncoding.Utf8;
ServiceName.Text = "Service Name: \"" + attributeReader.ReadString(serviceNameLength) + "\"";

lock (this)
{
chatSocket = new StreamSocket();
}

await chatSocket.ConnectAsync(chatService.ConnectionHostName, chatService.ConnectionServiceName);

chatWriter = new DataWriter(chatSocket.OutputStream);
ControlBox.Visibility = Visibility.Visible;

DataReader chatReader = new DataReader(chatSocket.InputStream);
ReceiveStringLoop(chatReader);
}
catch (Exception ex)
{
RunButton.IsEnabled = true;
Debug.WriteLine("Error: " + ex.HResult.ToString() + " - " + ex.Message,);
}
}

The very basic thing it does it starts getting device info out and creates a String Loop that listens for a string. I wont go with that details rather I’d show how to send a bluetooth data through it.


private async void SendMessage(string message)
{
try
{
chatWriter.WriteUInt32((uint)message.Length);
chatWriter.WriteString(message);

await chatWriter.StoreAsync();

}
catch (Exception ex)
{
//MainPage.Current.NotifyUser("Error: " + ex.HResult.ToString() + " - " + ex.Message,
//    NotifyType.StatusMessage);
}
}

For the first part I’d stop here now, in the next two parts we are going to see how we are going to feed this data to vjoy and use our phone as a game controller. 🙂

গ্রাফ সার্চ – এ* সার্চ

গ্রাফ সার্চ নিয়ে কচকচানো শুরু করার কারণ আমি বেশ কয়েকদিন আগে একটি অ্যাপ এর কাজে এটি ব্যবহার করেছিলাম। ভাবলাম লিখে ফেলা উচিত, তাই শুরু করলাম। লেখাটা পড়ার আগে আপনার যা যা জানা থাকলে ভালো তা হচ্ছে।

  1. বেসিক গ্রাফ (http://en.wikipedia.org/wiki/Graph_%28mathematics%29)
  2. গ্রাফ ট্রাভের্সাল (http://en.wikipedia.org/wiki/Graph_traversal)

গ্রাফ সার্চের অসংখ্য মেথডের মধ্যে এ* সার্চ বেশ পরিচিত হবার কারণ এটি অনেক জায়গায় বিশাল কানেক্টেড একটি গ্রাফ এর এক প্রান্ত থেকে অন্য প্রান্তে যাবার রাস্তা খুঁজে বের করার জন্যে ব্যবহৃত হয়। যেসব জায়গায় এটি সবচেয়ে বেশি ব্যবহৃত হয় তা হচ্ছে:

  1. রুবিক কিউব সলভ করার জন্যে
  2. ম্যাপ এ রাউট সার্চ করার জন্যে
  3. রোবট নেভিগেশন রাউট বের করার জন্যে
  4. কোন গেইম এ পাথ, রাউট সার্চ করার জন্যে

অন্য সব অ্যালগরিদম থেকে এটির ব্যবহার এতো বেশি হবার কারণ এটি শুরু এবং শেষের নোড খোঁজার জন্যে শুরু এবং শেষের নোড এর আশেপাশের নোড গুলো থেকে শুরু করে। অন্য একটি কারণ হচ্ছে এ* সার্চ শুধুমাত্র একটি নোড হতে অন্য নোডের দূরত্ব (cost) ছাড়াও একটি অনুমেয় দূরত্ব(Heuristic cost) ব্যবহার করে।

যদি এখনো পর্যন্ত যা বলছি তা কঠিন লাগে তাহলে আসুন একটি বাস্তব উদাহরণ এ চলে যাই।

আমরা প্রথমে শুরু করছি একটি গ্রাফ দিয়ে। ধরে নেই আমাদের গ্রাফটি দেখতে এরকম:

Graph1

সহজ বাংলায় এখানে একটি ছোট গ্রাফ আছে যার নোডসংখ্যা ৫ টি এবং কোন নোড থেকে অন্যান্য নোড এ যাবার cost নোড গুলোর edge এ লেখা। যেমন S থেকে A  যাবার জন্যে Cost 1. A থেকে G তে যাবার Cost হচ্ছে ১২. অন্যান্য সকল গ্রাফ সার্চিং অ্যালগরিদম এর মতো শুধুমাত্র path cost এর উপর এটি নির্ভর করেনা। আপনার ঠিক এর পর যেটি দরকার হবে সেটি হচ্ছে একটি Heuristic Cost . এখন প্রশ্ন আসতেই পারে কিভাবে Heuristic Cost আমরা ঠিক করবো। এই ক্ষেত্রে আমরা আমাদের এক নোড থেকে অন্য নোডের Expected Cost বসিয়ে নিয়েছি। তবে আপনি চাইলে এই Heuristic Cost ও নির্ণয় করার পদ্ধতিগুলো পরীক্ষা করতে পারেন। আমরা সেগুলো পরবর্তী কোন টিউটোরিয়াল এ দেখবো।

আসুন ধরে নেই আমাদের Heuristic Cost Table এরকম:

Graph2

আমাদের শুরু করবার নোড হবে S এবং শেষ করবার নোড হবে G। আসুন দেখি এ* সার্চ কিভাবে সঠিক পথ টি খুঁজে বের করে। আমরা একটি priority queue ব্যবহার করবো এ ক্ষেত্রে। আপনি যদি Priority Queue কি না জেনে থাকেন, অনুগ্রহ করে জেনে নিন এখান থেকে।

মনে করি লিস্টটির নাম Closed List, এটির ব্যবহার ব্যাখ্যা করার থেকে দেখে নেয়াটাই বুদ্ধিমানের কাজ হবে। অাপাতত জেনে রাখুন এটি একটি লিস্ট। আমাদের শুরু করার নোড হচ্ছে S , আমরা যেতে চাই G তে। আসুন দেখি, আমরা কিভাবে সেটি করতে পারি। প্রথমে নেই S কে। S এর সাথে Attached Node হচ্ছে A এবং B। তাহলে S থেকে G তে যেতে হলে আগে আমাকে A অথবা B তে যেতে হবে। তার মানে হচ্ছে যে নোড টি থেকে আপনি শুরু করবেন তার সাথে সংযুক্ত সকল নোড কে আপনার আগে বিবেচনায় আনতে হবে অথবা node টি expand করতে হবে।

সবার শুরুতে S এর Total Cost হিসেব করি:

c(s) = g(s) + h(s)

এখানে g(s) হচ্ছে S এ আসার Cost. S এ আসতে আমার তেমন কোন খরচ হয়নি বিধায় আমি এটিকে ধরে নিচ্ছি শূন্য। এবং h(s) হচ্ছে S এর heuristic cost যেটা আমরা table থেকে দেখে পাচ্ছি 7. এখন আমাদের কাজ হচ্ছে S এর সাথে সংযুক্ত সকল নোড বিবেচনায় আনা, মানে S expand করা। S কে expand করলে আমরা পাই A এবং B ।

c(s) = 0 + 7

মনে করি শুরুতে আমরা A তে যাবো।

এখন S হতে A তে যাবার Cost নির্ণয় করার উপায় হচ্ছে S থেকে A তে যাবার Cost এবং A এর Heuristic Cost যোগ করা। মনে করি:

c(S-A) = ( g(s)+g(a) ) + h(a)

এখানে c(S-A) হচ্ছে S হতে A তে যাবার Total Cost. g(s) হচ্ছে s এ আসার Cost. এখানে যেটি শুন্য। কারণ, s থেকে আমরা শুরু করছি। A তে যাবার Cost হচ্ছে 1. A এর Heuristic Cost হচ্ছে 6. তাহলে সম্পূর্ণ Cost দাঁড়ায়:

c(S-A) = ( 0+ 1 ) + 6 =7

অনুরূপ ভাবে S হতে B যাবার পর Cost দাঁড়ায়

c(S-B) = ( 0+ 4 ) + 4 =8

কারণ, s এ আসতে 0 এবং B আসতে 4 এবং B এর heuristic cost হলো 4 . এখন আমাদের অবস্থা নিচের মতো:
(sav)Graph

খেয়াল করলে দেখবেন, এখানে closed_list নামে একটি queue আছে। আমরা যখনি কোন নোড পুরোপুরি expand করে ফেলবো তখনি সেটিকে এখানে নিয়ে নেবো, যাতে পরে এটিকে Expand না করা লাগে। তাই আমরা এখানে S এর সব attached node (A, B) ভিসিট করে ফেলেছি বলে S কে closed_list এ রেখে দিয়েছি। আর ডান পাশে যে Tree টি তৈরী হচ্ছে তাকে বলবো আমরা Search Tree.

এখন যেহেতু A এবং B ভিসিট করা শেষ, আমাদের পরবর্তী টার্গেট A অথবা B expand করা। A এবং B এর মধ্যে কোনটি আগে করবো? যার Total cost কম তারটি আগে। এখানে A এর Total Cost 7 যেখানে B তে আসার Total Cost হচ্ছে 8, তাই এটি আগে expand করবো। A হতে শুধু B,C,G তে যাওয়া যায়। তাই ৩ টি পথের ই Total Cost বের করতে হবে। তাই Total Cost হবে:

c(S-A-B) = ( g(s)+g(b)+g(c) ) + h(c)

c(S-A-B) = ( 0+1+2) +4 = 7

অনুরূপভাবে,

c(S-A-C) = (0+1+5) + 2 = 8

c(S-A-G) = (0+1+12) + 0 = 13

(sav)Graph3যেহেতু A নোডটি আমাদের expand করা শেষ সেহেতু আমি A কে closed_list এ পাঠিয়ৈ দিবো। এখন সার্চ ট্রি এর দিকে লক্ষ্য করুন। প্রশ্ন হচ্ছে কোনটি আপনি expand করবেন? ট্রি এর সকল Leaf Node গুলো খেয়াল করুন (যেগুলো এখনো expand হয়নি)। নোডগুলো হচ্ছে:

  1. s-a-b
  2. s-a-c
  3. s-a-g
  4. s-b

এখন এর মধ্যে সবচেয়ে কম Total Cost হচ্ছে s-a-b এর। এটি এখন expand করতে হবে।

s-a-b এর শেষ নোড b, তাহলে b expand করি। b থেকে শুধু c তে যাওয়া যায় ।

c(s-a-b-c) = (g(s) + g(a) + g(b) + g(c)) + h(c)

c(s-a-b-c) = (0+1+2+2) + 2 = 7

যেহেতু B নোডটি আমাদের expand করা শেষ সেহেতু আমি B কে closed_list এ পাঠিয়ৈ দিবো।

(sav)Graph4

এখন আমাদের Leaf Node (ট্রি এর তলার নোড গুলো যেগুলো এক্সপান্ড করা হয়নি) সেগুলো হচ্ছে

  1. s-a-b-c
  2. s-a-g
  3. s-a-c
  4. s-b

যেহেতু s-a-b-c এর Total Cost কম সেহেতু আমরা এটিই expand করবো, মানে এটির শেষ নোড c expand করবো। c থেকে শুধু g তে যাওয়া যায়। তাহলে s-a-b-c-g এর total cost হচ্ছে

c(s-a-b-c-g) = (g(s) + g(a) + g(b) + g(c) + g(g) ) + h(g)

c(s-a-b-c-g) = (0+1+2+2+3) + 0 = 8

আমরা C কেও closed_list এ ঢুকিয়ে দেবো কারণ, এটি expanded হয়ে গেছে।

(sav)Graph5

এখন খেয়াল করলে দেখবেন আমাদের expand করার মতো path এবং তাদের Total Cost হচ্ছে:

  1. s-a-b-c-g = 8
  2. s-a-c = 8
  3. s-a-g = 13
  4. s-b = 8

এখানে s-a-b-c-g এবং s-a-c এবং s-b এর Total cost এক ই। এখন কোনটি expand করবো?

এখন আমাদের সমস্যা সমাধান করার জন্যে খেয়াল করে দেখুন alphabetically dictionary sort এ s-a-b-c-g আগে আসে, এরপর আসে s-a-c এবং তার পরে s-b

তাহলে s-a-b-c-g expand করা উচিত। কিন্তু এটি g তে চলে এসেছে এবং এখানেই আমরা আসতে চেয়েছিলাম। তাই, এই s-a-b-c-g ই আমাদের খুঁজতে থাকা পথ।তার মানে হচ্ছে আপনার এ* সার্চ এ যদি এক্সপান্ড করতে যে নোডটি সিলেক্ট হবে সেটিই যদি গোল নোড হয়, আপনি আপনার পথ পেয়ে গেছেন।

এটি ই সবচেয়ে ভালো পথ কিনা সেটি নিয়ে কথা বলবো পরের টিউটোরিয়াল এ। সাথে থাকবে একটি স্যাম্পল উইন্ডোজ ফোন অ্যাপ।

হ্যাপী কোডিং!

Recording Audio in Windows Phone 8.1

First Words

This article points to a simple, fast way to record audio in Windows Phone 8.1. As the old Microphone class is no longer available, Windows Phone 8.1 came with new MediaCapture class to consolidate the media recording part for audio and video together. So, why waiting, let’s see how to do it!

Let’s get busy

I jotted a very simple GUI for this that has three simple buttons named “Capture Audio”, “Stop Capture” and “Play Capture”.  And it looks as follows:

CaptureAudio1

If you guys want to have a closer look at the XAML behind, peek a look:

<Page
    x:Class="CaptureSoundTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CaptureSoundTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <MediaElement x:Name="playbackElement1" ></MediaElement>
        <Button x:Name="CaptureButton" Content="Capture Audio" HorizontalAlignment="Center" Margin="0,184,0,0" VerticalAlignment="Top" Click="CaptureButton_Click" Width="145"/>
        <Button x:Name="StopCaptureButton" Content="Stop Capture" HorizontalAlignment="Center" Margin="0,284,0,0" VerticalAlignment="Top" Click="StopCaptureButton_Click" Width="145"/>
        <Button x:Name="PlayRecordButton" Content="Play Capture" HorizontalAlignment="Center" Margin="0,380,0,0" VerticalAlignment="Top" Click="PlayRecordButton_Click" Width="145"/>

    </Grid>
</Page>

It’s pretty basic, I didn’t do much here without keeping the buttons in place. There’s a MediaElement named playbackElement1 to play back the recorded video.

Now, it’s time to populate the button events here named CaptureButton_Click, StopCaptureButton_Click and PlayRecordButton_Click

Initializing and Capturing audio

To capture audio, first we need to initialize the recording. Before digging into that, let’s just initialize some variables that we might need on the journey.

private MediaCapture _mediaCaptureManager;
private StorageFile _recordStorageFile;
private bool _recording;
private bool _userRequestedRaw;
private bool _rawAudioSupported;

The MediaCapture class here is the one responsible here to capture audio and video both here. And StorageFile instance will help us store, locate and play the recorded media on our device.

So, let’s have a look how our recording initialization method looks like:

private async void InitializeAudioRecording()
{

   _mediaCaptureManager = new MediaCapture();
   var settings = new MediaCaptureInitializationSettings();
   settings.StreamingCaptureMode = StreamingCaptureMode.Audio;
   settings.MediaCategory = MediaCategory.Other;
   settings.AudioProcessing = (_rawAudioSupported &amp;&amp; _userRequestedRaw) ? AudioProcessing.Raw : AudioProcessing.Default;

   await _mediaCaptureManager.InitializeAsync(settings);

   Debug.WriteLine("Device initialised successfully");

   _mediaCaptureManager.RecordLimitationExceeded += new RecordLimitationExceededEventHandler(RecordLimitationExceeded);
    _mediaCaptureManager.Failed += new MediaCaptureFailedEventHandler(Failed);
}

So, the very first thing done here is the initialization of the MediaCapture class. Every media capture is associated with a MediaCaptureInitializationSettings instance. We’ve set the StreamingCaptureMode to Audio to make sure this is only audio recording rather than video. There were two bool variables declared before named _rawAudioSupported and _userRequestedRaw. Although I didn’t hook them up from GUI, you guys can defintiely try hooking them up from GUI and thus you can give the app a choice to record raw or pointing it to default audio processing.

The next thing to do is initializing the _mediaCaptureManager with the settings provided. I have included two event handlers for RecordingLimitExceeded and Failed. You guys can write your own handlers of course in these cases.

Now, usually you can put the InitializeAudioRecording method where your app initializes. I put it here on MainPage constructor.

Now, let’s capture audio, MediaCapture class made it really easy indeed.

private async void CaptureAudio()
{
   try
   {
     Debug.WriteLine("Starting record");
     String fileName = "record.m4a";

     _recordStorageFile = await KnownFolders.VideosLibrary.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);

     Debug.WriteLine("Create record file successfully");

     MediaEncodingProfile recordProfile = MediaEncodingProfile.CreateM4a(AudioEncodingQuality.Auto);
     await _mediaCaptureManager.StartRecordToStorageFileAsync(recordProfile, this._recordStorageFile);

     Debug.WriteLine("Start Record successful");

     _recording = true;
    }
    catch (Exception e)
    {
      Debug.WriteLine("Failed to capture audio");
    }
}

If you have a good look on the code you will see we declared a filename first. And then we created a file in our VideosLibrary using KnownFolders.VideosLibrary.CreateFileAsync that actually points to the media and video library of windows phone 8.1 with a given filename and we also gave a CreationCollisionOption.GenerateUniqueName that says it will create a unique name in case of collision. The next thing to do is creating a recording profile using MediaEncodingProfile class and you can get all possible recording profiles for videos and audios from here. I created a M4a audio profile using MediaEncodingProfile.CreateM4a(recordProfile, this._recordStorageFile) method.

All we have left to do is now start the recording, so  let’s go ahead and start the recording. And it’s easy as pie with _mediaCaptureManager.StartRecordToStorageFileAsync(recordProfile, this._recordStorageFile)

Stopping Recording

Stopping the recording is quiet easy too. All you have to do is call _mediaCaptureManager.StopRecordAsync()

private async void StopCapture()
{

     if (_recording)
     {
          Debug.WriteLine("Stopping recording");
          await _mediaCaptureManager.StopRecordAsync();
          Debug.WriteLine("Stop recording successful");
          _recording = false;
     }

}

Playing Recording

Playing a recording kind of consists of two tasks. First we have to open the recorded file and then play it. If you guys remember we used StorageFile _recordStorageFile to define our file that will hold the recording.

private async void PlayRecordedCapture()
{
     if (!_recording)
     {
         var stream = await _recordStorageFile.OpenAsync(FileAccessMode.Read);
         Debug.WriteLine(&quot;Recording file opened&quot;);
         playbackElement1.AutoPlay = true;
         playbackElement1.SetSource(stream, _recordStorageFile.FileType);
         playbackElement1.Play();
     }
}

So, let’s open up the file and assign the resultant stream to a source of a MediaElement on XAML. In this case that one is playBackElement1

 

Voila! You’re done, now you can play your recording. All you have to do now is assign these three methods to proper button events. For the full source please download the demo project above.

Windows Phone 8.1 for newbies: Episode 2 – Hello Xaml!

উইন্ডোজ ফোন সম্পূর্ণ নতুনদের জন্যে তৈরী করা সিরিজের দ্বিতীয় ভিডিও এটি। আজকের বিষয় Hello Xaml. আশা করি কেমন লাগছে জানাতে ভুলবেন না।

ইউটিউব প্লেলিস্টটি পাচ্ছেন এইখানে

A little bit of fun with face detection in Windows Phone 8

To start off

If anybody is actually looking for Face Detection Libraries for Windows Phone and haven’t tried this one, this is for them. It’s a neat library popping off facedetecionwp7 library by Julia Schwarz. And you can do pretty cool stuffs with it with pretty less hassle.

Let’s have a little fun

Let’s go ahead and get ourselves started with a Windows Phone 8 Project. Our job would be try this library and detect faces in a picture and have some fun with it, say overlay the face with the classic troll face with the laugh. 😛

Troll

Now, no matter what that sounds, let’s give it a shot. I’ve jotted down a very simple GUI to do this one. And it’s as following:

FaceDetection1

If you want to have a closer look at the XAML it will look the following:

<Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

       
        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="Face Detection in Windows Phone" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Button x:Name="CaptureImageButton" Content="Capture Image" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Top" Width="267" Click="CaptureImageButton_Click"/>
            <Image Name="facesPic" HorizontalAlignment="Center" Height="388" Margin="0,170,0,0" VerticalAlignment="Top" Width="427"/>
        </Grid>

        
    </Grid>

Now, you can definitely see that this is a very basic UI. We have a Button with a click event CaptureImageButton_Click and a Image named facesPic.

Now, before we get our hands dirty, let’s go ahead and add reference to a library we will need. We will need WritableBitmapEx from here. This lib is already available on Nuget too, so you can get it from there too.

After you added that in your project reference, you will need a bunch of libraries from FaceDetectionWP8 to make this things work. You can get the classes on there from the following link too.

After you download the .zip , unzip it and include all the classes inside in your project. I added them under a separate folder named FaceDetector.

Let’s move to our MainPage.xaml.cs

Now, the first thing to do is to pick a picture and the best thing to use for that is PhotoChooserTask . Let’s hook up the following snippet in CaptureImageButton_Click event.

private void CaptureImageButton_Click(object sender, RoutedEventArgs e)
        {
            PhotoChooserTask photo = new PhotoChooserTask();
            photo.Completed += new EventHandler&lt;PhotoResult&gt;(photoChooserTask_Completed);
            photo.ShowCamera = true;
            photo.Show();
        }

Now, the next thing to write is definitely photoChooserTask_Completed event handler. Let’s go ahead and write it. First thing to do would be get the chosen photo into a  WritableBitmap as we are going to do some changes on it.

if(e.TaskResult==TaskResult.OK)
{
    BitmapImage SourceBitmap = new BitmapImage();
    SourceBitmap.SetSource(e.ChosenPhoto);
    WriteableBitmap SourceWritableBitmap = new WriteableBitmap(SourceBitmap);

}

Now, the next thing we need to do is downsample the image a bit as most of the Windows Phone devices pack a pretty powerful camera and often the pictures are oversampled. I personally suggest you downsize the image a bit too. I din’t do it in this demo but if you want a faster performance, you really should try that too. I added the following code segment inside the if block.

byte[] downsampledImage = new byte[SourceWritableBitmap.PixelWidth / _downsampleFactor * SourceWritableBitmap.PixelHeight / _downsampleFactor];

Utils.DownSample(SourceWritableBitmap.ToByteArray(), SourceWritableBitmap.PixelWidth, SourceWritableBitmap.PixelHeight, ref downsampledImage, _downsampleFactor);

SourceWritableBitmap = SourceWritableBitmap.FromByteArray(downsampledImage);

The code segment is pretty straight forward here now. The Utils class here is from the FaceDetectionWP8 library. The first argument for Utils.DownSample used here is a Byte Array of the SourceWritableBitmap and it used the WritableBitmapEx we added here before. The second one is the width of the source bitmap and the third one is the height. The last argument passed here is the downsample factor. This was defined as the following in the MainPage class.

int _downsampleFactor = 2;

And then the SourceWritableBitmap is reinitiazed with a downsampled version of it’s own.

The next thing to do would be getting the faces detected of course. 😀 So, why wait? I added the following sinppet for that.

List<FaceDetector.Rectangle> faces = new List<FaceDetector.Rectangle>();
faces = _detector.getFaces(SourceWritableBitmap, 2f, 1.25f, 0.1f, 1, false, true);

I used the defaults here except the last argument that determines whether it should detect multiple faces and I kept it true.  You can have fun with the other params if you want to tweak your haar cascade detection parameters here.

here comes the fun part, now we are going to replace the face/faces in the picture with the troll laugh picture. :P. We can see it returns the faces as a List<FaceDetector.Rectangle>. All we have to do now is paint the Troll laugh in the rectangles returned by the method. fun, huh?

Now, before replacing the Source Image with the Troll Laugh, we need to load it in another WritableBitmap so we can blend the both of them.

StreamResourceInfo MaskImageSri = Application.GetResourceStream(new Uri("Images/Troll.png", UriKind.Relative));
BitmapImage MaskImageBitmap = new BitmapImage();
MaskImageBitmap.SetSource(MaskImageSri.Stream);

WriteableBitmap MaskWritableBitmap = new WriteableBitmap(MaskImageBitmap);

As we got our Troll.png, why don’t we paste it on the source bitmap?

foreach (var r in faces)
{
   int x = Convert.ToInt32(r.X);
   int y = Convert.ToInt32(r.Y);
   int width = Convert.ToInt32(r.Width);
   int height = Convert.ToInt32(r.Height);                    

   System.Windows.Rect destRect = new Rect(x, y, width, height);
   System.Windows.Rect srcRect = new Rect(0, 0, MaskWritableBitmap.PixelWidth, MaskWritableBitmap.PixelHeight);

   SourceWritableBitmap.Blit(destRect, MaskWritableBitmap, srcRect);

}
   SourceWritableBitmap.Invalidate();
   facesPic.Source = SourceWritableBitmap;

Now, this is pretty straight forward too. All we need is we iterated over the faces and we created to separate rect structs. One is from the MaskWritableBitmap so we can get the rect of the portion of the image we are pasting, in this case, the full one and the destination rect is the face rectangle on the source image we are pasting this troll laugh on.

The next thing to do is invoke Blit() method as this one is responsible to blend these two WritableBitmaps. It comes with the WritableBitmapEx library we added before. The first parameter is the destination rectangle where the source rectangle will be pasted. In this case the face rectangle that will be replaced by the troll laughter image. The second parameter would be the WritableBitmap where the rect that would be posted in the source is found. Here this one is the Troll Image and the last one is the rect in the Troll Image that would be transferred to the main bitmap.

We called it on SourceWritableBitmap as we want to paste the troll Laugh on it. And when all is said and done we set facesPic source to the SourceWritableBitmap.

Now all we have to do is build and test the app. And the result is as following:

FaceDetectionScreenshot

So, what are waiting for? Test the demo project here of the article and have fun!

Windows Phone For Newbies: Episode 1 – Introduction

আপনি যদি আগে কখনোই উইন্ডোজ ফোনে কাজ না করে থাকেন তাহলে এই ভিডিও সিরিজ টি আপনার জন্যে। এটি উইন্ডোজ ফোন ৮.১ এর একটি বাংলা টিউটোরিয়াল সিরিজ যা আপনাকে একদম শুরু থেকে উইন্ডোজ ফোনে কাজ করার জন্য সম্যক সকল কিছু জানিয়ে দেবে।

এটি সিরিজটির প্রথম পর্ব

ইউটিউব প্লেলিস্টটি পাচ্ছেন এইখানে

প্রোজেক্ট সোর্স কোড পাচ্ছেন এইখানে

Making a quick rating user control for Windows Phone 8.1

First Words

Usually when someone is working on Windows Phone 8.1 and usually if he’s the guy who just came from Windows Phone 8 development, the first thing he misses is all the toolkits lying around like the Windows Phone Toolkit or Coding4Fun Toolkits. Thus, missing a rating control is not new. So, let’s get our hands dirty and make a little 5 starred rating control fast enough to solve our problem at least to a minimum extent.

Design First!

Okay, to do this thing fast, we might need to make at least a little bit of groundwork in design, I’m going to use Microsoft Expression Design for it. You guys can get the free version from here. It’s pretty lightweight and we can practically export stuff straight to Blend for Visual Studio!

So, let’s go over Microsoft Expression Blend and create a new document. Take a size to your preference as you need it. Let’s draw some stars! To get started, look on the left toolbar and select Polygons.

1

After you select polygons, drag your mouse pointer in the artboard to draw anything that pops off. Now, it might be any kind of polygon, starting from a triangle, like the following came up with too much of points.

2

To rectify this, we need to make sure it has 5 points and an inner depth above 40% and close to 50% so it looks like a star, you can modify the existing one you made or set the proper settings and make a new one. To do that, look on the right on Edit Polygon dialog and change the points to 5 and move the innder depth to 47%. If you want to create a new one you will see the dialog name is Create Polygon. You can go for anything in between 45% tp 50%, I used 47% in this case.

3 4

 

 

Now, with the proper settings set with the polygon give it a yellowish shade and no borders please. And copy the stars and set them side by side so you can have 5 stars in a line that resembles a regular rating control. So, in the artboard it might look pretty close to the one following:

5

Now, what we want to do is put these together on a gradient so it resembles more to the rating control. But before we go do that, we need to make the stars act as a compound path together. So, lets go ahead and select all of them and select Object -> Compound Path -> Make so all the stars can work as a compound path.

6

Now, it’s time to put a gradient over it. Select a yellow to white gradient and put it on your rating control from left to right. Now, there comes a trick, at first you will see the color melted down in the middle, in a rating control we need a clear difference of color to make sure that it looks like one.

7

Now, click on the gradient bar in the middle to put a gradient stop in there.

8

Now, drag the midpoints (the dots over the gradient bar) and put them together to make the color difference more prominent.

9

Now, if we move the Gradient Stop now, we will see the color changes are more prominent and the starts look a lot like rating control now.

10

Now let’s go over Visual Studio and create a Windows Phone 8.1 Project. Let’s put a Right Click on the solution name and add a user control.

11

12

Now, lets select the user control and open it on blend. Let’s select all the stars, copy it and just paste it on the grid of the user control. To your surprise, this thing will just get copied to blend just fine. And let’s make the height of the user control to 40 and the width to 200 just to get the user control to appropriate proportion. I copied a set of stars and put the background to a very light gray color and put it behind the ones we copied at first so it looks a bit more prominent even in a white background.

13

Now, the xaml for the usercontrol will look somewhat like the following:

<UserControl
    x:Class="RatingControlTest.usercontrol"
    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:DesignHeight="40"
    d:DesignWidth="200">

    <Grid>
        <Path Stretch="Fill"
              Data="M -1346.6,-259.247L -1358.76,-305.451L -1321.61,-335.489L -1369.31,-338.197L -1386.39,-382.816L -1403.71,-338.285L -1451.43,-335.823L -1414.43,-305.594L -1426.83,-259.454L -1386.65,-285.302L -1346.6,-259.247 Z M -1067.9,-259.247L -1080.07,-305.451L -1042.91,-335.489L -1090.61,-338.197L -1107.7,-382.816L -1125.01,-338.285L -1172.73,-335.823L -1135.73,-305.594L -1148.13,-259.453L -1107.95,-285.301L -1067.9,-259.247 Z M -1207.25,-259.247L -1219.41,-305.451L -1182.26,-335.489L -1229.96,-338.197L -1247.05,-382.816L -1264.36,-338.285L -1312.08,-335.823L -1275.08,-305.594L -1287.48,-259.453L -1247.3,-285.301L -1207.25,-259.247 Z M -928.552,-259.247L -940.718,-305.451L -903.562,-335.489L -951.264,-338.197L -968.35,-382.816L -985.666,-338.285L -1033.38,-335.823L -996.382,-305.594L -1008.79,-259.453L -968.602,-285.301L -928.552,-259.247 Z M -789.204,-259.247L -801.369,-305.451L -764.214,-335.489L -811.916,-338.197L -829.002,-382.816L -846.318,-338.285L -894.034,-335.823L -857.033,-305.594L -869.437,-259.453L -829.254,-285.301L -789.204,-259.247 Z "  
              UseLayoutRounding="False"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Height="Auto" Width="Auto" Fill="#FFDEDEDE"/>
        <Path Stretch="Fill"
              Data="M -1346.6,-259.247L -1358.76,-305.451L -1321.61,-335.489L -1369.31,-338.197L -1386.39,-382.816L -1403.71,-338.285L -1451.43,-335.823L -1414.43,-305.594L -1426.83,-259.454L -1386.65,-285.302L -1346.6,-259.247 Z M -1067.9,-259.247L -1080.07,-305.451L -1042.91,-335.489L -1090.61,-338.197L -1107.7,-382.816L -1125.01,-338.285L -1172.73,-335.823L -1135.73,-305.594L -1148.13,-259.453L -1107.95,-285.301L -1067.9,-259.247 Z M -1207.25,-259.247L -1219.41,-305.451L -1182.26,-335.489L -1229.96,-338.197L -1247.05,-382.816L -1264.36,-338.285L -1312.08,-335.823L -1275.08,-305.594L -1287.48,-259.453L -1247.3,-285.301L -1207.25,-259.247 Z M -928.552,-259.247L -940.718,-305.451L -903.562,-335.489L -951.264,-338.197L -968.35,-382.816L -985.666,-338.285L -1033.38,-335.823L -996.382,-305.594L -1008.79,-259.453L -968.602,-285.301L -928.552,-259.247 Z M -789.204,-259.247L -801.369,-305.451L -764.214,-335.489L -811.916,-338.197L -829.002,-382.816L -846.318,-338.285L -894.034,-335.823L -857.033,-305.594L -869.437,-259.453L -829.254,-285.301L -789.204,-259.247 Z "  
              UseLayoutRounding="False"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Height="Auto" Width="Auto">
            <Path.Fill>
                <LinearGradientBrush StartPoint="3.55262e-007,0.500002" EndPoint="1,0.500001">
                    <GradientStop Color="#FFFFCC00" Offset="0.6"/>
                    <GradientStop Color="#06FCFCFC" Offset="0.6"/>
                </LinearGradientBrush>
            </Path.Fill>
        </Path>

    </Grid>
</UserControl>

Code Comes Along

Now if we remember stuff clearly, when we moved the gradient stop in blend it looked like the rating bar value is changing. We just need to emulate that in code, that’s it. So, all we need to is change the Offset of <GradientStop> ‘s in LinearGradientBrush entry inside <Path.Fill>. So, we have to databind the offset from backend so we can access it from the usercontrol. And please remember this have to be 0.0 to 1 of course as thats the range for the offset value.

I renamed my user control to RatingControl and let’s move back to the code backend of RatingControl.xaml

public partial class RatingControl : UserControl
    {
        public RatingControl()
        {
            this.InitializeComponent();
        }

        DependencyProperty RateValueProperty = DependencyProperty.Register("RateValue", typeof(double), typeof(RatingControl), new PropertyMetadata(0.1, UpdateValue));

        private static void UpdateValue(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RatingControl control = d as RatingControl;
            control.Value = (double)e.NewValue;
        }

        private double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        private static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(RatingControl), new PropertyMetadata(0.1));

        public double RateValue
        {
            get
            {
                return (double)GetValue(RateValueProperty);
            }
            set
            {
                SetValue(RateValueProperty, value);
            }
        }

    }

Now, our job was to hook up the Value provided from backend. Now I used two DependencyProperty here instead of one because we are going to attach the value in the xaml using a element binding. The first DependencyProperty RateValueProperty has a PropertyMetadata of 0.1 and a function is attached to update the value in the xaml control (update the offset from the xaml).

And Value is the actual DependencyProperty Attached to the control and as it’s private it’s accessible only from inside. So we are exposing it using the RateValueProperty and update it with the Value Dependency Property. You can only use Value and expose it if you want.

Now all we have to do is hook it up in the xaml:

Let’s add a name to the Rating Control. Lets just add x:Name=”UserControl” in the UserControl Tag. And let’s tag the GradientStop property Offset on the ElementName “UserControl”. So, let’s modify the GradientStop tags as following:

<Path.Fill>
     <LinearGradientBrush StartPoint="3.55262e-007,0.500002" EndPoint="1,0.500001">
          <GradientStop Color="#FFFFCC00" Offset="{Binding Value, ElementName=UserControl}"/>
          <GradientStop Color="#06FCFCFC" Offset="{Binding Value, ElementName=UserControl}"/>
      </LinearGradientBrush>
</Path.Fill>

And voila! We are done!

Using the control

Using the control is pretty easy, add xmlns:local=”using:RatingControlTest” in the page tag and use it just like the following:

<Page
    x:Class="RatingControlTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:RatingControlTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <local:RatingControl Width="200" Height="40" RateValue="0.5"></local:RatingControl>
    </Grid>
</Page>

And it will look like the following:

14

Demo Project:

The demo project is here so you can test it yourself. Hope this helps! 😉