diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..5aec15cdd7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,37 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+# Declare files that will always have CRLF line endings on checkout.
+*.appxmanifest text eol=crlf
+*.c text eol=crlf
+*.cpp text eol=crlf
+*.cs text eol=crlf
+*.csproj text eol=crlf
+*.css text eol=crlf
+*.def text eol=crlf
+*.filters text eol=crlf
+*.h text eol=crlf
+*.htm text eol=crlf
+*.html text eol=crlf
+*.idl text eol=crlf
+*.inf text eol=crlf
+*.inx text eol=crlf
+*.js text eol=crlf
+*.jsproj text eol=crlf
+*.rc text eol=crlf
+*.rgs text eol=crlf
+*.sln text eol=crlf
+*.vcxproj text eol=crlf
+*.xaml text eol=crlf
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+*.cs diff=csharp
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..677dfa66c3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,201 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+[Gg]enerated Files/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studo 2015 cache/options directory
+.vs/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding addin-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+*.[Cc]ache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Custom ignores
+gallery.xml
+project.lock.json
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..701b833021
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Microsoft Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..37876aaebb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,457 @@
+# Universal Windows app samples
+This repo contains the samples that demonstrate the API usage patterns for the Universal Windows Platform (UWP) in the Windows Software Development Kit (SDK) for Windows 10. These code samples were created with the Universal Windows templates available in Visual Studio, and are designed to run on desktop, mobile, and future devices that support the Universal Windows Platform.
+
+## Universal Windows Platform development
+These samples require Visual Studio 2015 and the Windows Software Development Kit (SDK) for Windows 10 to build, test, and deploy your Universal Windows apps.
+
+ [Get a free copy of Visual Studio 2015 Community Edition with support for building Universal Windows apps](http://go.microsoft.com/fwlink/?LinkID=280676)
+
+Additionally, to stay on top of the latest updates to Windows and the development tools, become a Windows Insider by joining the Windows Insider Program.
+
+ [Become a Windows Insider](https://insider.windows.com/)
+
+## Using the samples
+The easiest way to use these samples without using Git is to download the zip file containing the current version (using the link below or by clicking the "Download ZIP" button on the repo page). You can then unzip the samples and use them in Visual Studio 2015.
+
+ [Download the samples ZIP](../../archive/master.zip)
+
+The samples use Linked files in Visual Studio to reduce duplication of common files, including sample template files and image assets. These common files are stored in the SharedContent folder at the root of the repository and referred to in the project files using links.
+
+For more info about the programming models, platforms, languages, and APIs demonstrated in these samples, please refer to the guidance, tutorials, and reference topics provided in the Windows 10 documentation available in the [Windows Developer Center](https://dev.windows.com). These samples are provided as-is in order to indicate or demonstrate the functionality of the programming models and feature APIs for Windows.
+
+## Contributions
+These samples are direct from the feature teams and we welcome your input on issues and suggestions for new samples. At this time we are not accepting new samples from the public, but check back here as we evolve our contribution model.
+
+## Samples by category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/README.md b/Samples/Accelerometer/README.md
new file mode 100644
index 0000000000..4c5b435a4e
--- /dev/null
+++ b/Samples/Accelerometer/README.md
@@ -0,0 +1,72 @@
+
+
+# Accelerometer sample
+
+This sample shows how to use the [**Accelerometer**](http://msdn.microsoft.com/library/windows/apps/br225687) API.
+
+This sample allows the user to view the acceleration forces along the X-, Y-, and Z-axes for a 3-axis accelerometer. You can choose one of four scenarios:
+
+- Accelerometer data events
+- Accelerometer shake events
+- Poll accelerometer readings
+- Accelerometer orientation changed
+- Accelerometer data events batching
+
+### Acclerometer Data Events
+
+When you choose the **Enable** button for the **Data Events** option, the app begins streaming accelerometer readings in real time.
+
+### Accelerometer Shake Events
+
+When you choose the **Enable** button for the **Shake Events** option, the app displays the cumulative number of shake events each time an event occurs. (The app first increments the event count and then renders the most recent value.)
+
+### Poll Accelerometer Readings
+
+When you choose the **Enable** button for the **Polling** option, the app will retrieve the sensor readings at a fixed interval.
+
+### Accelerometer Orientation Changed
+
+When you choose the **Enable** button for the **OrientationChange** option, the app will display both raw sensor readings, as well as sensor readings that align with the current display orientation.
+
+### Accelerometer data events batching**
+
+When you choose the **Enable** button for the **Data Events** option, the app begins streaming accelerometer readings. The readings may be delivered in batches if the device supports data batching.
+
+## Related topics
+
+[**Accelerometer.GetCurrentReading method**](http://msdn.microsoft.com/library/windows/apps/br225699)
+
+[**Accelerometer.ReadingChanged event handler**](http://msdn.microsoft.com/library/windows/apps/br225702)
+
+[Quickstart: Responding to user movement with the accelerometer](http://msdn.microsoft.com/library/windows/apps/hh465265)
+
+[Windows.Devices.Sensors namespace](http://go.microsoft.com/fwlink/p/?linkid=241981)
+
+## System requirements
+
+**Client:** Windows 10
+
+**Server:** Windows Server 2016 Technical Preview
+
+**Phone:** Windows 10
+
+## Build the sample
+
+1. Start Microsoft Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C++ or C\#. Double-click the Visual Studio 2015 Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+### Deploying the sample
+
+- Select Build > Deploy Solution.
+
+### Deploying and running the sample
+
+- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
+
diff --git a/Samples/Accelerometer/cpp/Accelerometer.sln b/Samples/Accelerometer/cpp/Accelerometer.sln
new file mode 100644
index 0000000000..10f2a8c0a7
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Accelerometer.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22418.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Accelerometer", "Accelerometer.vcxproj", "{F710B9FD-4E6B-42D7-A99A-6D48888D48B0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|ARM = Release|ARM
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.ActiveCfg = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.Build.0 = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.Deploy.0 = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.Build.0 = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.Deploy.0 = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.ActiveCfg = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.Build.0 = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.Deploy.0 = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.ActiveCfg = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.Build.0 = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.Deploy.0 = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.ActiveCfg = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.Build.0 = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.Deploy.0 = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.ActiveCfg = Release|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.Build.0 = Release|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.Deploy.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/Accelerometer/cpp/Accelerometer.vcxproj b/Samples/Accelerometer/cpp/Accelerometer.vcxproj
new file mode 100644
index 0000000000..06afcf347e
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Accelerometer.vcxproj
@@ -0,0 +1,243 @@
+
+
+
+ {f710b9fd-4e6b-42d7-a99a-6d48888d48b0}
+ SDKTemplate
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.10240.0
+ 10.0.10240.0
+ true
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+
+ Scenario1_DataEvents.xaml
+
+
+ Scenario2_ShakeEvents.xaml
+
+
+ Scenario3_Polling.xaml
+
+
+ Scenario4_OrientationChanged.xaml
+
+
+ Scenario5_DataEventsBatching.xaml
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ Designer
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+ Scenario1_DataEvents.xaml
+
+
+ Scenario2_ShakeEvents.xaml
+
+
+ Scenario3_Polling.xaml
+
+
+ Scenario4_OrientationChanged.xaml
+
+
+ Scenario5_DataEventsBatching.xaml
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smalltile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squaretile-sdk.png
+
+
+ Assets\storelogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cpp/Accelerometer.vcxproj.filters b/Samples/Accelerometer/cpp/Accelerometer.vcxproj.filters
new file mode 100644
index 0000000000..dbb5bd5576
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Accelerometer.vcxproj.filters
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Styles
+
+
+
+
+ {3d69c7fe-172e-4737-a906-6b0e1b47f307}
+
+
+ {d6ad62a9-d6a8-4fe4-954b-07e844f1033d}
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cpp/Package.appxmanifest b/Samples/Accelerometer/cpp/Package.appxmanifest
new file mode 100644
index 0000000000..7302b04421
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Package.appxmanifest
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ AccelerometerCPP
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cpp/SampleConfiguration.cpp b/Samples/Accelerometer/cpp/SampleConfiguration.cpp
new file mode 100644
index 0000000000..ee6898a5d7
--- /dev/null
+++ b/Samples/Accelerometer/cpp/SampleConfiguration.cpp
@@ -0,0 +1,25 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+#include "SampleConfiguration.h"
+
+using namespace SDKTemplate;
+
+Platform::Array^ MainPage::scenariosInner = ref new Platform::Array
+{
+ { "Data Events", "SDKTemplate.Scenario1_DataEvents" },
+ { "Shake Events", "SDKTemplate.Scenario2_ShakeEvents" },
+ { "Polling", "SDKTemplate.Scenario3_Polling" },
+ { "OrientationChanged", "SDKTemplate.Scenario4_OrientationChanged" },
+ { "Data Events Batching", "SDKTemplate.Scenario5_DataEventsBatching" }
+};
diff --git a/Samples/Accelerometer/cpp/SampleConfiguration.h b/Samples/Accelerometer/cpp/SampleConfiguration.h
new file mode 100644
index 0000000000..d5054996a4
--- /dev/null
+++ b/Samples/Accelerometer/cpp/SampleConfiguration.h
@@ -0,0 +1,47 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace SDKTemplate
+{
+ value struct Scenario;
+
+ partial ref class MainPage
+ {
+ internal:
+ static property Platform::String^ FEATURE_NAME
+ {
+ Platform::String^ get()
+ {
+ return "Accelerometer";
+ }
+ }
+
+ static property Platform::Array^ scenarios
+ {
+ Platform::Array^ get()
+ {
+ return scenariosInner;
+ }
+ }
+
+ private:
+ static Platform::Array^ scenariosInner;
+ };
+
+ public value struct Scenario
+ {
+ Platform::String^ Title;
+ Platform::String^ ClassName;
+ };
+}
diff --git a/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml
new file mode 100644
index 0000000000..483c7c04fc
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.cpp b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.cpp
new file mode 100644
index 0000000000..e5b0dcd43c
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.cpp
@@ -0,0 +1,156 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario1_DataEvents.xaml.cpp
+// Implementation of the Scenario1_DataEvents class
+//
+
+#include "pch.h"
+#include "Scenario1_DataEvents.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Core;
+using namespace Platform;
+
+Scenario1_DataEvents::Scenario1_DataEvents() : rootPage(MainPage::Current), desiredReportInterval(0)
+{
+ InitializeComponent();
+
+ accelerometer = Accelerometer::GetDefault();
+ if (accelerometer != nullptr)
+ {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint32 minReportInterval = accelerometer->MinimumReportInterval;
+ desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario1_DataEvents::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario1_DataEvents::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (e->NavigationMode == NavigationMode::Forward && e->Uri == nullptr)
+ {
+ return;
+ }
+
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->ReadingChanged::remove(readingToken);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+ }
+}
+
+///
+/// This is the event handler for VisibilityChanged events. You would register for these notifications
+/// if handling sensor data when the app is not visible could cause unintended actions in the app.
+///
+///
+///
+/// Event data that can be examined for the current visibility state.
+///
+void Scenario1_DataEvents::VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
+{
+ // The app should watch for VisibilityChanged events to disable and re-enable sensor input as appropriate
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ if (e->Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ readingToken = accelerometer->ReadingChanged::add(ref new TypedEventHandler(this, &Scenario1_DataEvents::ReadingChanged));
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ accelerometer->ReadingChanged::remove(readingToken);
+ }
+ }
+}
+
+void Scenario1_DataEvents::ReadingChanged(Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ e)
+{
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this, e]()
+ {
+ AccelerometerReading^ reading = e->Reading;
+
+ ScenarioOutput_X->Text = reading->AccelerationX.ToString();
+ ScenarioOutput_Y->Text = reading->AccelerationY.ToString();
+ ScenarioOutput_Z->Text = reading->AccelerationZ.ToString();
+ },
+ CallbackContext::Any
+ )
+ );
+}
+
+void Scenario1_DataEvents::ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (accelerometer != nullptr)
+ {
+ // Establish the report interval
+ accelerometer->ReportInterval = desiredReportInterval;
+
+ visibilityToken = Window::Current->VisibilityChanged::add(ref new WindowVisibilityChangedEventHandler(this, &Scenario1_DataEvents::VisibilityChanged));
+ readingToken = accelerometer->ReadingChanged::add(ref new TypedEventHandler(this, &Scenario1_DataEvents::ReadingChanged));
+
+ ScenarioEnableButton->IsEnabled = false;
+ ScenarioDisableButton->IsEnabled = true;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+void Scenario1_DataEvents::ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->ReadingChanged::remove(readingToken);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
diff --git a/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.h b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.h
new file mode 100644
index 0000000000..20e0937f78
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario1_DataEvents.xaml.h
@@ -0,0 +1,50 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario1_DataEvents.xaml.h
+// Declaration of the Scenario1_DataEvents class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario1_DataEvents.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario1_DataEvents sealed
+ {
+ public:
+ Scenario1_DataEvents();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::Devices::Sensors::Accelerometer^ accelerometer;
+ Windows::Foundation::EventRegistrationToken visibilityToken;
+ Windows::Foundation::EventRegistrationToken readingToken;
+ uint32 desiredReportInterval;
+
+ void VisibilityChanged(Platform::Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
+ void ReadingChanged(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ e);
+ void ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml
new file mode 100644
index 0000000000..89667077fc
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.cpp b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.cpp
new file mode 100644
index 0000000000..1179ef1001
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.cpp
@@ -0,0 +1,138 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario2_ShakeEvents.xaml.cpp
+// Implementation of the Scenario2_ShakeEvents class
+//
+
+#include "pch.h"
+#include "Scenario2_ShakeEvents.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Core;
+using namespace Platform;
+
+Scenario2_ShakeEvents::Scenario2_ShakeEvents() : rootPage(MainPage::Current), shakeCounter(0)
+{
+ InitializeComponent();
+
+ accelerometer = Accelerometer::GetDefault();
+ if (accelerometer == nullptr)
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario2_ShakeEvents::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario2_ShakeEvents::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (e->NavigationMode == NavigationMode::Forward && e->Uri == nullptr)
+ {
+ return;
+ }
+
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->Shaken::remove(shakenToken);
+ }
+}
+
+///
+/// This is the event handler for VisibilityChanged events. You would register for these notifications
+/// if handling sensor data when the app is not visible could cause unintended actions in the app.
+///
+///
+///
+/// Event data that can be examined for the current visibility state.
+///
+void Scenario2_ShakeEvents::VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
+{
+ // The app should watch for VisibilityChanged events to disable and re-enable sensor input as appropriate
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ if (e->Visible)
+ {
+ // Re-enable sensor input
+ shakenToken = accelerometer->Shaken::add(ref new TypedEventHandler(this, &Scenario2_ShakeEvents::Shaken));
+ }
+ else
+ {
+ // Disable sensor input
+ accelerometer->Shaken::remove(shakenToken);
+ }
+ }
+}
+
+void Scenario2_ShakeEvents::Shaken(Accelerometer^ sender, AccelerometerShakenEventArgs^ e)
+{
+ shakeCounter++;
+
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this]()
+ {
+ ScenarioOutputText->Text = shakeCounter.ToString();
+ },
+ CallbackContext::Any
+ )
+ );
+}
+
+void Scenario2_ShakeEvents::ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (accelerometer != nullptr)
+ {
+ visibilityToken = Window::Current->VisibilityChanged::add(ref new WindowVisibilityChangedEventHandler(this, &Scenario2_ShakeEvents::VisibilityChanged));
+ shakenToken = accelerometer->Shaken::add(ref new TypedEventHandler(this, &Scenario2_ShakeEvents::Shaken));
+
+ ScenarioEnableButton->IsEnabled = false;
+ ScenarioDisableButton->IsEnabled = true;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+void Scenario2_ShakeEvents::ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->Shaken::remove(shakenToken);
+
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
diff --git a/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.h b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.h
new file mode 100644
index 0000000000..2b26072dc5
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario2_ShakeEvents.xaml.h
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario2_ShakeEvents.xaml.h
+// Declaration of the Scenario2_ShakeEvents class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario2_ShakeEvents.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario2_ShakeEvents sealed
+ {
+ public:
+ Scenario2_ShakeEvents();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::UI::Core::CoreDispatcher^ dispatcher;
+ Windows::Devices::Sensors::Accelerometer^ accelerometer;
+ Windows::Foundation::EventRegistrationToken visibilityToken;
+ Windows::Foundation::EventRegistrationToken shakenToken;
+ uint16 shakeCounter;
+
+ void VisibilityChanged(Platform::Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
+ void Shaken(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerShakenEventArgs^ e);
+ void ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/Accelerometer/cpp/Scenario3_Polling.xaml b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml
new file mode 100644
index 0000000000..d34432a35b
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.cpp b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.cpp
new file mode 100644
index 0000000000..bdc79179cc
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.cpp
@@ -0,0 +1,157 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario3_Polling.xaml.cpp
+// Implementation of the Scenario3_Polling class
+//
+
+#include "pch.h"
+#include "Scenario3_Polling.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Core;
+using namespace Platform;
+
+Scenario3_Polling::Scenario3_Polling() : rootPage(MainPage::Current), desiredReportInterval(0)
+{
+ InitializeComponent();
+
+ accelerometer = Accelerometer::GetDefault();
+ if (accelerometer != nullptr)
+ {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint32 minReportInterval = accelerometer->MinimumReportInterval;
+ desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+
+ // Set up a DispatchTimer
+ TimeSpan span;
+ span.Duration = static_cast(desiredReportInterval) * 10000; // convert to 100ns ticks
+ dispatcherTimer = ref new DispatcherTimer();
+ dispatcherTimer->Interval = span;
+ dispatcherTimer->Tick += ref new Windows::Foundation::EventHandler(this, &Scenario3_Polling::DisplayCurrentReading);
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario3_Polling::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario3_Polling::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (e->NavigationMode == NavigationMode::Forward && e->Uri == nullptr)
+ {
+ return;
+ }
+
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ dispatcherTimer->Stop();
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+ }
+}
+
+///
+/// This is the event handler for VisibilityChanged events. You would register for these notifications
+/// if handling sensor data when the app is not visible could cause unintended actions in the app.
+///
+///
+///
+/// Event data that can be examined for the current visibility state.
+///
+void Scenario3_Polling::VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
+{
+ // The app should watch for VisibilityChanged events to disable and re-enable sensor input as appropriate
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ if (e->Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ dispatcherTimer->Start();
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ dispatcherTimer->Stop();
+ }
+ }
+}
+
+void Scenario3_Polling::DisplayCurrentReading(Object^ sender, Object^ e)
+{
+ AccelerometerReading^ reading = accelerometer->GetCurrentReading();
+ if (reading != nullptr)
+ {
+ ScenarioOutput_X->Text = reading->AccelerationX.ToString();
+ ScenarioOutput_Y->Text = reading->AccelerationY.ToString();
+ ScenarioOutput_Z->Text = reading->AccelerationZ.ToString();
+ }
+}
+
+void Scenario3_Polling::ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (accelerometer != nullptr)
+ {
+ visibilityToken = Window::Current->VisibilityChanged::add(ref new WindowVisibilityChangedEventHandler(this, &Scenario3_Polling::VisibilityChanged));
+
+ // Set the report interval to enable the sensor for polling
+ accelerometer->ReportInterval = desiredReportInterval;
+
+ dispatcherTimer->Start();
+
+ ScenarioEnableButton->IsEnabled = false;
+ ScenarioDisableButton->IsEnabled = true;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+void Scenario3_Polling::ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+
+ dispatcherTimer->Stop();
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
diff --git a/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.h b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.h
new file mode 100644
index 0000000000..3ddf15ed74
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario3_Polling.xaml.h
@@ -0,0 +1,50 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//
+// Scenario3_Polling.xaml.h
+// Declaration of the Scenario3_Polling class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario3_Polling.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario3_Polling sealed
+ {
+ public:
+ Scenario3_Polling();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::UI::Core::CoreDispatcher^ dispatcher;
+ Windows::Devices::Sensors::Accelerometer^ accelerometer;
+ Windows::Foundation::EventRegistrationToken visibilityToken;
+ uint32 desiredReportInterval;
+ Windows::UI::Xaml::DispatcherTimer^ dispatcherTimer;
+
+ void VisibilityChanged(Platform::Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
+ void DisplayCurrentReading(Platform::Object^ sender, Platform::Object^ e);
+ void ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml
new file mode 100644
index 0000000000..84cdcf7fc2
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.cpp b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.cpp
new file mode 100644
index 0000000000..df7bbcb723
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.cpp
@@ -0,0 +1,246 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario4_OrientationChanged.xaml.cpp
+// Implementation of the Scenario4_OrientationChanged class
+//
+
+#include "pch.h"
+#include "Scenario4_OrientationChanged.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Core;
+using namespace Platform;
+using namespace Windows::Graphics::Display;
+
+Scenario4_OrientationChanged::Scenario4_OrientationChanged() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+
+ // Get two instances of the accelerometer:
+ // One that returns the raw accelerometer data
+ accelerometerOriginal = Accelerometer::GetDefault();
+ // Other on which the 'ReadingTransform' is updated so that data returned aligns with the request transformation.
+ accelerometerReadingTransform = Accelerometer::GetDefault();
+
+ if (nullptr == accelerometerOriginal || nullptr == accelerometerReadingTransform)
+ {
+ rootPage->NotifyUser("No accelerometerReadingTransform found", NotifyType::ErrorMessage);
+ }
+
+ displayInformation = DisplayInformation::GetForCurrentView();
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario4_OrientationChanged::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ if (nullptr == accelerometerOriginal || nullptr == accelerometerReadingTransform)
+ {
+ ScenarioEnableButton->IsEnabled = false;
+ }
+ else
+ {
+ ScenarioEnableButton->IsEnabled = true;
+ }
+ ScenarioDisableButton->IsEnabled = false;
+
+ // Register for orientation change
+ orientationChangedToken = displayInformation->OrientationChanged += ref new Windows::Foundation::TypedEventHandler(this, &Scenario4_OrientationChanged::OnOrientationChanged);
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario4_OrientationChanged::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (NavigationMode::Forward == e->NavigationMode && nullptr == e->Uri)
+ {
+ return;
+ }
+
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ Window::Current->VisibilityChanged -= visibilityToken;
+ accelerometerOriginal->ReadingChanged -= readingTokenOriginal;
+ accelerometerReadingTransform->ReadingChanged -= readingTokenReadingTransform;
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometerOriginal->ReportInterval = 0;
+ accelerometerReadingTransform->ReportInterval = 0;
+ }
+
+ displayInformation->OrientationChanged -= orientationChangedToken;
+}
+
+
+///
+/// Invoked on pressing 'Enable' button'.
+///
+///
+///
+void Scenario4_OrientationChanged::ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ // Establish the report interval
+ accelerometerOriginal->ReportInterval = accelerometerReadingTransform->MinimumReportInterval;
+ accelerometerReadingTransform->ReportInterval = accelerometerReadingTransform->MinimumReportInterval;
+
+ // Establish the ReadingTransform to align with the current display orientation, so
+ // that the accelerometer data from 'accelerometerReadingTransform' will align with the
+ // current display orientation
+ accelerometerReadingTransform->ReadingTransform = displayInformation->CurrentOrientation;
+
+ visibilityToken = Window::Current->VisibilityChanged += ref new WindowVisibilityChangedEventHandler(this, &Scenario4_OrientationChanged::VisibilityChanged);
+
+ // Register for ReadingChanged event
+ readingTokenOriginal = accelerometerOriginal->ReadingChanged += ref new TypedEventHandler(this, &Scenario4_OrientationChanged::ReadingChangedOriginal);
+ readingTokenReadingTransform = accelerometerReadingTransform->ReadingChanged += ref new TypedEventHandler(this, &Scenario4_OrientationChanged::ReadingChangedReadingTransform);
+
+ ScenarioEnableButton->IsEnabled = false;
+ ScenarioDisableButton->IsEnabled = true;
+}
+
+
+
+///
+/// Invoked on pressing 'Disable' button'.
+///
+///
+///
+void Scenario4_OrientationChanged::ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometerOriginal->ReadingChanged::remove(readingTokenOriginal);
+ accelerometerReadingTransform->ReadingChanged::remove(readingTokenReadingTransform);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometerOriginal->ReportInterval = 0;
+ accelerometerReadingTransform->ReportInterval = 0;
+
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+
+}
+
+///
+/// This is the event handler for VisibilityChanged events. You would register for these notifications
+/// if handling sensor data when the app is not visible could cause unintended actions in the app.
+///
+///
+///
+/// Event data that can be examined for the current visibility state.
+///
+void Scenario4_OrientationChanged::VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
+{
+ // The app should watch for VisibilityChanged events to disable and re-enable sensor input as appropriate
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ if (e->Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ readingTokenOriginal = accelerometerOriginal->ReadingChanged += ref new TypedEventHandler(this, &Scenario4_OrientationChanged::ReadingChangedOriginal);
+ readingTokenReadingTransform = accelerometerReadingTransform->ReadingChanged += ref new TypedEventHandler(this, &Scenario4_OrientationChanged::ReadingChangedReadingTransform);
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ accelerometerOriginal->ReadingChanged::remove(readingTokenOriginal);
+ accelerometerReadingTransform->ReadingChanged::remove(readingTokenReadingTransform);
+ }
+ }
+}
+
+
+///
+/// This is the event handler for ReadingChanged event of the 'accelerometerOriginal' and should
+/// notify of the accelerometer reading changes.
+///
+///
+///
+/// Event data represents the accelerometer reading in its original reference frame.
+///
+void Scenario4_OrientationChanged::ReadingChangedOriginal(Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ e)
+{
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this, e]()
+ {
+ AccelerometerReading^ reading = e->Reading;
+
+ ScenarioOutput_X_Original->Text = reading->AccelerationX.ToString();
+ ScenarioOutput_Y_Original->Text = reading->AccelerationY.ToString();
+ ScenarioOutput_Z_Original->Text = reading->AccelerationZ.ToString();
+ },
+ CallbackContext::Any
+ )
+ );
+}
+
+
+///
+/// This is the event handler for ReadingChanged event of the 'accelerometerReadingTransform' and should
+/// notify of the accelerometer reading changes.
+///
+///
+///
+/// Event data represents the accelerometer reading in the reference frame of the current
+// display orientation (as set to 'ReadingTransform' property of the sensor).
+///
+void Scenario4_OrientationChanged::ReadingChangedReadingTransform(Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ e)
+{
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this, e]()
+ {
+ AccelerometerReading^ reading = e->Reading;
+
+ ScenarioOutput_X_ReadingTransform->Text = reading->AccelerationX.ToString();
+ ScenarioOutput_Y_ReadingTransform->Text = reading->AccelerationY.ToString();
+ ScenarioOutput_Z_ReadingTransform->Text = reading->AccelerationZ.ToString();
+ },
+ CallbackContext::Any
+ )
+ );
+}
+
+
+///
+/// This is the event handler for OrientationChanged events. You would register for these notifications
+/// if sensor data needs to be transformed to align with the current display orientation.
+///
+///
+/// DisplayInformation object from which the new Orientation can be determined
+///
+///
+void Scenario4_OrientationChanged::OnOrientationChanged(Windows::Graphics::Display::DisplayInformation ^sender, Platform::Object ^args)
+{
+ if (nullptr != accelerometerReadingTransform)
+ {
+ accelerometerReadingTransform->ReadingTransform = sender->CurrentOrientation;
+ }
+}
diff --git a/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.h b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.h
new file mode 100644
index 0000000000..b9ef560b07
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario4_OrientationChanged.xaml.h
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario4_OrientationChanged.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario4_OrientationChanged sealed
+ {
+ public:
+ Scenario4_OrientationChanged();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::Devices::Sensors::Accelerometer^ accelerometerOriginal;
+ Windows::Devices::Sensors::Accelerometer^ accelerometerReadingTransform;
+ Windows::Foundation::EventRegistrationToken visibilityToken;
+ Windows::Foundation::EventRegistrationToken readingTokenOriginal;
+ Windows::Foundation::EventRegistrationToken readingTokenReadingTransform;
+ Windows::Foundation::EventRegistrationToken orientationChangedToken;
+ Windows::Graphics::Display::DisplayInformation^ displayInformation;
+
+ void ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+
+ void VisibilityChanged(Platform::Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
+ void ReadingChangedOriginal(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ e);
+ void ReadingChangedReadingTransform(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ e);
+ void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation ^sender, Platform::Object ^args);
+ };
+}
diff --git a/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml
new file mode 100644
index 0000000000..0a8210db8e
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.cpp b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.cpp
new file mode 100644
index 0000000000..b812cf2ed9
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.cpp
@@ -0,0 +1,163 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario5_DataEventsBatching.xaml.cpp
+// Implementation of the Scenario5_DataEventsBatching class
+//
+
+#include "pch.h"
+#include "Scenario5_DataEventsBatching.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::UI::Core;
+using namespace Platform;
+
+Scenario5_DataEventsBatching::Scenario5_DataEventsBatching() : rootPage(MainPage::Current), desiredReportInterval(0), desiredReportLatency(0)
+{
+ InitializeComponent();
+
+ accelerometer = Accelerometer::GetDefault();
+ if (accelerometer != nullptr)
+ {
+ // Select a report interval and report latency that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint32 minReportInterval = accelerometer->MinimumReportInterval;
+ desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+
+ // MaxBatchSize will be 0 if the accelerometer does not support batching.
+ uint32 maxSupportedLatency = desiredReportInterval * accelerometer->MaxBatchSize;
+ desiredReportLatency = maxSupportedLatency < 10000 ? maxSupportedLatency : 10000;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario5_DataEventsBatching::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario5_DataEventsBatching::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (e->NavigationMode == NavigationMode::Forward && e->Uri == nullptr)
+ {
+ return;
+ }
+
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->ReadingChanged::remove(readingToken);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+ }
+}
+
+///
+/// This is the event handler for VisibilityChanged events. You would register for these notifications
+/// if handling sensor data when the app is not visible could cause unintended actions in the app.
+///
+///
+///
+/// Event data that can be examined for the current visibility state.
+///
+void Scenario5_DataEventsBatching::VisibilityChanged(Object^ sender, VisibilityChangedEventArgs^ e)
+{
+ // The app should watch for VisibilityChanged events to disable and re-enable sensor input as appropriate
+ if (ScenarioDisableButton->IsEnabled)
+ {
+ if (e->Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ readingToken = accelerometer->ReadingChanged::add(ref new TypedEventHandler(this, &Scenario5_DataEventsBatching::ReadingChanged));
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ accelerometer->ReadingChanged::remove(readingToken);
+ }
+ }
+}
+
+void Scenario5_DataEventsBatching::ReadingChanged(Accelerometer^ sender, AccelerometerReadingChangedEventArgs^ e)
+{
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this, e]()
+ {
+ AccelerometerReading^ reading = e->Reading;
+
+ ScenarioOutput_X->Text = reading->AccelerationX.ToString();
+ ScenarioOutput_Y->Text = reading->AccelerationY.ToString();
+ ScenarioOutput_Z->Text = reading->AccelerationZ.ToString();
+ },
+ CallbackContext::Any
+ )
+ );
+}
+
+void Scenario5_DataEventsBatching::ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (accelerometer != nullptr)
+ {
+ // Establish the report interval
+ accelerometer->ReportInterval = desiredReportInterval;
+
+ // Establish the report latency. This is a no-op if the accelerometer does not support batching
+ accelerometer->ReportLatency = desiredReportLatency;
+
+ visibilityToken = Window::Current->VisibilityChanged::add(ref new WindowVisibilityChangedEventHandler(this, &Scenario5_DataEventsBatching::VisibilityChanged));
+ readingToken = accelerometer->ReadingChanged::add(ref new TypedEventHandler(this, &Scenario5_DataEventsBatching::ReadingChanged));
+
+ ScenarioEnableButton->IsEnabled = false;
+ ScenarioDisableButton->IsEnabled = true;
+ }
+ else
+ {
+ rootPage->NotifyUser("No accelerometer found", NotifyType::ErrorMessage);
+ }
+}
+
+void Scenario5_DataEventsBatching::ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ Window::Current->VisibilityChanged::remove(visibilityToken);
+ accelerometer->ReadingChanged::remove(readingToken);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer->ReportInterval = 0;
+
+ ScenarioEnableButton->IsEnabled = true;
+ ScenarioDisableButton->IsEnabled = false;
+}
diff --git a/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.h b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.h
new file mode 100644
index 0000000000..ebaff9e9df
--- /dev/null
+++ b/Samples/Accelerometer/cpp/Scenario5_DataEventsBatching.xaml.h
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario5_DataEventsBatching.xaml.h
+// Declaration of the Scenario5_DataEventsBatching class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario5_DataEventsBatching.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario5_DataEventsBatching sealed
+ {
+ public:
+ Scenario5_DataEventsBatching();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::Devices::Sensors::Accelerometer^ accelerometer;
+ Windows::Foundation::EventRegistrationToken visibilityToken;
+ Windows::Foundation::EventRegistrationToken readingToken;
+ uint32 desiredReportInterval;
+ uint32 desiredReportLatency;
+
+ void VisibilityChanged(Platform::Object^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ e);
+ void ReadingChanged(Windows::Devices::Sensors::Accelerometer^ sender, Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs^ e);
+ void ScenarioEnable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioDisable(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/Accelerometer/cpp/pch.cpp b/Samples/Accelerometer/cpp/pch.cpp
new file mode 100644
index 0000000000..3ca571eb50
--- /dev/null
+++ b/Samples/Accelerometer/cpp/pch.cpp
@@ -0,0 +1,12 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
diff --git a/Samples/Accelerometer/cpp/pch.h b/Samples/Accelerometer/cpp/pch.h
new file mode 100644
index 0000000000..05d6651958
--- /dev/null
+++ b/Samples/Accelerometer/cpp/pch.h
@@ -0,0 +1,17 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include
+#include
+
+#include "App.xaml.h"
diff --git a/Samples/Accelerometer/cs/Accelerometer.csproj b/Samples/Accelerometer/cs/Accelerometer.csproj
new file mode 100644
index 0000000000..ce818bc4f2
--- /dev/null
+++ b/Samples/Accelerometer/cs/Accelerometer.csproj
@@ -0,0 +1,191 @@
+
+
+
+
+ Debug
+ x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
+ AppContainerExe
+ Properties
+ AccelerometerCS
+ AccelerometerCS
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+ App.xaml.cs
+ App.xaml
+
+
+ MainPage.xaml.cs
+ MainPage.xaml
+
+
+ Properties\AssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+ App.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MainPage.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/Accelerometer.sln b/Samples/Accelerometer/cs/Accelerometer.sln
new file mode 100644
index 0000000000..3919f241a5
--- /dev/null
+++ b/Samples/Accelerometer/cs/Accelerometer.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22820.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Accelerometer", "Accelerometer.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/Accelerometer/cs/Package.appxmanifest b/Samples/Accelerometer/cs/Package.appxmanifest
new file mode 100644
index 0000000000..c24cea491e
--- /dev/null
+++ b/Samples/Accelerometer/cs/Package.appxmanifest
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+ AccelerometerCS
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/SampleConfiguration.cs b/Samples/Accelerometer/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..cb1dff2671
--- /dev/null
+++ b/Samples/Accelerometer/cs/SampleConfiguration.cs
@@ -0,0 +1,38 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using AccelerometerCS;
+
+namespace SDKTemplate
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "AccelerometerCS";
+
+ List scenarios = new List
+ {
+ new Scenario() { Title = "Data events", ClassType = typeof(AccelerometerCS.Scenario1_DataEvents) },
+ new Scenario() { Title = "Shake events", ClassType = typeof(AccelerometerCS.Scenario2_ShakeEvents) },
+ new Scenario() { Title = "Polling", ClassType = typeof(AccelerometerCS.Scenario3_Polling) },
+ new Scenario() { Title = "OrientationChange", ClassType = typeof(AccelerometerCS.Scenario4_OrientationChanged) },
+ new Scenario() { Title = "Data events batching", ClassType = typeof(AccelerometerCS.Scenario5_DataEventsBatching)}
+ };
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+}
diff --git a/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml b/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml
new file mode 100644
index 0000000000..3dfa10c9be
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml.cs b/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml.cs
new file mode 100644
index 0000000000..6850c3aca2
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario1_DataEvents.xaml.cs
@@ -0,0 +1,166 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+
+namespace AccelerometerCS
+{
+ public sealed partial class Scenario1_DataEvents : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ private Accelerometer _accelerometer;
+ private uint _desiredReportInterval;
+
+ public Scenario1_DataEvents()
+ {
+ this.InitializeComponent();
+
+ _accelerometer = Accelerometer.GetDefault();
+ if (_accelerometer != null)
+ {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint minReportInterval = _accelerometer.MinimumReportInterval;
+ _desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ _accelerometer.ReportInterval = 0;
+ }
+
+ base.OnNavigatingFrom(e);
+ }
+
+ ///
+ /// This is the event handler for VisibilityChanged events. You would register for these notifications
+ /// if handling sensor data when the app is not visible could cause unintended actions in the app.
+ ///
+ ///
+ ///
+ /// Event data that can be examined for the current visibility state.
+ ///
+ private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ if (e.Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ _accelerometer.ReadingChanged += new TypedEventHandler(ReadingChanged);
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ _accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+ }
+ }
+ }
+
+ ///
+ /// This is the event handler for ReadingChanged events.
+ ///
+ ///
+ ///
+ async private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ AccelerometerReading reading = e.Reading;
+ ScenarioOutput_X.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
+ ScenarioOutput_Y.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
+ ScenarioOutput_Z.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
+ });
+ }
+
+ ///
+ /// This is the click handler for the 'Enable' button.
+ ///
+ ///
+ ///
+ private void ScenarioEnable(object sender, RoutedEventArgs e)
+ {
+ if (_accelerometer != null)
+ {
+ // Establish the report interval
+ _accelerometer.ReportInterval = _desiredReportInterval;
+
+ Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.ReadingChanged += new TypedEventHandler(ReadingChanged);
+
+ ScenarioEnableButton.IsEnabled = false;
+ ScenarioDisableButton.IsEnabled = true;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Disable' button.
+ ///
+ ///
+ ///
+ private void ScenarioDisable(object sender, RoutedEventArgs e)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ _accelerometer.ReportInterval = 0;
+
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+ }
+}
diff --git a/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml b/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml
new file mode 100644
index 0000000000..d5a8477c32
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml.cs b/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml.cs
new file mode 100644
index 0000000000..2b018f49d3
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario2_ShakeEvents.xaml.cs
@@ -0,0 +1,148 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+// Windows Store code
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using Windows.UI.Core;
+
+namespace AccelerometerCS
+{
+ public sealed partial class Scenario2_ShakeEvents : Page
+ {
+ private Accelerometer _accelerometer;
+ private ushort _shakeCount;
+
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ public Scenario2_ShakeEvents()
+ {
+ this.InitializeComponent();
+
+ _accelerometer = Accelerometer.GetDefault();
+ if (_accelerometer == null)
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ _shakeCount = 0;
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.Shaken -= new TypedEventHandler(Shaken);
+ }
+
+ base.OnNavigatingFrom(e);
+ }
+
+ ///
+ /// This is the event handler for VisibilityChanged events. You would register for these notifications
+ /// if handling sensor data when the app is not visible could cause unintended actions in the app.
+ ///
+ ///
+ ///
+ /// Event data that can be examined for the current visibility state.
+ ///
+ private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ if (e.Visible)
+ {
+ // Re-enable sensor input
+ _accelerometer.Shaken += new TypedEventHandler(Shaken);
+ }
+ else
+ {
+ // Disable sensor input
+ _accelerometer.Shaken -= new TypedEventHandler(Shaken);
+ }
+ }
+ }
+
+ ///
+ /// This is the event handler for Shaken events.
+ ///
+ ///
+ ///
+ async private void Shaken(object sender, AccelerometerShakenEventArgs e)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ _shakeCount++;
+ ScenarioOutputText.Text = _shakeCount.ToString();
+ });
+ }
+
+ ///
+ /// This is the click handler for the 'Enable' button.
+ ///
+ ///
+ ///
+ private void ScenarioEnable(object sender, RoutedEventArgs e)
+ {
+ if (_accelerometer != null)
+ {
+ Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.Shaken += new TypedEventHandler(Shaken);
+ ScenarioEnableButton.IsEnabled = false;
+ ScenarioDisableButton.IsEnabled = true;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Disable' button.
+ ///
+ ///
+ ///
+ private void ScenarioDisable(object sender, RoutedEventArgs e)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _accelerometer.Shaken -= new TypedEventHandler(Shaken);
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+ }
+}
diff --git a/Samples/Accelerometer/cs/Scenario3_Polling.xaml b/Samples/Accelerometer/cs/Scenario3_Polling.xaml
new file mode 100644
index 0000000000..17489a8b78
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario3_Polling.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/Scenario3_Polling.xaml.cs b/Samples/Accelerometer/cs/Scenario3_Polling.xaml.cs
new file mode 100644
index 0000000000..4c65972e72
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario3_Polling.xaml.cs
@@ -0,0 +1,177 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+
+namespace AccelerometerCS
+{
+ public sealed partial class Scenario3_Polling : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ private Accelerometer _accelerometer;
+ private uint _desiredReportInterval;
+ private DispatcherTimer _dispatcherTimer;
+
+ public Scenario3_Polling()
+ {
+ this.InitializeComponent();
+
+ _accelerometer = Accelerometer.GetDefault();
+ if (_accelerometer != null)
+ {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint minReportInterval = _accelerometer.MinimumReportInterval;
+ _desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+
+ // Set up a DispatchTimer
+ _dispatcherTimer = new DispatcherTimer();
+ _dispatcherTimer.Tick += DisplayCurrentReading;
+ _dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, (int)_desiredReportInterval);
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+
+ // Stop the dispatcher
+ _dispatcherTimer.Stop();
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ _accelerometer.ReportInterval = 0;
+ }
+
+ base.OnNavigatingFrom(e);
+ }
+
+ ///
+ /// This is the event handler for VisibilityChanged events. You would register for these notifications
+ /// if handling sensor data when the app is not visible could cause unintended actions in the app.
+ ///
+ ///
+ ///
+ /// Event data that can be examined for the current visibility state.
+ ///
+ private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ if (e.Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ _dispatcherTimer.Start();
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ _dispatcherTimer.Stop();
+ }
+ }
+ }
+
+ ///
+ /// This is the dispatcher callback.
+ ///
+ ///
+ ///
+ private void DisplayCurrentReading(object sender, object args)
+ {
+ AccelerometerReading reading = _accelerometer.GetCurrentReading();
+ if (reading != null)
+ {
+ ScenarioOutput_X.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
+ ScenarioOutput_Y.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
+ ScenarioOutput_Z.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Enable' button.
+ ///
+ ///
+ ///
+ private void ScenarioEnable(object sender, RoutedEventArgs e)
+ {
+ if (_accelerometer != null)
+ {
+ // Set the report interval to enable the sensor for polling
+ _accelerometer.ReportInterval = _desiredReportInterval;
+
+ Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ _dispatcherTimer.Start();
+
+ ScenarioEnableButton.IsEnabled = false;
+ ScenarioDisableButton.IsEnabled = true;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Disable' button.
+ ///
+ ///
+ ///
+ private void ScenarioDisable(object sender, RoutedEventArgs e)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+
+ // Stop the dispatcher
+ _dispatcherTimer.Stop();
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ _accelerometer.ReportInterval = 0;
+
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+ }
+}
diff --git a/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml b/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml
new file mode 100644
index 0000000000..5a451ff4f3
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml.cs b/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml.cs
new file mode 100644
index 0000000000..8942b27ef7
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario4_OrientationChanged.xaml.cs
@@ -0,0 +1,228 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+using Windows.Graphics.Display;
+
+namespace AccelerometerCS
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario4_OrientationChanged : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ Accelerometer accelerometerOriginal;
+ Accelerometer accelerometerReadingTransform;
+ DisplayInformation displayInformation;
+
+ public Scenario4_OrientationChanged()
+ {
+ this.InitializeComponent();
+
+ // Get two instances of the accelerometer:
+ // One that returns the raw accelerometer data
+ accelerometerOriginal = Accelerometer.GetDefault();
+ // Other on which the 'ReadingTransform' is updated so that data returned aligns with the request transformation.
+ accelerometerReadingTransform = Accelerometer.GetDefault();
+
+ if(accelerometerOriginal == null || accelerometerReadingTransform == null)
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ displayInformation = DisplayInformation.GetForCurrentView();
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ if (accelerometerOriginal == null || accelerometerReadingTransform == null)
+ {
+ ScenarioEnableButton.IsEnabled = false;
+ }
+ else
+ {
+ ScenarioEnableButton.IsEnabled = true;
+ }
+ ScenarioDisableButton.IsEnabled = false;
+
+ // Register for orientation change
+ displayInformation.OrientationChanged += displayInformation_OrientationChanged;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ Window.Current.VisibilityChanged -= Current_VisibilityChanged;
+ accelerometerOriginal.ReadingChanged -= _accelerometerOriginal_ReadingChanged;
+ accelerometerReadingTransform.ReadingChanged -= _accelerometerReadingTransform_ReadingChanged;
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometerOriginal.ReportInterval = 0;
+ accelerometerReadingTransform.ReportInterval = 0;
+ }
+
+ displayInformation.OrientationChanged -= displayInformation_OrientationChanged;
+
+ base.OnNavigatingFrom(e);
+ }
+
+
+ ///
+ /// Invoked when there is a change in the display orientation.
+ ///
+ ///
+ /// DisplayInformation object from which the new Orientation can be determined
+ ///
+ ///
+ void displayInformation_OrientationChanged(DisplayInformation sender, object args)
+ {
+ if (null != accelerometerReadingTransform)
+ {
+ accelerometerReadingTransform.ReadingTransform = sender.CurrentOrientation;
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Enable' button.
+ ///
+ ///
+ ///
+ void ScenarioEnable(object sender, RoutedEventArgs e)
+ {
+ // Establish the report interval
+ accelerometerOriginal.ReportInterval = accelerometerOriginal.MinimumReportInterval;
+ accelerometerReadingTransform.ReportInterval = accelerometerReadingTransform.MinimumReportInterval;
+
+ // Establish the ReadingTransform to align with the current display orientation, so
+ // that the accelerometer data from 'accelerometerReadingTransform' will align with the
+ // current display orientation
+ accelerometerReadingTransform.ReadingTransform = displayInformation.CurrentOrientation;
+
+ Window.Current.VisibilityChanged += Current_VisibilityChanged;
+ accelerometerOriginal.ReadingChanged += _accelerometerOriginal_ReadingChanged;
+ accelerometerReadingTransform.ReadingChanged += _accelerometerReadingTransform_ReadingChanged;
+
+ ScenarioEnableButton.IsEnabled = false;
+ ScenarioDisableButton.IsEnabled = true;
+ }
+
+
+ ///
+ /// This is the event handler for ReadingChanged event of the 'accelerometerOriginal' and should
+ /// notify of the accelerometer reading changes.
+ ///
+ ///
+ ///
+ /// Event data represents the accelerometer reading in its original reference frame.
+ ///
+ async void _accelerometerOriginal_ReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ AccelerometerReading reading = args.Reading;
+ ScenarioOutput_X_Original.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
+ ScenarioOutput_Y_Original.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
+ ScenarioOutput_Z_Original.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
+ });
+ }
+
+
+ ///
+ /// This is the event handler for ReadingChanged event of the 'accelerometerReadingTransform' and should
+ /// notify of the accelerometer reading changes.
+ ///
+ ///
+ ///
+ /// Event data represents the accelerometer reading in its original reference frame.
+ ///
+ async void _accelerometerReadingTransform_ReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ AccelerometerReading reading = args.Reading;
+ ScenarioOutput_X_ReadingTransform.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
+ ScenarioOutput_Y_ReadingTransform.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
+ ScenarioOutput_Z_ReadingTransform.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
+ });
+ }
+
+ ///
+ /// This is the event handler for VisibilityChanged events. You would register for these notifications
+ /// if handling sensor data when the app is not visible could cause unintended actions in the app.
+ ///
+ ///
+ ///
+ /// Event data that can be examined for the current visibility state.
+ ///
+ void Current_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ if (e.Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ accelerometerOriginal.ReadingChanged += _accelerometerOriginal_ReadingChanged;
+ accelerometerReadingTransform.ReadingChanged += _accelerometerReadingTransform_ReadingChanged;
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ accelerometerOriginal.ReadingChanged -= _accelerometerOriginal_ReadingChanged;
+ accelerometerReadingTransform.ReadingChanged -= _accelerometerReadingTransform_ReadingChanged;
+ }
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Disable' button.
+ ///
+ ///
+ ///
+ void ScenarioDisable(object sender, RoutedEventArgs e)
+ {
+ Window.Current.VisibilityChanged -= Current_VisibilityChanged;
+ accelerometerOriginal.ReadingChanged -= _accelerometerOriginal_ReadingChanged;
+ accelerometerReadingTransform.ReadingChanged -= _accelerometerReadingTransform_ReadingChanged;
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometerOriginal.ReportInterval = 0;
+ accelerometerReadingTransform.ReportInterval = 0;
+
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+ }
+}
diff --git a/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml b/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml
new file mode 100644
index 0000000000..24f5a8e4b3
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml.cs b/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml.cs
new file mode 100644
index 0000000000..c9746a5b30
--- /dev/null
+++ b/Samples/Accelerometer/cs/Scenario5_DataEventsBatching.xaml.cs
@@ -0,0 +1,174 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+using System;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+
+namespace AccelerometerCS
+{
+ public sealed partial class Scenario5_DataEventsBatching : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ private Accelerometer accelerometer;
+ private uint desiredReportInterval;
+ private uint desiredReportLatency;
+
+
+ public Scenario5_DataEventsBatching()
+ {
+ this.InitializeComponent();
+
+ accelerometer = Accelerometer.GetDefault();
+ if (accelerometer != null)
+ {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ uint minReportInterval = accelerometer.MinimumReportInterval;
+ desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;
+
+ // MaxBatchSize will be 0 if the accelerometer does not support batching.
+ uint maxLatency = accelerometer.MaxBatchSize * desiredReportInterval;
+ desiredReportLatency = maxLatency < 10000 ? maxLatency : 10000;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer.ReportInterval = 0;
+ }
+
+ base.OnNavigatingFrom(e);
+ }
+
+ ///
+ /// This is the event handler for VisibilityChanged events. You would register for these notifications
+ /// if handling sensor data when the app is not visible could cause unintended actions in the app.
+ ///
+ ///
+ ///
+ /// Event data that can be examined for the current visibility state.
+ ///
+ private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+ if (ScenarioDisableButton.IsEnabled)
+ {
+ if (e.Visible)
+ {
+ // Re-enable sensor input (no need to restore the desired reportInterval... it is restored for us upon app resume)
+ accelerometer.ReadingChanged += new TypedEventHandler(ReadingChanged);
+ }
+ else
+ {
+ // Disable sensor input (no need to restore the default reportInterval... resources will be released upon app suspension)
+ accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+ }
+ }
+ }
+
+ ///
+ /// This is the event handler for ReadingChanged events.
+ ///
+ ///
+ ///
+ async private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ AccelerometerReading reading = e.Reading;
+ ScenarioOutput_X.Text = String.Format("{0,5:0.00}", reading.AccelerationX);
+ ScenarioOutput_Y.Text = String.Format("{0,5:0.00}", reading.AccelerationY);
+ ScenarioOutput_Z.Text = String.Format("{0,5:0.00}", reading.AccelerationZ);
+ });
+ }
+
+ ///
+ /// This is the click handler for the 'Enable' button.
+ ///
+ ///
+ ///
+ private void ScenarioEnable(object sender, RoutedEventArgs e)
+ {
+ if (accelerometer != null)
+ {
+ // Establish the report interval
+ accelerometer.ReportInterval = desiredReportInterval;
+
+ // Establish the report latency. This is a no-op if the accelerometer does not support batching
+ accelerometer.ReportLatency = desiredReportLatency;
+ Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ accelerometer.ReadingChanged += new TypedEventHandler(ReadingChanged);
+
+ ScenarioEnableButton.IsEnabled = false;
+ ScenarioDisableButton.IsEnabled = true;
+ }
+ else
+ {
+ rootPage.NotifyUser("No accelerometer found", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Disable' button.
+ ///
+ ///
+ ///
+ private void ScenarioDisable(object sender, RoutedEventArgs e)
+ {
+ Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged);
+ accelerometer.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+
+ // Restore the default report interval to release resources while the sensor is not in use
+ accelerometer.ReportInterval = 0;
+
+ ScenarioEnableButton.IsEnabled = true;
+ ScenarioDisableButton.IsEnabled = false;
+ }
+ }
+}
diff --git a/Samples/Accelerometer/cs/project.json b/Samples/Accelerometer/cs/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/Accelerometer/cs/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/Accelerometer.jsproj b/Samples/Accelerometer/js/Accelerometer.jsproj
new file mode 100644
index 0000000000..50a74a1841
--- /dev/null
+++ b/Samples/Accelerometer/js/Accelerometer.jsproj
@@ -0,0 +1,152 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ Debug
+ ARM
+
+
+ Debug
+ x64
+
+
+ Debug
+ x86
+
+
+ Release
+ AnyCPU
+
+
+ Release
+ ARM
+
+
+ Release
+ x64
+
+
+ Release
+ x86
+
+
+
+ c2adb9af-edb3-4e57-8056-9d0531d4a6b2
+
+
+
+ 14.0
+
+
+
+
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ $(VersionNumberMajor).$(VersionNumberMinor)
+ en-US
+
+
+
+ Designer
+
+
+
+
+
+
+
+ default.html
+
+
+
+
+
+
+
+ images\microsoft-sdk.png
+
+
+ images\smallTile-sdk.png
+
+
+ images\splash-sdk.png
+
+
+ images\storeLogo-sdk.png
+
+
+ images\tile-sdk.png
+
+
+ images\windows-sdk.png
+
+
+ js\default.js
+
+
+ css\default.css
+
+
+
+
+
+
+
+
+ Microsoft.WinJS.4.0\css\ui-dark.css
+
+
+ Microsoft.WinJS.4.0\css\ui-light.css
+
+
+ Microsoft.WinJS.4.0\js\en-US\ui.strings.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense-setup.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense.js
+
+
+ Microsoft.WinJS.4.0\fonts\Symbols.ttf
+
+
+ Microsoft.WinJS.4.0\js\base.js
+
+
+ Microsoft.WinJS.4.0\js\ui.js
+
+
+ sample-utils\footer.html
+
+
+ sample-utils\header.html
+
+
+ sample-utils\sample-utils.js
+
+
+ sample-utils\scenario-select.css
+
+
+ sample-utils\scenario-select.html
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/Accelerometer.sln b/Samples/Accelerometer/js/Accelerometer.sln
new file mode 100644
index 0000000000..ec32f09b5a
--- /dev/null
+++ b/Samples/Accelerometer/js/Accelerometer.sln
@@ -0,0 +1,48 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22609.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "Accelerometer", "Accelerometer.jsproj", "{C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.Build.0 = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.Deploy.0 = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.ActiveCfg = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.Build.0 = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.Deploy.0 = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.ActiveCfg = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.Build.0 = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.Deploy.0 = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.ActiveCfg = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.Build.0 = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.Deploy.0 = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.ActiveCfg = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.Build.0 = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.Deploy.0 = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.ActiveCfg = Release|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.Build.0 = Release|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/Accelerometer/js/Microsoft.WinJS.4.0/css/placeholder.txt b/Samples/Accelerometer/js/Microsoft.WinJS.4.0/css/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/Accelerometer/js/Microsoft.WinJS.4.0/fonts/placeholder b/Samples/Accelerometer/js/Microsoft.WinJS.4.0/fonts/placeholder
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/Accelerometer/js/Microsoft.WinJS.4.0/js/en-us/placeholder.txt b/Samples/Accelerometer/js/Microsoft.WinJS.4.0/js/en-us/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/Accelerometer/js/Package.appxmanifest b/Samples/Accelerometer/js/Package.appxmanifest
new file mode 100644
index 0000000000..485064c191
--- /dev/null
+++ b/Samples/Accelerometer/js/Package.appxmanifest
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+ Accelerometer JS SDK Sample
+ Microsoft Corporation
+ images\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/css/scenario1_DataEvents.css b/Samples/Accelerometer/js/css/scenario1_DataEvents.css
new file mode 100644
index 0000000000..b76d53df43
--- /dev/null
+++ b/Samples/Accelerometer/js/css/scenario1_DataEvents.css
@@ -0,0 +1,14 @@
+/*
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+*/
+
+/* styles */
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/css/scenario2_ShakeEvents.css b/Samples/Accelerometer/js/css/scenario2_ShakeEvents.css
new file mode 100644
index 0000000000..b76d53df43
--- /dev/null
+++ b/Samples/Accelerometer/js/css/scenario2_ShakeEvents.css
@@ -0,0 +1,14 @@
+/*
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+*/
+
+/* styles */
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/css/scenario3_Polling.css b/Samples/Accelerometer/js/css/scenario3_Polling.css
new file mode 100644
index 0000000000..b76d53df43
--- /dev/null
+++ b/Samples/Accelerometer/js/css/scenario3_Polling.css
@@ -0,0 +1,14 @@
+/*
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+*/
+
+/* styles */
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/css/scenario4_OrientationChanged.css b/Samples/Accelerometer/js/css/scenario4_OrientationChanged.css
new file mode 100644
index 0000000000..b76d53df43
--- /dev/null
+++ b/Samples/Accelerometer/js/css/scenario4_OrientationChanged.css
@@ -0,0 +1,14 @@
+/*
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+*/
+
+/* styles */
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/css/scenario5_DataEventsBatching.css b/Samples/Accelerometer/js/css/scenario5_DataEventsBatching.css
new file mode 100644
index 0000000000..b76d53df43
--- /dev/null
+++ b/Samples/Accelerometer/js/css/scenario5_DataEventsBatching.css
@@ -0,0 +1,14 @@
+/*
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+*/
+
+/* styles */
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/html/scenario1_DataEvents.html b/Samples/Accelerometer/js/html/scenario1_DataEvents.html
new file mode 100644
index 0000000000..2fcb7465ce
--- /dev/null
+++ b/Samples/Accelerometer/js/html/scenario1_DataEvents.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Registers an event listener for accelerometer data and displays the X, Y and Z acceleration values as they are reported.
+
Enable
+
Disable
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/html/scenario2_ShakeEvents.html b/Samples/Accelerometer/js/html/scenario2_ShakeEvents.html
new file mode 100644
index 0000000000..40be33c413
--- /dev/null
+++ b/Samples/Accelerometer/js/html/scenario2_ShakeEvents.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Registers an event listener for accelerometer shake events and displays the cumulative count of shake events.
+
+
Enable
+
Disable
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/html/scenario3_Polling.html b/Samples/Accelerometer/js/html/scenario3_Polling.html
new file mode 100644
index 0000000000..84ae67f96b
--- /dev/null
+++ b/Samples/Accelerometer/js/html/scenario3_Polling.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Polls for accelerometer data and displays the X, Y and Z acceleration values at a set interval.
+
Enable
+
Disable
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/html/scenario4_OrientationChanged.html b/Samples/Accelerometer/js/html/scenario4_OrientationChanged.html
new file mode 100644
index 0000000000..f89d331eee
--- /dev/null
+++ b/Samples/Accelerometer/js/html/scenario4_OrientationChanged.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Registers for OrientationChanged event of the DisplayInformation class to illustrate the usage of the 'ReadingTransform' Property. Displays accelerometer readings with and without the transformation.
+
+
Enable
+
Disable
+
+
+
+
+
+
+ Transform:
+ None
+ DisplayOrientation
+
+
+ X:
+ no data
+ no data
+
+
+ Y:
+ no data
+ no data
+
+
+ Z:
+ no data
+ no data
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/html/scenario5_DataEventsBatching.html b/Samples/Accelerometer/js/html/scenario5_DataEventsBatching.html
new file mode 100644
index 0000000000..c84176b0f6
--- /dev/null
+++ b/Samples/Accelerometer/js/html/scenario5_DataEventsBatching.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Registers an event listener for accelerometer data (with a report latency specified) and displays the X, Y and Z acceleration values as they are reported.
+
+
Enable
+
Disable
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/js/sample-configuration.js b/Samples/Accelerometer/js/js/sample-configuration.js
new file mode 100644
index 0000000000..c5eef00d34
--- /dev/null
+++ b/Samples/Accelerometer/js/js/sample-configuration.js
@@ -0,0 +1,20 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+
+ var sampleTitle = "AccelerometerJS";
+
+ var scenarios = [
+ { url: "/html/scenario1_DataEvents.html", title: "Data Events" },
+ { url: "/html/scenario2_ShakeEvents.html", title: "Shake Events" },
+ { url: "/html/scenario3_Polling.html", title: "Polling" },
+ { url: "/html/scenario4_OrientationChanged.html", title: "OrientationChanged Handling" },
+ { url: "/html/scenario5_DataEventsBatching.html", title: "Data Events Batching" }
+ ];
+
+ WinJS.Namespace.define("SdkSample", {
+ sampleTitle: sampleTitle,
+ scenarios: new WinJS.Binding.List(scenarios)
+ });
+})();
\ No newline at end of file
diff --git a/Samples/Accelerometer/js/js/scenario1_DataEvents.js b/Samples/Accelerometer/js/js/scenario1_DataEvents.js
new file mode 100644
index 0000000000..5a55579353
--- /dev/null
+++ b/Samples/Accelerometer/js/js/scenario1_DataEvents.js
@@ -0,0 +1,90 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var reportInterval = 0;
+ var accelerometer;
+
+ var page = WinJS.UI.Pages.define("/html/scenario1_DataEvents.html", {
+ ready: function (element, options) {
+ document.getElementById("scenario1Open").addEventListener("click", enableReadingChangedScenario, false);
+ document.getElementById("scenario1Revoke").addEventListener("click", disableReadingChangedScenario, false);
+ document.getElementById("scenario1Open").disabled = false;
+ document.getElementById("scenario1Revoke").disabled = true;
+
+ accelerometer = Windows.Devices.Sensors.Accelerometer.getDefault();
+ if (accelerometer) {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ var minimumReportInterval = accelerometer.minimumReportInterval;
+ reportInterval = minimumReportInterval > 16 ? minimumReportInterval : 16;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ },
+ unload: function () {
+ if (document.getElementById("scenario1Open").disabled) {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+ }
+ });
+
+ function visibilityChangeHandler() {
+ // This is the event handler for VisibilityChanged events. You would register for these notifications
+ // if handling sensor data when the app is not visible could cause unintended actions in the app.
+ if (document.getElementById("scenario1Open").disabled) {
+ if (document.msVisibilityState === "visible") {
+ // Re-enable sensor input. No need to restore the desired reportInterval (it is restored for us upon app resume)
+ accelerometer.addEventListener("readingchanged", onDataChanged);
+ } else {
+ // Disable sensor input. No need to restore the default reportInterval (resources will be released upon app suspension)
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+ }
+ }
+ }
+
+ function onDataChanged(e) {
+ var reading = e.reading;
+
+ // event can still be in queue after unload is called
+ // so check if elements are still loaded
+
+ if (document.getElementById("eventOutputX")) {
+ document.getElementById("eventOutputX").innerHTML = reading.accelerationX.toFixed(2);
+ }
+ if (document.getElementById("eventOutputY")) {
+ document.getElementById("eventOutputY").innerHTML = reading.accelerationY.toFixed(2);
+ }
+ if (document.getElementById("eventOutputZ")) {
+ document.getElementById("eventOutputZ").innerHTML = reading.accelerationZ.toFixed(2);
+ }
+ }
+
+ function enableReadingChangedScenario() {
+ if (accelerometer) {
+ // Set the reportInterval to enable the sensor events
+ accelerometer.reportInterval = reportInterval;
+
+ document.addEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.addEventListener("readingchanged", onDataChanged);
+ document.getElementById("scenario1Open").disabled = true;
+ document.getElementById("scenario1Revoke").disabled = false;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ }
+
+ function disableReadingChangedScenario() {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+ document.getElementById("scenario1Open").disabled = false;
+ document.getElementById("scenario1Revoke").disabled = true;
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+})();
diff --git a/Samples/Accelerometer/js/js/scenario2_ShakeEvents.js b/Samples/Accelerometer/js/js/scenario2_ShakeEvents.js
new file mode 100644
index 0000000000..7bca2f0bba
--- /dev/null
+++ b/Samples/Accelerometer/js/js/scenario2_ShakeEvents.js
@@ -0,0 +1,67 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var accelerometer;
+
+ var page = WinJS.UI.Pages.define("/html/scenario2_ShakeEvents.html", {
+ ready: function (element, options) {
+ document.getElementById("scenario2Open").addEventListener("click", enableShakenScenario, false);
+ document.getElementById("scenario2Revoke").addEventListener("click", disableShakenScenario, false);
+ document.getElementById("scenario2Open").disabled = false;
+ document.getElementById("scenario2Revoke").disabled = true;
+
+ accelerometer = Windows.Devices.Sensors.Accelerometer.getDefault();
+ if (accelerometer === null) {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ },
+ unload: function () {
+ if (document.getElementById("scenario2Open").disabled) {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("shaken", onShaken);
+ }
+ }
+ });
+
+ function visibilityChangeHandler() {
+ // This is the event handler for VisibilityChanged events. You would register for these notifications
+ // if handling sensor data when the app is not visible could cause unintended actions in the app.
+ if (document.getElementById("scenario2Open").disabled) {
+ if (document.msVisibilityState === "visible") {
+ // Re-enable sensor input
+ accelerometer.addEventListener("shaken", onShaken);
+ } else {
+ // Disable sensor input
+ accelerometer.removeEventListener("shaken", onShaken);
+ }
+ }
+ }
+
+ var onShaken = (function () {
+ var shakeCount = 0;
+
+ return function (e) {
+ shakeCount++;
+ document.getElementById("shakeOutput").innerHTML = shakeCount;
+ };
+ })();
+
+ function enableShakenScenario() {
+ if (accelerometer) {
+ document.addEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.addEventListener("shaken", onShaken);
+ document.getElementById("scenario2Open").disabled = true;
+ document.getElementById("scenario2Revoke").disabled = false;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ }
+
+ function disableShakenScenario() {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("shaken", onShaken);
+ document.getElementById("scenario2Open").disabled = false;
+ document.getElementById("scenario2Revoke").disabled = true;
+ }
+})();
diff --git a/Samples/Accelerometer/js/js/scenario3_Polling.js b/Samples/Accelerometer/js/js/scenario3_Polling.js
new file mode 100644
index 0000000000..07bab9022b
--- /dev/null
+++ b/Samples/Accelerometer/js/js/scenario3_Polling.js
@@ -0,0 +1,83 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var reportInterval = 0;
+ var intervalId = 0;
+ var accelerometer;
+
+ var page = WinJS.UI.Pages.define("/html/scenario3_Polling.html", {
+ ready: function (element, options) {
+ document.getElementById("scenario3Open").addEventListener("click", enableGetReadingScenario, false);
+ document.getElementById("scenario3Revoke").addEventListener("click", disableGetReadingScenario, false);
+ document.getElementById("scenario3Open").disabled = false;
+ document.getElementById("scenario3Revoke").disabled = true;
+
+ accelerometer = Windows.Devices.Sensors.Accelerometer.getDefault();
+ if (accelerometer) {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ var minimumReportInterval = accelerometer.minimumReportInterval;
+ reportInterval = minimumReportInterval > 16 ? minimumReportInterval : 16;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ },
+ unload: function () {
+ if (document.getElementById("scenario3Open").disabled) {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ clearInterval(intervalId);
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+ }
+ });
+
+ function visibilityChangeHandler() {
+ // This is the event handler for VisibilityChanged events. You would register for these notifications
+ // if handling sensor data when the app is not visible could cause unintended actions in the app.
+ if (document.getElementById("scenario3Open").disabled) {
+ if (document.msVisibilityState === "visible") {
+ // Re-enable sensor input. No need to restore the desired reportInterval (it is restored for us upon app resume)
+ intervalId = setInterval(getCurrentReading, reportInterval);
+ } else {
+ // Disable sensor input. No need to restore the default reportInterval (resources will be released upon app suspension)
+ clearInterval(intervalId);
+ }
+ }
+ }
+
+ function getCurrentReading() {
+ var reading = accelerometer.getCurrentReading();
+ if (reading) {
+ document.getElementById("readingOutputX").innerHTML = reading.accelerationX.toFixed(2);
+ document.getElementById("readingOutputY").innerHTML = reading.accelerationY.toFixed(2);
+ document.getElementById("readingOutputZ").innerHTML = reading.accelerationZ.toFixed(2);
+ }
+ }
+
+ function enableGetReadingScenario() {
+ if (accelerometer) {
+ // Set the report interval to enable the sensor for polling
+ accelerometer.reportInterval = reportInterval;
+
+ document.addEventListener("visibilitychange", visibilityChangeHandler, false);
+ intervalId = setInterval(getCurrentReading, reportInterval);
+ document.getElementById("scenario3Open").disabled = true;
+ document.getElementById("scenario3Revoke").disabled = false;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ }
+
+ function disableGetReadingScenario() {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ clearInterval(intervalId);
+ document.getElementById("scenario3Open").disabled = false;
+ document.getElementById("scenario3Revoke").disabled = true;
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+})();
diff --git a/Samples/Accelerometer/js/js/scenario4_OrientationChanged.js b/Samples/Accelerometer/js/js/scenario4_OrientationChanged.js
new file mode 100644
index 0000000000..1996fc8121
--- /dev/null
+++ b/Samples/Accelerometer/js/js/scenario4_OrientationChanged.js
@@ -0,0 +1,131 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var accelerometerOriginal;
+ var accelerometerReadingTransform;
+ var displayInformation;
+
+ var page = WinJS.UI.Pages.define("/html/scenario4_OrientationChanged.html", {
+ ready: function (element, options) {
+ var disableOpen = true;
+ document.getElementById("scenario4Open").addEventListener("click", enableOrientationChangedScenario, false);
+ document.getElementById("scenario4Revoke").addEventListener("click", disableOrientationChangedScenario, false);
+ document.getElementById("scenario4Revoke").disabled = true;
+
+ displayInformation = Windows.Graphics.Display.DisplayInformation.getForCurrentView();
+
+ // Get two instances of the accelerometer:
+ // One that returns the raw accelerometer data
+ accelerometerOriginal = Windows.Devices.Sensors.Accelerometer.getDefault();
+ // Other on which the 'ReadingTransform' is updated so that data returned aligns with the request transformation.
+ accelerometerReadingTransform = Windows.Devices.Sensors.Accelerometer.getDefault();
+
+ if (!accelerometerOriginal || !accelerometerReadingTransform) {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ } else {
+ disableOpen = false;
+ displayInformation.addEventListener("orientationchanged", onOrientationChanged);
+ }
+ document.getElementById("scenario4Open").disabled = disableOpen;
+ },
+ unload: function () {
+ if (!document.getElementById("scenario4Revoke").disabled) {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ displayInformation.removeEventListener("orientationchanged", onOrientationChanged);
+ accelerometerOriginal.removeEventListener("readingchanged", onDataChangedOriginal);
+ accelerometerReadingTransform.removeEventListener("readingchanged", onDataChangedReadingTransform);
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometerOriginal.reportInterval = 0;
+ accelerometerReadingTransform.reportInterval = 0;
+ }
+ }
+ });
+
+ function visibilityChangeHandler() {
+ // This is the event handler for VisibilityChanged events. You would register for these notifications
+ // if handling sensor data when the app is not visible could cause unintended actions in the app.
+ if (!document.getElementById("scenario4Revoke").disabled) {
+ if (document.msVisibilityState === "visible") {
+ // Re-enable sensor input. No need to restore the desired reportInterval (it is restored for us upon app resume)
+ accelerometerOriginal.addEventListener("readingchanged", onDataChangedOriginal);
+ accelerometerReadingTransform.addEventListener("readingchanged", onDataChangedReadingTransform);
+ } else {
+ // Disable sensor input. No need to restore the default reportInterval (resources will be released upon app suspension)
+ accelerometerOriginal.removeEventListener("readingchanged", onDataChangedOriginal);
+ accelerometerReadingTransform.removeEventListener("readingchanged", onDataChangedReadingTransform);
+ }
+ }
+ }
+
+ function onDataChangedOriginal(e) {
+ var reading = e.reading;
+
+ // event can still be in queue after unload is called
+ // so check if elements are still loaded
+
+ if (document.getElementById("eventOutputXOriginal")) {
+ document.getElementById("eventOutputXOriginal").innerHTML = reading.accelerationX.toFixed(2);
+ }
+ if (document.getElementById("eventOutputYOriginal")) {
+ document.getElementById("eventOutputYOriginal").innerHTML = reading.accelerationY.toFixed(2);
+ }
+ if (document.getElementById("eventOutputZOriginal")) {
+ document.getElementById("eventOutputZOriginal").innerHTML = reading.accelerationZ.toFixed(2);
+ }
+ }
+
+ function onDataChangedReadingTransform(e) {
+ var reading = e.reading;
+
+ // event can still be in queue after unload is called
+ // so check if elements are still loaded
+
+ if (document.getElementById("eventOutputXDataTransform")) {
+ document.getElementById("eventOutputXDataTransform").innerHTML = reading.accelerationX.toFixed(2);
+ }
+ if (document.getElementById("eventOutputYDataTransform")) {
+ document.getElementById("eventOutputYDataTransform").innerHTML = reading.accelerationY.toFixed(2);
+ }
+ if (document.getElementById("eventOutputZDataTransform")) {
+ document.getElementById("eventOutputZDataTransform").innerHTML = reading.accelerationZ.toFixed(2);
+ }
+ }
+
+ function enableOrientationChangedScenario() {
+ // Set the reportInterval to enable the sensor events
+ accelerometerOriginal.reportInterval = accelerometerOriginal.minimumReportInterval;
+ accelerometerReadingTransform.reportInterval = accelerometerReadingTransform.minimumReportInterval;
+
+ // Set the readingTransform to align with the current display orientation
+ accelerometerReadingTransform.readingTransform = displayInformation.currentOrientation;
+
+ accelerometerOriginal.addEventListener("readingchanged", onDataChangedOriginal);
+ accelerometerReadingTransform.addEventListener("readingchanged", onDataChangedReadingTransform);
+
+ document.addEventListener("visibilitychange", visibilityChangeHandler, false);
+
+ document.getElementById("scenario4Open").disabled = true;
+ document.getElementById("scenario4Revoke").disabled = false;
+ }
+
+ function disableOrientationChangedScenario() {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometerOriginal.removeEventListener("readingchanged", onDataChangedOriginal);
+ accelerometerReadingTransform.removeEventListener("readingchanged", onDataChangedReadingTransform);
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometerOriginal.reportInterval = 0;
+ accelerometerReadingTransform.reportInterval = 0;
+
+ document.getElementById("scenario4Open").disabled = false;
+ document.getElementById("scenario4Revoke").disabled = true;
+ }
+
+ function onOrientationChanged(eventArgs) {
+ if (accelerometerReadingTransform) {
+ accelerometerReadingTransform.readingTransform = eventArgs.target.currentOrientation;
+ }
+ }
+})();
diff --git a/Samples/Accelerometer/js/js/scenario5_DataEventsBatching.js b/Samples/Accelerometer/js/js/scenario5_DataEventsBatching.js
new file mode 100644
index 0000000000..172a794d7e
--- /dev/null
+++ b/Samples/Accelerometer/js/js/scenario5_DataEventsBatching.js
@@ -0,0 +1,98 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var reportInterval = 0;
+ var reportLatency = 0;
+ var accelerometer;
+
+ var page = WinJS.UI.Pages.define("/html/scenario5_DataEventsBatching.html", {
+ ready: function (element, options) {
+ document.getElementById("scenario5Open").addEventListener("click", enableReadingChangedScenario, false);
+ document.getElementById("scenario5Revoke").addEventListener("click", disableReadingChangedScenario, false);
+ document.getElementById("scenario5Open").disabled = false;
+ document.getElementById("scenario5Revoke").disabled = true;
+
+ accelerometer = Windows.Devices.Sensors.Accelerometer.getDefault();
+ if (accelerometer) {
+ // Select a report interval that is both suitable for the purposes of the app and supported by the sensor.
+ // This value will be used later to activate the sensor.
+ var minimumReportInterval = accelerometer.minimumReportInterval;
+ reportInterval = minimumReportInterval > 16 ? minimumReportInterval : 16;
+
+ // MaxBatchSize will be 0 if the accelerometer does not support batching.
+ var maxLatency = accelerometer.MaxBatchSize * reportLatency;
+ reportLatency = maxLatency < 10 ? maxLatency : 10;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ },
+ unload: function () {
+ if (document.getElementById("scenario5Open").disabled) {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+ }
+ });
+
+ function visibilityChangeHandler() {
+ // This is the event handler for VisibilityChanged events. You would register for these notifications
+ // if handling sensor data when the app is not visible could cause unintended actions in the app.
+ if (document.getElementById("scenario5Open").disabled) {
+ if (document.msVisibilityState === "visible") {
+ // Re-enable sensor input. No need to restore the desired reportInterval (it is restored for us upon app resume)
+ accelerometer.addEventListener("readingchanged", onDataChanged);
+ } else {
+ // Disable sensor input. No need to restore the default reportInterval (resources will be released upon app suspension)
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+ }
+ }
+ }
+
+ function onDataChanged(e) {
+ var reading = e.reading;
+
+ // event can still be in queue after unload is called
+ // so check if elements are still loaded
+
+ if (document.getElementById("eventOutputX")) {
+ document.getElementById("eventOutputX").innerHTML = reading.accelerationX.toFixed(2);
+ }
+ if (document.getElementById("eventOutputY")) {
+ document.getElementById("eventOutputY").innerHTML = reading.accelerationY.toFixed(2);
+ }
+ if (document.getElementById("eventOutputZ")) {
+ document.getElementById("eventOutputZ").innerHTML = reading.accelerationZ.toFixed(2);
+ }
+ }
+
+ function enableReadingChangedScenario() {
+ if (accelerometer) {
+ // Set the reportInterval to enable the sensor events
+ accelerometer.reportInterval = reportInterval;
+
+ // Set the report latency. This is a no-op if the accelerometer does not support batching
+ accelerometer.reportLatency = reportLatency;
+
+ document.addEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.addEventListener("readingchanged", onDataChanged);
+ document.getElementById("scenario5Open").disabled = true;
+ document.getElementById("scenario5Revoke").disabled = false;
+ } else {
+ WinJS.log && WinJS.log("No accelerometer found", "sample", "error");
+ }
+ }
+
+ function disableReadingChangedScenario() {
+ document.removeEventListener("visibilitychange", visibilityChangeHandler, false);
+ accelerometer.removeEventListener("readingchanged", onDataChanged);
+ document.getElementById("scenario5Open").disabled = false;
+ document.getElementById("scenario5Revoke").disabled = true;
+
+ // Return the report interval to its default to release resources while the sensor is not in use
+ accelerometer.reportInterval = 0;
+ }
+})();
diff --git a/Samples/Accelerometer/js/sample-utils/placeholder.txt b/Samples/Accelerometer/js/sample-utils/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/README.md b/Samples/AccountPictureName/README.md
new file mode 100644
index 0000000000..789d459ba8
--- /dev/null
+++ b/Samples/AccountPictureName/README.md
@@ -0,0 +1,53 @@
+
+# Account picture name sample
+
+This sample demonstrates different ways of getting the name of the user that is currently logged in. It also demonstrates how to get and set the image used for the user's tile.
+
+Specifically, this sample demonstrates the following scenarios:
+
+- How to get the [**DisplayName**](http://msdn.microsoft.com/library/windows/apps/hh921595) for the current logged on user.
+- How to get the first and last name for the current logged on user. (This is available only for Microsoft accounts. An empty string is returned if a Microsoft account is not available.)
+- How to obtain the logged on user's account picture as a bitmap. You can get request three different types: small, large, and video. If the size that is requested is not available an empty file is returned.
+- How to set the account picture for the currently logged on user. You can set three different types: small, large, and video. (More than one type can be set in the same call, but a small image must be accompanied by a large image and/or video.)
+- How to register for a change event for account picture updates.
+
+**Note** The Universal Windows app samples require Visual Studio 2015 to build and Windows 10 to execute.
+
+To obtain information about Windows 10, go to [Windows 10](http://go.microsoft.com/fwlink/?LinkID=532421)
+
+To obtain information about Microsoft Visual Studio 2015 and the tools for developing Windows apps, go to [Visual Studio 2015](http://go.microsoft.com/fwlink/?LinkID=532422)
+
+## Related topics
+
+### Reference
+
+[**Windows.System.UserProfile** namespace](http://msdn.microsoft.com/library/windows/apps/br241881)
+
+## System requirements
+
+**Client:** Windows 10
+
+**Server:** Windows Server 2016 Technical Preview
+
+**Phone:** Not supported
+
+## Build the sample
+
+1. Start Microsoft Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C++, C#, or JavaScript. Double-click the Visual Studio 2015 Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+### Deploying the sample
+
+- Select Build > Deploy Solution.
+
+### Deploying and running the sample
+
+- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or select Debug > Start Without Debugging.
+
diff --git a/Samples/AccountPictureName/cpp/AccountPictureName.sln b/Samples/AccountPictureName/cpp/AccountPictureName.sln
new file mode 100644
index 0000000000..80b5afae19
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/AccountPictureName.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AccountPictureName", "AccountPictureName.vcxproj", "{C5B886A7-8300-46FF-B533-9613DE2AF637}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|ARM.Build.0 = Debug|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|ARM.Deploy.0 = Debug|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x64.ActiveCfg = Debug|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x64.Build.0 = Debug|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x64.Deploy.0 = Debug|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x86.ActiveCfg = Debug|Win32
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x86.Build.0 = Debug|Win32
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Debug|x86.Deploy.0 = Debug|Win32
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|ARM.ActiveCfg = Release|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|ARM.Build.0 = Release|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|ARM.Deploy.0 = Release|ARM
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x64.ActiveCfg = Release|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x64.Build.0 = Release|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x64.Deploy.0 = Release|x64
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x86.ActiveCfg = Release|Win32
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x86.Build.0 = Release|Win32
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj b/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj
new file mode 100644
index 0000000000..176706c626
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj
@@ -0,0 +1,245 @@
+
+
+
+ {C5B886A7-8300-46FF-B533-9613DE2AF637}
+ SDKTemplate
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.10240.0
+ 10.0.10240.0
+ true
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+
+ ..\shared\GetAccountPicture.xaml
+
+
+ ..\shared\GetUserDisplayName.xaml
+
+
+ ..\shared\GetUserFirstAndLastName.xaml
+
+
+ ..\shared\SetAccountPicture.xaml
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ Designer
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+ ..\shared\GetAccountPicture.xaml
+
+
+ ..\shared\GetUserDisplayName.xaml
+
+
+ ..\shared\GetUserFirstAndLastName.xaml
+
+
+ ..\shared\SetAccountPicture.xaml
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smalltile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squaretile-sdk.png
+
+
+ Assets\storelogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj.filters b/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj.filters
new file mode 100644
index 0000000000..21f9938e98
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/AccountPictureName.vcxproj.filters
@@ -0,0 +1,71 @@
+
+
+
+
+ 80bfd669-aa83-4537-9611-027cffe0d8af
+ bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png
+
+
+ {c6978fb6-bc64-498d-97c8-f5b53997e54e}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Styles
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.cpp b/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.cpp
new file mode 100644
index 0000000000..6570deefcc
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.cpp
@@ -0,0 +1,155 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "GetAccountPicture.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::System::UserProfile;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Media::Imaging;
+using namespace Windows::UI::Xaml::Navigation;
+
+GetAccountPicture::GetAccountPicture() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+}
+
+void GetAccountPicture::GetSmallImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ HideImageAndVideoControls();
+
+ if (UserInformation::NameAccessAllowed)
+ {
+ auto smallImageFile = UserInformation::GetAccountPicture(AccountPictureKind::SmallImage);
+ if (smallImageFile != nullptr)
+ {
+ rootPage->NotifyUser("Path = " + smallImageFile->Path, NotifyType::StatusMessage);
+ create_task(smallImageFile->OpenReadAsync()).then(
+ [this](task imageStreamTask)
+ {
+ try
+ {
+ auto imageStream = imageStreamTask.get();
+ auto bitmapImage = ref new BitmapImage();
+ bitmapImage->SetSource(imageStream);
+ SmallImage->Source = bitmapImage;
+ SmallImage->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+ catch (Exception^ ex)
+ {
+ rootPage->NotifyUser("Error opening stream: " + ex->Message, NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Small account picture is not available.", NotifyType::ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
+
+void GetAccountPicture::GetLargeImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ HideImageAndVideoControls();
+
+ if (UserInformation::NameAccessAllowed)
+ {
+ auto largeImageFile = UserInformation::GetAccountPicture(AccountPictureKind::LargeImage);
+ if (largeImageFile != nullptr)
+ {
+ rootPage->NotifyUser("Path = " + largeImageFile->Path, NotifyType::StatusMessage);
+ create_task(largeImageFile->OpenReadAsync()).then(
+ [this](task imageStreamTask)
+ {
+ try
+ {
+ auto imageStream = imageStreamTask.get();
+ auto bitmapImage = ref new BitmapImage();
+ bitmapImage->SetSource(imageStream);
+ LargeImage->Source = bitmapImage;
+ LargeImage->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+ catch (Exception^ ex)
+ {
+ rootPage->NotifyUser("Error opening stream: " + ex->Message, NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No large account picture image returned for current user.", NotifyType::ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
+
+void GetAccountPicture::GetVideoButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ HideImageAndVideoControls();
+
+ if (UserInformation::NameAccessAllowed)
+ {
+ auto videoFile = UserInformation::GetAccountPicture(AccountPictureKind::Video);
+ if (videoFile != nullptr)
+ {
+ rootPage->NotifyUser("Path = " + videoFile->Path, NotifyType::StatusMessage);
+ create_task(videoFile->OpenReadAsync()).then(
+ [this](task videoStreamTask)
+ {
+ try
+ {
+ auto videoStream = videoStreamTask.get();
+ MediaPlayer->SetSource(videoStream, "video/mp4");
+ MediaPlayer->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+ catch (Exception^ ex)
+ {
+ rootPage->NotifyUser("Error opening stream: " + ex->Message, NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Video is not available.", NotifyType::ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
+
+void GetAccountPicture::HideImageAndVideoControls()
+{
+ SmallImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+ LargeImage->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+ MediaPlayer->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
+}
diff --git a/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.h b/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.h
new file mode 100644
index 0000000000..0d6ad31bd4
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetAccountPicture.xaml.h
@@ -0,0 +1,31 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "GetAccountPicture.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class GetAccountPicture sealed
+ {
+ public:
+ GetAccountPicture();
+ private:
+ MainPage^ rootPage;
+ void GetSmallImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void GetLargeImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void GetVideoButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void HideImageAndVideoControls();
+ };
+}
diff --git a/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.cpp b/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.cpp
new file mode 100644
index 0000000000..ecc0c71d6c
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.cpp
@@ -0,0 +1,55 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "GetUserDisplayName.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::System::UserProfile;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+GetUserDisplayName::GetUserDisplayName() : rootPage(SDKTemplate::MainPage::Current)
+{
+ InitializeComponent();
+}
+
+void GetUserDisplayName::GetDisplayNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (UserInformation::NameAccessAllowed)
+ {
+ create_task(UserInformation::GetDisplayNameAsync()).then([this](String^ displayName)
+ {
+ if (displayName != nullptr)
+ {
+ rootPage->NotifyUser("Display name = " + displayName, NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage->NotifyUser("No display name was returned.", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
diff --git a/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.h b/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.h
new file mode 100644
index 0000000000..2830f0c074
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetUserDisplayName.xaml.h
@@ -0,0 +1,29 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "GetUserDisplayName.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class GetUserDisplayName sealed
+ {
+ public:
+ GetUserDisplayName();
+
+ private:
+ MainPage^ rootPage;
+ void GetDisplayNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.cpp b/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.cpp
new file mode 100644
index 0000000000..d1fa5cda87
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.cpp
@@ -0,0 +1,77 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "GetUserFirstAndLastName.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::System::UserProfile;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+GetUserFirstAndLastName::GetUserFirstAndLastName() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+}
+
+void GetUserFirstAndLastName::GetFirstNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (UserInformation::NameAccessAllowed)
+ {
+ create_task(UserInformation::GetFirstNameAsync()).then([this](String^ firstName)
+ {
+ if (firstName != nullptr)
+ {
+ rootPage->NotifyUser("First name = " + firstName, NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage->NotifyUser("No first name was returned.", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
+
+void GetUserFirstAndLastName::GetLastNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ if (UserInformation::NameAccessAllowed)
+ {
+ create_task(UserInformation::GetLastNameAsync()).then([this](String^ lastName)
+ {
+ if (lastName != nullptr)
+ {
+ rootPage->NotifyUser("Last name = " + lastName, NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage->NotifyUser("No last name was returned.", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+}
diff --git a/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.h b/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.h
new file mode 100644
index 0000000000..c337a2bb0f
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/GetUserFirstAndLastName.xaml.h
@@ -0,0 +1,29 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "GetUserFirstAndLastName.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class GetUserFirstAndLastName sealed
+ {
+ public:
+ GetUserFirstAndLastName();
+ private:
+ MainPage^ rootPage;
+ void GetFirstNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void GetLastNameButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/AccountPictureName/cpp/Package.appxmanifest b/Samples/AccountPictureName/cpp/Package.appxmanifest
new file mode 100644
index 0000000000..eab571cc5d
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/Package.appxmanifest
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+ Account Picture Name C++ Sample
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/cpp/SampleConfiguration.cpp b/Samples/AccountPictureName/cpp/SampleConfiguration.cpp
new file mode 100644
index 0000000000..a28a93699c
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/SampleConfiguration.cpp
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+#include "SampleConfiguration.h"
+
+using namespace SDKTemplate;
+using namespace Platform;
+using namespace Windows::ApplicationModel;
+using namespace Windows::ApplicationModel::Activation;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Interop;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Navigation;
+
+Platform::Array^ MainPage::scenariosInner = ref new Platform::Array
+{
+ { "Get display name", "SDKTemplate.GetUserDisplayName" },
+ { "Get first and last name", "SDKTemplate.GetUserFirstAndLastName" },
+ { "Get account picture", "SDKTemplate.GetAccountPicture" },
+ { "Set account picture and listen for changes", "SDKTemplate.SetAccountPicture" }
+};
+
+void App::OnActivated(IActivatedEventArgs^ args)
+{
+ // Check to see if the app was activated via a protocol
+ if (args->Kind == ActivationKind::Protocol)
+ {
+ auto protocolArgs = safe_cast(args);
+ if (protocolArgs->Uri->SchemeName->Equals("ms-accountpictureprovider"))
+ {
+ if (Window::Current->Content == nullptr)
+ {
+ auto rootFrame = ref new Frame();
+ TypeName pageType = { "SDKTemplate.MainPage", TypeKind::Custom };
+ rootFrame->Navigate(pageType);
+ Window::Current->Content = rootFrame;
+ Window::Current->Activate();
+ }
+
+ MainPage::Current->NavigateToScenario("SDKTemplate.SetAccountPicture");
+ }
+ }
+}
diff --git a/Samples/AccountPictureName/cpp/SampleConfiguration.h b/Samples/AccountPictureName/cpp/SampleConfiguration.h
new file mode 100644
index 0000000000..9a7651fd7b
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/SampleConfiguration.h
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+#pragma once
+#include "pch.h"
+
+namespace SDKTemplate
+{
+ value struct Scenario;
+
+ partial ref class MainPage
+ {
+ internal:
+ static property Platform::String^ FEATURE_NAME
+ {
+ Platform::String^ get()
+ {
+ return "Account picture name C++ sample";
+ }
+ }
+
+ static property Platform::Array^ scenarios
+ {
+ Platform::Array^ get()
+ {
+ return scenariosInner;
+ }
+ }
+
+ void NavigateToScenario(Platform::String^ scenario)
+ {
+ for (unsigned index = 0; index < scenarios->Length; index++)
+ {
+ if (scenarios[index].ClassName == scenario)
+ {
+ ScenarioControl->SelectedIndex = index;
+ break;
+ }
+ }
+ }
+
+ private:
+ static Platform::Array^ scenariosInner;
+ };
+
+ public value struct Scenario
+ {
+ Platform::String^ Title;
+ Platform::String^ ClassName;
+ };
+
+ partial ref class App sealed
+ {
+ protected:
+ virtual void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs^ args) override;
+ };
+}
diff --git a/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.cpp b/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.cpp
new file mode 100644
index 0000000000..4b565f9ff7
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.cpp
@@ -0,0 +1,160 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "SetAccountPicture.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace concurrency;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::Storage::Pickers;
+using namespace Windows::System::UserProfile;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Controls::Primitives;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Media::Imaging;
+using namespace Windows::UI::Xaml::Navigation;
+
+SetAccountPicture::SetAccountPicture() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+}
+
+void SetAccountPicture::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ accountPictureChangedToken = UserInformation::AccountPictureChanged += ref new EventHandler(this, &SetAccountPicture::PictureChanged);
+}
+
+void SetAccountPicture::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ UserInformation::AccountPictureChanged -= accountPictureChangedToken;
+}
+
+void SetAccountPicture::SetImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ FileOpenPicker^ imagePicker = ref new FileOpenPicker();
+ imagePicker->ViewMode = PickerViewMode::Thumbnail;
+ imagePicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
+ imagePicker->FileTypeFilter->Append(".jpg");
+ imagePicker->FileTypeFilter->Append(".jpeg");
+ imagePicker->FileTypeFilter->Append(".png");
+ imagePicker->FileTypeFilter->Append(".bmp");
+
+ create_task(imagePicker->PickSingleFileAsync()).then(
+ [this](StorageFile^ imageFile)
+ {
+ if (imageFile != nullptr)
+ {
+ rootPage->NotifyUser("Setting " + imageFile->Name + " as account picture ...",
+ NotifyType::StatusMessage);
+ create_task(UserInformation::SetAccountPictureAsync(imageFile)).then(
+ [this](SetAccountPictureResult setPictureResult)
+ {
+ if (setPictureResult == SetAccountPictureResult::Success)
+ {
+ rootPage->NotifyUser("Successfully updated account picture.", NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage->NotifyUser("Setting account picture failed.", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No image was selected.", NotifyType::StatusMessage);
+ }
+ });
+}
+
+void SetAccountPicture::SetVideoButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
+{
+ FileOpenPicker^ videoPicker = ref new FileOpenPicker();
+ videoPicker->ViewMode = PickerViewMode::Thumbnail;
+ videoPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
+ videoPicker->FileTypeFilter->Append(".mp4");
+ videoPicker->FileTypeFilter->Append(".wmv");
+ videoPicker->FileTypeFilter->Append(".mpeg");
+ videoPicker->FileTypeFilter->Append(".mov");
+
+ create_task(videoPicker->PickSingleFileAsync()).then(
+ [this](StorageFile^ videoFile)
+ {
+ if (videoFile != nullptr)
+ {
+ rootPage->NotifyUser("Setting " + videoFile->Name + " as account picture ...",
+ NotifyType::StatusMessage);
+ create_task(UserInformation::SetAccountPictureAsync(videoFile)).then(
+ [this](SetAccountPictureResult setPictureResult)
+ {
+ if (setPictureResult == SetAccountPictureResult::Success)
+ {
+ rootPage->NotifyUser("Successfully updated account picture.", NotifyType::StatusMessage);
+ }
+ else
+ {
+ rootPage->NotifyUser("Setting account picture failed.", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No video was selected.", NotifyType::StatusMessage);
+ }
+ });
+}
+
+void SetAccountPicture::PictureChanged(Platform::Object^ sender, Platform::Object^ e)
+{
+ Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
+ {
+ if (UserInformation::NameAccessAllowed)
+ {
+ auto largeImageFile = UserInformation::GetAccountPicture(AccountPictureKind::LargeImage);
+ if (largeImageFile != nullptr)
+ {
+ create_task(largeImageFile->OpenReadAsync()).then(
+ [this](task imageStreamTask)
+ {
+ try
+ {
+ auto imageStream = imageStreamTask.get();
+ auto bitmapImage = ref new BitmapImage();
+ bitmapImage->SetSource(imageStream);
+ AccountPictureImage->Source = bitmapImage;
+ AccountPictureImage->Visibility = Windows::UI::Xaml::Visibility::Visible;
+ }
+ catch (Exception^ ex)
+ {
+ rootPage->NotifyUser("Failed to read from stream. " + ex->Message, NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No large account picture image returned for current user.", NotifyType::ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType::ErrorMessage);
+ }
+ }));
+}
diff --git a/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.h b/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.h
new file mode 100644
index 0000000000..e5cf9fdb9a
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/SetAccountPicture.xaml.h
@@ -0,0 +1,36 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+
+#include "SetAccountPicture.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class SetAccountPicture sealed
+ {
+ public:
+ SetAccountPicture();
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ MainPage^ rootPage;
+ void SetImageButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void SetVideoButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void PictureChanged(Platform::Object^ sender, Platform::Object^ e);
+
+ Windows::Foundation::EventRegistrationToken accountPictureChangedToken;
+ };
+}
diff --git a/Samples/AccountPictureName/cpp/pch.cpp b/Samples/AccountPictureName/cpp/pch.cpp
new file mode 100644
index 0000000000..ade821753a
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/pch.cpp
@@ -0,0 +1,5 @@
+//
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/AccountPictureName/cpp/pch.h b/Samples/AccountPictureName/cpp/pch.h
new file mode 100644
index 0000000000..2662955e22
--- /dev/null
+++ b/Samples/AccountPictureName/cpp/pch.h
@@ -0,0 +1,11 @@
+//
+// Header for standard system include files.
+//
+
+#pragma once
+
+#include
+#include
+
+#include "SampleConfiguration.h"
+#include "App.xaml.h"
diff --git a/Samples/AccountPictureName/cs/AccountPictureName.csproj b/Samples/AccountPictureName/cs/AccountPictureName.csproj
new file mode 100644
index 0000000000..c0acb7551d
--- /dev/null
+++ b/Samples/AccountPictureName/cs/AccountPictureName.csproj
@@ -0,0 +1,203 @@
+
+
+
+
+ Debug
+ x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}
+ AppContainerExe
+ Properties
+ SDKTemplate
+ AccountPictureName
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+ App.xaml.cs
+ App.xaml
+
+
+ MainPage.xaml.cs
+ MainPage.xaml
+
+
+ Properties\AssemblyInfo.cs
+
+
+
+ GetUserDisplayName.xaml
+
+
+ GetAccountPicture.xaml
+
+
+ GetUserFirstAndLastName.xaml
+
+
+ SetAccountPicture.xaml
+
+
+
+
+ Designer
+
+
+
+
+ App.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MainPage.xaml
+ MSBuild:Compile
+ Designer
+
+
+ GetUserDisplayName.xaml
+ MSBuild:Compile
+ Designer
+
+
+ GetAccountPicture.xaml
+ MSBuild:Compile
+ Designer
+
+
+ GetUserFirstAndLastName.xaml
+ MSBuild:Compile
+ Designer
+
+
+ SetAccountPicture.xaml
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ Microsoft Desktop Extension SDK for Universal App Platform
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/cs/AccountPictureName.sln b/Samples/AccountPictureName/cs/AccountPictureName.sln
new file mode 100644
index 0000000000..8924a9375e
--- /dev/null
+++ b/Samples/AccountPictureName/cs/AccountPictureName.sln
@@ -0,0 +1,43 @@
+
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22609.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AccountPictureName", "AccountPictureName.csproj", "{CF1CD0D5-BF6B-457A-9927-8079FC667CA4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|ARM.ActiveCfg = Debug|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|ARM.Build.0 = Debug|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|ARM.Deploy.0 = Debug|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x64.ActiveCfg = Debug|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x64.Build.0 = Debug|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x64.Deploy.0 = Debug|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x86.ActiveCfg = Debug|x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x86.Build.0 = Debug|x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Debug|x86.Deploy.0 = Debug|x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|ARM.ActiveCfg = Release|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|ARM.Build.0 = Release|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|ARM.Deploy.0 = Release|ARM
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x64.ActiveCfg = Release|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x64.Build.0 = Release|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x64.Deploy.0 = Release|x64
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x86.ActiveCfg = Release|x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x86.Build.0 = Release|x86
+ {CF1CD0D5-BF6B-457A-9927-8079FC667CA4}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
+
+
diff --git a/Samples/AccountPictureName/cs/GetAccountPicture.xaml.cs b/Samples/AccountPictureName/cs/GetAccountPicture.xaml.cs
new file mode 100644
index 0000000000..53a4af871a
--- /dev/null
+++ b/Samples/AccountPictureName/cs/GetAccountPicture.xaml.cs
@@ -0,0 +1,151 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using System;
+using Windows.Storage;
+using Windows.Storage.Streams;
+using Windows.UI.Xaml.Media.Imaging;
+using Windows.System.UserProfile;
+
+namespace SDKTemplate
+{
+ public sealed partial class GetAccountPicture : Page
+ {
+ private MainPage rootPage;
+
+ public GetAccountPicture()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ private async void GetSmallImageButton_Click(object sender, RoutedEventArgs e)
+ {
+ HideImageAndVideoControls();
+
+ if (UserInformation.NameAccessAllowed)
+ {
+ // The small picture returned by GetAccountPicture() is 96x96 pixels in size.
+ StorageFile image = UserInformation.GetAccountPicture(AccountPictureKind.SmallImage) as StorageFile;
+ if (image != null)
+ {
+ rootPage.NotifyUser("Path = " + image.Path, NotifyType.StatusMessage);
+
+ try
+ {
+ IRandomAccessStream imageStream = await image.OpenReadAsync();
+ BitmapImage bitmapImage = new BitmapImage();
+ bitmapImage.SetSource(imageStream);
+ SmallImage.Source = bitmapImage;
+ SmallImage.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex)
+ {
+ rootPage.NotifyUser("Error opening stream: " + ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Small account picture is not available.", NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+
+ private async void GetLargeImageButton_Click(object sender, RoutedEventArgs e)
+ {
+ HideImageAndVideoControls();
+
+ if (UserInformation.NameAccessAllowed)
+ {
+ // The large picture returned by GetAccountPicture() is 448x448 pixels in size.
+ StorageFile image = UserInformation.GetAccountPicture(AccountPictureKind.LargeImage) as StorageFile;
+ if (image != null)
+ {
+ rootPage.NotifyUser("Path = " + image.Path, NotifyType.StatusMessage);
+
+ try
+ {
+ IRandomAccessStream imageStream = await image.OpenReadAsync();
+ BitmapImage bitmapImage = new BitmapImage();
+ bitmapImage.SetSource(imageStream);
+ LargeImage.Source = bitmapImage;
+ LargeImage.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex)
+ {
+ rootPage.NotifyUser("Error opening stream: " + ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Large account picture is not available.", NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+
+ private async void GetVideoButton_Click(object sender, RoutedEventArgs e)
+ {
+ HideImageAndVideoControls();
+
+ if (UserInformation.NameAccessAllowed)
+ {
+ // The video returned from getAccountPicture is 448x448 pixels in size.
+ StorageFile video = UserInformation.GetAccountPicture(AccountPictureKind.Video) as StorageFile;
+ if (video != null)
+ {
+ rootPage.NotifyUser("Path: " + video.Path, NotifyType.StatusMessage);
+
+ try
+ {
+ IRandomAccessStream videoStream = await video.OpenAsync(FileAccessMode.Read);
+ MediaPlayer.SetSource(videoStream, "video/mp4");
+ MediaPlayer.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex)
+ {
+ rootPage.NotifyUser("Error opening stream: " + ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Video is not available.", NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to account picture disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+
+ private void HideImageAndVideoControls()
+ {
+ SmallImage.Visibility = Visibility.Collapsed;
+ LargeImage.Visibility = Visibility.Collapsed;
+ MediaPlayer.Visibility = Visibility.Collapsed;
+ }
+
+ }
+}
diff --git a/Samples/AccountPictureName/cs/GetUserDisplayName.xaml.cs b/Samples/AccountPictureName/cs/GetUserDisplayName.xaml.cs
new file mode 100644
index 0000000000..9288f48a59
--- /dev/null
+++ b/Samples/AccountPictureName/cs/GetUserDisplayName.xaml.cs
@@ -0,0 +1,54 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using System;
+using Windows.System.UserProfile;
+
+namespace SDKTemplate
+{
+ public sealed partial class GetUserDisplayName : Page
+ {
+ private MainPage rootPage;
+
+ public GetUserDisplayName()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ private async void GetDisplayNameButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (UserInformation.NameAccessAllowed)
+ {
+ string displayName = await UserInformation.GetDisplayNameAsync();
+ if (string.IsNullOrEmpty(displayName))
+ {
+ rootPage.NotifyUser("No display name was returned.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("Display name = " + displayName, NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+ }
+}
diff --git a/Samples/AccountPictureName/cs/GetUserFirstAndLastName.xaml.cs b/Samples/AccountPictureName/cs/GetUserFirstAndLastName.xaml.cs
new file mode 100644
index 0000000000..ba1643b7b7
--- /dev/null
+++ b/Samples/AccountPictureName/cs/GetUserFirstAndLastName.xaml.cs
@@ -0,0 +1,74 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using System;
+using Windows.System.UserProfile;
+
+namespace SDKTemplate
+{
+ public sealed partial class GetUserFirstAndLastName : Page
+ {
+ private MainPage rootPage;
+
+ public GetUserFirstAndLastName()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ private async void GetFirstNameButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (UserInformation.NameAccessAllowed)
+ {
+ string firstName = await UserInformation.GetFirstNameAsync();
+ if (string.IsNullOrEmpty(firstName))
+ {
+ rootPage.NotifyUser("No first name was returned.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("First name = " + firstName, NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+
+ private async void GetLastNameButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (UserInformation.NameAccessAllowed)
+ {
+ string lastName = await UserInformation.GetLastNameAsync();
+ if (string.IsNullOrEmpty(lastName))
+ {
+ rootPage.NotifyUser("No last name was returned.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("Last name = " + lastName, NotifyType.StatusMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to name disabled by Privacy Setting or Group Policy.", NotifyType.ErrorMessage);
+ }
+ }
+ }
+}
diff --git a/Samples/AccountPictureName/cs/Package.appxmanifest b/Samples/AccountPictureName/cs/Package.appxmanifest
new file mode 100644
index 0000000000..e1b4540aec
--- /dev/null
+++ b/Samples/AccountPictureName/cs/Package.appxmanifest
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+ Account Picture Name C# Sample
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/cs/SampleConfiguration.cs b/Samples/AccountPictureName/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..acbb82e6ef
--- /dev/null
+++ b/Samples/AccountPictureName/cs/SampleConfiguration.cs
@@ -0,0 +1,82 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace SDKTemplate
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "Account picture name C# sample";
+
+ List scenarios = new List
+ {
+ new Scenario() { Title = "Get display name", ClassType = typeof(GetUserDisplayName) },
+ new Scenario() { Title = "Get first and last name", ClassType = typeof(GetUserFirstAndLastName) },
+ new Scenario() { Title = "Get account picture", ClassType = typeof(GetAccountPicture) },
+ new Scenario() { Title = "Set account picture and listen for changes", ClassType = typeof(SetAccountPicture) }
+ };
+
+ public void NavigateToScenario(Type type)
+ {
+ for (int index = 0; index < scenarios.Count; index++)
+ {
+ if (scenarios[index].ClassType == type)
+ {
+ ScenarioControl.SelectedIndex = index;
+ break;
+ }
+ }
+ }
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+
+ ///
+ /// Provides sample-specific behavior to supplement the default Application class.
+ ///
+ sealed partial class App : Application
+ {
+ protected override void OnActivated(IActivatedEventArgs args)
+ {
+ // Check to see if the app was activated via a protocol
+ if (args.Kind == ActivationKind.Protocol)
+ {
+ var protocolArgs = (ProtocolActivatedEventArgs)args;
+
+ // This app was activated via the Account picture apps section in PC Settings / Personalize / Account picture.
+ // Here you would do app-specific logic so that the user receives account picture selection UX.
+ if (protocolArgs.Uri.Scheme == "ms-accountpictureprovider")
+ {
+ // The Content might be null if App has not yet been activated, if so first activate the main page.
+ if (Window.Current.Content == null)
+ {
+ Frame rootFrame = new Frame();
+ rootFrame.Navigate(typeof(MainPage));
+ Window.Current.Content = rootFrame;
+ Window.Current.Activate();
+ }
+ MainPage.Current.NavigateToScenario(typeof(SDKTemplate.SetAccountPicture));
+ }
+ }
+ }
+ }
+}
diff --git a/Samples/AccountPictureName/cs/SetAccountPicture.xaml.cs b/Samples/AccountPictureName/cs/SetAccountPicture.xaml.cs
new file mode 100644
index 0000000000..a6cfa5be6f
--- /dev/null
+++ b/Samples/AccountPictureName/cs/SetAccountPicture.xaml.cs
@@ -0,0 +1,158 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using System;
+
+using System.Linq;
+using System.Collections.Generic;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.Graphics.Display;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Core;
+using Windows.Storage.Pickers;
+using Windows.Storage;
+using Windows.Storage.Streams;
+using Windows.UI.Xaml.Media.Imaging;
+using Windows.System.UserProfile;
+
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class SetAccountPicture : Page
+ {
+ MainPage rootPage = MainPage.Current;
+
+ public SetAccountPicture()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+
+ //Listen to AccountPictureChanged event
+ UserInformation.AccountPictureChanged += this.PictureChanged;
+ }
+
+ protected override void OnNavigatedFrom(NavigationEventArgs e)
+ {
+ //Remove listener to AccountPictureChanged event
+ UserInformation.AccountPictureChanged -= this.PictureChanged;
+ }
+
+ private async void SetImageButton_Click(object sender, RoutedEventArgs e)
+ {
+
+ FileOpenPicker imagePicker = new FileOpenPicker
+ {
+ ViewMode = PickerViewMode.Thumbnail,
+ SuggestedStartLocation = PickerLocationId.PicturesLibrary,
+ FileTypeFilter = { ".jpg", ".jpeg", ".png", ".bmp" }
+ };
+
+ StorageFile imageFile = await imagePicker.PickSingleFileAsync();
+ if (imageFile != null)
+ {
+ // SetAccountPictureAsync() accepts 3 storageFile objects for setting the small image, large image, and video.
+ // More than one type can be set in the same call, but a small image must be accompanied by a large image and/or video.
+ // If only a large image is passed, the small image will be autogenerated.
+ // If only a video is passed, the large image and small will be autogenerated.
+ // Videos must be convertable to mp4, <=5MB, and height and width >= 448 pixels.
+
+ // Setting the Account Picture will fail if user disallows it in PC Settings.
+ SetAccountPictureResult result = await UserInformation.SetAccountPicturesAsync(null, imageFile, null);
+ if (result == SetAccountPictureResult.Success)
+ {
+ rootPage.NotifyUser("Account picture was successfully changed.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("Account picture could not be changed.", NotifyType.StatusMessage);
+ AccountPictureImage.Visibility = Visibility.Collapsed;
+ }
+ }
+ }
+
+ private async void SetVideoButton_Click(object sender, RoutedEventArgs e)
+ {
+ FileOpenPicker videoPicker = new FileOpenPicker
+ {
+ ViewMode = PickerViewMode.Thumbnail,
+ SuggestedStartLocation = PickerLocationId.VideosLibrary,
+ FileTypeFilter = { ".mp4", ".mpeg", ".wmv", ".mov" }
+ };
+
+ StorageFile videoFile = await videoPicker.PickSingleFileAsync();
+ if (videoFile != null)
+ {
+ // SetAccountPictureAsync() accepts 3 storageFile objects for setting the small image, large image, and video.
+ // More than one type can be set in the same call, but small image must be accompanied by a large image and/or video.
+ // If only a large image is passed, the small image will be autogenerated.
+ // If only a video is passed, the large image and small will be autogenerated.
+ // Videos must be convertable to mp4, <=5MB, and height and width >= 448 pixels.
+
+ // Setting the Account Picture will fail if a user disallows it in PC Settings.
+ SetAccountPictureResult result = await UserInformation.SetAccountPicturesAsync(null, null, videoFile);
+ if (result == SetAccountPictureResult.Success)
+ {
+ rootPage.NotifyUser("Video account picture was successfully changed.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("Account picture could not be changed.", NotifyType.StatusMessage);
+ AccountPictureImage.Visibility = Visibility.Collapsed;
+ }
+ }
+ }
+
+ private async void PictureChanged(object sender, object e)
+ {
+ await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
+ {
+ // The large picture returned by GetAccountPicture() is 448x448 pixels in size.
+ StorageFile image = UserInformation.GetAccountPicture(AccountPictureKind.LargeImage) as StorageFile;
+ if (image != null)
+ {
+ try
+ {
+ IRandomAccessStream imageStream = await image.OpenReadAsync();
+ BitmapImage bitmapImage = new BitmapImage();
+ bitmapImage.SetSource(imageStream);
+ rootPage.NotifyUser("LargeImage path = " + image.Path, NotifyType.StatusMessage);
+ AccountPictureImage.Source = bitmapImage;
+ AccountPictureImage.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex)
+ {
+ rootPage.NotifyUser("Error opening stream: " + ex.ToString(), NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Large Account Picture is not available.", NotifyType.StatusMessage);
+ }
+ });
+ }
+
+ }
+}
diff --git a/Samples/AccountPictureName/cs/project.json b/Samples/AccountPictureName/cs/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/AccountPictureName/cs/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/AccountPictureName.jsproj b/Samples/AccountPictureName/js/AccountPictureName.jsproj
new file mode 100644
index 0000000000..cb9c8eac79
--- /dev/null
+++ b/Samples/AccountPictureName/js/AccountPictureName.jsproj
@@ -0,0 +1,145 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ Debug
+ ARM
+
+
+ Debug
+ x64
+
+
+ Debug
+ x86
+
+
+ Release
+ AnyCPU
+
+
+ Release
+ ARM
+
+
+ Release
+ x64
+
+
+ Release
+ x86
+
+
+
+ {9ee3ba23-05ba-402a-a8b6-f3281c3f8b2c}
+
+
+
+ 14.0
+
+
+
+
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ $(VersionNumberMajor).$(VersionNumberMinor)
+ en-US
+
+
+
+ Designer
+
+
+ css\default.css
+
+
+ default.html
+
+
+
+
+
+
+ images\microsoft-sdk.png
+
+
+ images\smallTile-sdk.png
+
+
+ images\splash-sdk.png
+
+
+ images\storeLogo-sdk.png
+
+
+ images\tile-sdk.png
+
+
+ images\windows-sdk.png
+
+
+ js\default.js
+
+
+
+
+
+
+
+ Microsoft.WinJS.4.0\css\ui-dark.css
+
+
+ Microsoft.WinJS.4.0\css\ui-light.css
+
+
+ Microsoft.WinJS.4.0\js\en-US\ui.strings.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense-setup.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense.js
+
+
+ Microsoft.WinJS.4.0\fonts\Symbols.ttf
+
+
+ Microsoft.WinJS.4.0\js\base.js
+
+
+ Microsoft.WinJS.4.0\js\ui.js
+
+
+ sample-utils\footer.html
+
+
+ sample-utils\header.html
+
+
+ sample-utils\sample-utils.js
+
+
+ sample-utils\scenario-select.css
+
+
+ sample-utils\scenario-select.html
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/AccountPictureName.sln b/Samples/AccountPictureName/js/AccountPictureName.sln
new file mode 100644
index 0000000000..2846249094
--- /dev/null
+++ b/Samples/AccountPictureName/js/AccountPictureName.sln
@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013 for Windows
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AccountPictureName", "AccountPictureName.jsproj", "{9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9EE3BA23-05BA-402A-A8B6-F3281C3F8B2C}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/css/placeholder.txt b/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/css/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/fonts/placeholder b/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/fonts/placeholder
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/js/en-US/placeholder.txt b/Samples/AccountPictureName/js/Microsoft.WinJS.4.0/js/en-US/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/js/Package.appxmanifest b/Samples/AccountPictureName/js/Package.appxmanifest
new file mode 100644
index 0000000000..0103b16e54
--- /dev/null
+++ b/Samples/AccountPictureName/js/Package.appxmanifest
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+ Account Picture Name JS Sample
+ Microsoft Corporation
+ images\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/css/placeholder.txt b/Samples/AccountPictureName/js/css/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/js/html/getAccountPicture.html b/Samples/AccountPictureName/js/html/getAccountPicture.html
new file mode 100644
index 0000000000..269a568d35
--- /dev/null
+++ b/Samples/AccountPictureName/js/html/getAccountPicture.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Get the Account Picture for the current user. You can get request three different types: small, large, and video. If the size that is requested is not available an empty file is returned.
+
+
+
+
+ Get Small Image
+
+
+ Get Large Image
+
+
+ Get Video
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/html/setAccountPicture.html b/Samples/AccountPictureName/js/html/setAccountPicture.html
new file mode 100644
index 0000000000..dbceeee048
--- /dev/null
+++ b/Samples/AccountPictureName/js/html/setAccountPicture.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the Account Picture image for the current logon user. The setAccountPicture method takes three parameters as input: small image, large image, and video. More than one type can be set in the same call, but a small image must be accompanied
+ by a large image and/or video. Pass a null for parameters you don't want to set. A change event can be listened to for Account Picture updates. The images below change by listening to the update.
+
+
+
+
+ Set image
+
+
+ Set video
+
+
+
+
+ Get Dynamic Account Picture video
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/html/userDisplayName.html b/Samples/AccountPictureName/js/html/userDisplayName.html
new file mode 100644
index 0000000000..b04d02fff0
--- /dev/null
+++ b/Samples/AccountPictureName/js/html/userDisplayName.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Get the DisplayName for the current user.
+
+
+
+
+ Get DisplayName
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/html/userFirstAndLastName.html b/Samples/AccountPictureName/js/html/userFirstAndLastName.html
new file mode 100644
index 0000000000..dff866477e
--- /dev/null
+++ b/Samples/AccountPictureName/js/html/userFirstAndLastName.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Get the First and Last Name for the current user. This is only available for Microsoft Accounts, an empty string will be returned if not available.
+
+
+
+ Get FirstName
+
+
+ Get LastName
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AccountPictureName/js/images/placeholder.txt b/Samples/AccountPictureName/js/images/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/js/js/getAccountPicture.js b/Samples/AccountPictureName/js/js/getAccountPicture.js
new file mode 100644
index 0000000000..3f09d36e5d
--- /dev/null
+++ b/Samples/AccountPictureName/js/js/getAccountPicture.js
@@ -0,0 +1,71 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/getAccountPicture.html", {
+ ready: function (element, options) {
+ hideVisibleHolders();
+ document.getElementById("getSmallImage").addEventListener("click", getSmallImage, false);
+ document.getElementById("getLargeImage").addEventListener("click", getLargeImage, false);
+ document.getElementById("getVideo").addEventListener("click", getVideo, false);
+ }
+ });
+
+ function getSmallImage() {
+ hideVisibleHolders();
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ // The small picture returned by getAccountPicture() is 96x96 pixels in size.
+ var image = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.smallImage);
+ if (image) {
+ document.getElementById("smallImageHolder").style.visibility = "visible";
+ document.getElementById("smallImageHolder").src = URL.createObjectURL(image, { oneTimeOnly: true });
+ WinJS.log && WinJS.log("Path: " + image.path, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("Small account picture is not available.", "sample", "status");
+ }
+ } else {
+ WinJS.log && WinJS.log("Access to account picture disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+
+ function getLargeImage() {
+ hideVisibleHolders();
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ // The large picture returned by getAccountPicture() is 448x448 pixels in size.
+ var image = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.largeImage);
+ if (image) {
+ document.getElementById("largeImageHolder").style.visibility = "visible";
+ document.getElementById("largeImageHolder").src = URL.createObjectURL(image, { oneTimeOnly: true });
+ WinJS.log && WinJS.log("Path: " + image.path, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("Large account picture is not available.", "sample", "status");
+ }
+ } else {
+ WinJS.log && WinJS.log("Access to account picture disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+
+ function getVideo() {
+ hideVisibleHolders();
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ // The video returned from getAccountPicture is 448x448 pixels in size.
+ var video = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.video);
+ if (video) {
+ document.getElementById("videoHolder").style.visibility = "visible";
+ document.getElementById("videoHolder").src = URL.createObjectURL(video, { oneTimeOnly: true });
+ document.getElementById("videoHolder").play();
+ WinJS.log && WinJS.log("Path: " + video.path, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("Video is not available.", "sample", "status");
+ }
+ } else {
+ WinJS.log && WinJS.log("Access to account picture disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+
+ function hideVisibleHolders() {
+ document.getElementById("smallImageHolder").style.visibility = "hidden";
+ document.getElementById("largeImageHolder").style.visibility = "hidden";
+ document.getElementById("videoHolder").style.visibility = "hidden";
+ }
+})();
diff --git a/Samples/AccountPictureName/js/js/sample-configuration.js b/Samples/AccountPictureName/js/js/sample-configuration.js
new file mode 100644
index 0000000000..de7c2f0022
--- /dev/null
+++ b/Samples/AccountPictureName/js/js/sample-configuration.js
@@ -0,0 +1,32 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+
+ var sampleTitle = "Account picture name JS sample";
+
+ var scenarios = [
+ { url: "/html/userDisplayName.html", title: "Get display name" },
+ { url: "/html/userFirstAndLastName.html", title: "Get first and last name" },
+ { url: "/html/getAccountPicture.html", title: "Get account picture" },
+ { url: "/html/setAccountPicture.html", title: "Set account picture and listen for changes" }
+ ];
+
+ WinJS.Navigation.addEventListener("navigating", function (e) {
+ if (e.detail && e.detail.state && e.detail.state.activatedEventArgs) {
+ var uri = e.detail.state.activatedEventArgs[0].uri;
+ if (uri && uri.schemeName === "ms-accountpictureprovider") {
+ // This app was activated via the Account picture apps section in Settings.
+ // Here you would do app-specific logic for providing the user with account picture selection UX
+ setImmediate(function () {
+ WinJS.Navigation.navigate(scenarios[3].url).done();
+ });
+ }
+ }
+ });
+
+ WinJS.Namespace.define("SdkSample", {
+ sampleTitle: sampleTitle,
+ scenarios: new WinJS.Binding.List(scenarios)
+ });
+})();
diff --git a/Samples/AccountPictureName/js/js/setAccountPicture.js b/Samples/AccountPictureName/js/js/setAccountPicture.js
new file mode 100644
index 0000000000..12d0d68a48
--- /dev/null
+++ b/Samples/AccountPictureName/js/js/setAccountPicture.js
@@ -0,0 +1,102 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/setAccountPicture.html", {
+ ready: function (element, options) {
+ hideVisibleHolders();
+ document.getElementById("setImage").addEventListener("click", setImage, false);
+ document.getElementById("setVideo").addEventListener("click", setVideo, false);
+ Windows.System.UserProfile.UserInformation.addEventListener("accountpicturechanged", accountPictureChanged);
+ }
+ });
+
+ function setImage() {
+ hideVisibleHolders();
+ var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
+ openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
+ openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
+ openPicker.fileTypeFilter.replaceAll([".bmp", ".png", ".jpg", ".jpeg"]);
+
+ openPicker.pickSingleFileAsync().done(function (file) {
+ if (file) {
+ // setAccountPictureAsync() accepts 3 storageFile objects for setting the small image, large image, and video.
+ // More than one type can be set in the same call, but small image must be accompanied by a large image and/or video.
+ // If only a large image is passed, the small image will be autogenerated.
+ // If only a video is passed, the large image and small will be autogenerated.
+ // Videos must be convertable to mp4, <=5MB, and height and width >= 448 pixels.
+ Windows.System.UserProfile.UserInformation.setAccountPicturesAsync(null, file, null).done(function (result) {
+ // A user might turn off access to the Account Picture in PC Settings, therefore we need to check the result for success.
+ if (result === Windows.System.UserProfile.SetAccountPictureResult.success) {
+ WinJS.log && WinJS.log("Successfully updated account picture.", "sample", "status");
+ } else {
+ // A user might turn off access to the account
+ WinJS.log && WinJS.log("Setting account picture failed.", "sample", "status");
+ }
+ });
+ } else {
+ WinJS.log && WinJS.log("No image was selected.", "sample", "status");
+ }
+ });
+ }
+
+ function setVideo() {
+ hideVisibleHolders();
+ var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
+ openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
+ openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
+ openPicker.fileTypeFilter.replaceAll([".mov", ".mp4", ".wmv"]);
+
+ openPicker.pickSingleFileAsync().done(function (file) {
+ if (file) {
+ // setAccountPictureAsync() accepts 3 storageFile objects for setting the small image, large image, and video.
+ // More than one type can be set in the same call, but small image must be accompanied by a large image and/or video.
+ // If only a large image is passed, the small image will be autogenerated.
+ // If only a video is passed, the large image and small will be autogenerated.
+ // Videos must be convertable to mp4, <=5MB, and height and width >= 448 pixels.
+ Windows.System.UserProfile.UserInformation.setAccountPicturesAsync(null, null, file).done(function (result) {
+ // A user might turn off access to the Account Picture in PC Settings, therefore we need to check the result for success.
+ if (result === Windows.System.UserProfile.SetAccountPictureResult.success) {
+ WinJS.log && WinJS.log("Successfully updated account picture.", "sample", "status");
+ } else {
+ // A user might turn off access to the account
+ WinJS.log && WinJS.log("Setting account picture failed.", "sample", "status");
+ }
+ });
+ } else {
+ WinJS.log && WinJS.log("No video was selected.", "sample", "status");
+ }
+ });
+ }
+
+ // This function is the handler for the AccountPictureChangedEvent, the event listener is added in initialize() below.
+ function accountPictureChanged() {
+ hideVisibleHolders();
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ var smallImage = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.smallImage);
+ if (smallImage) {
+ document.getElementById("smallImageHolder").src = URL.createObjectURL(smallImage, { oneTimeOnly: true });
+ document.getElementById("smallImageHolder").style.visibility = "visible";
+ }
+ var largeImage = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.largeImage);
+ if (largeImage) {
+ document.getElementById("largeImageHolder").src = URL.createObjectURL(largeImage, { oneTimeOnly: true });
+ document.getElementById("largeImageHolder").style.visibility = "visible";
+ }
+ var video = Windows.System.UserProfile.UserInformation.getAccountPicture(Windows.System.UserProfile.AccountPictureKind.video);
+ if (video) {
+ document.getElementById("videoHolder").src = URL.createObjectURL(video, { oneTimeOnly: true });
+ document.getElementById("videoHolder").style.visibility = "visible";
+ }
+ } else {
+ WinJS.log && WinJS.log("Access to account picture disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+
+ function hideVisibleHolders() {
+ document.getElementById("smallImageHolder").style.visibility = "hidden";
+ document.getElementById("largeImageHolder").style.visibility = "hidden";
+ document.getElementById("videoHolder").style.visibility = "hidden";
+ WinJS.log && WinJS.log(" ", "sample", "status");
+ }
+})();
diff --git a/Samples/AccountPictureName/js/js/userDisplayName.js b/Samples/AccountPictureName/js/js/userDisplayName.js
new file mode 100644
index 0000000000..040dbdfda3
--- /dev/null
+++ b/Samples/AccountPictureName/js/js/userDisplayName.js
@@ -0,0 +1,24 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/userDisplayName.html", {
+ ready: function (element, options) {
+ document.getElementById("getDisplayName").addEventListener("click", getDisplayName, false);
+ }
+ });
+
+ function getDisplayName() {
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ Windows.System.UserProfile.UserInformation.getDisplayNameAsync().done(function (result) {
+ if (result) {
+ WinJS.log && WinJS.log("Display name = " + result, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("No display name was returned.", "sample", "status");
+ }
+ });
+ } else {
+ WinJS.log && WinJS.log("Access to name disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+})();
diff --git a/Samples/AccountPictureName/js/js/userFirstAndLastName.js b/Samples/AccountPictureName/js/js/userFirstAndLastName.js
new file mode 100644
index 0000000000..b2e2e66d10
--- /dev/null
+++ b/Samples/AccountPictureName/js/js/userFirstAndLastName.js
@@ -0,0 +1,39 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/userFirstAndLastName.html", {
+ ready: function (element, options) {
+ document.getElementById("getFirstName").addEventListener("click", getFirstName, false);
+ document.getElementById("getLastName").addEventListener("click", getLastName, false);
+ }
+ });
+
+ function getFirstName() {
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ Windows.System.UserProfile.UserInformation.getFirstNameAsync().done(function (result) {
+ if (result) {
+ WinJS.log && WinJS.log("First name = " + result, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("No first name was returned.", "sample", "status");
+ }
+ });
+ } else {
+ WinJS.log && WinJS.log("Access to name disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+
+ function getLastName() {
+ if (Windows.System.UserProfile.UserInformation.nameAccessAllowed) {
+ Windows.System.UserProfile.UserInformation.getLastNameAsync().done(function (result) {
+ if (result) {
+ WinJS.log && WinJS.log("Last name = " + result, "sample", "status");
+ } else {
+ WinJS.log && WinJS.log("No last name was returned.", "sample", "status");
+ }
+ });
+ } else {
+ WinJS.log && WinJS.log("Access to name disabled by Privacy Setting or Group Policy.", "sample", "error");
+ }
+ }
+})();
diff --git a/Samples/AccountPictureName/js/sample-utils/placeholder.txt b/Samples/AccountPictureName/js/sample-utils/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AccountPictureName/shared/GetAccountPicture.xaml b/Samples/AccountPictureName/shared/GetAccountPicture.xaml
new file mode 100644
index 0000000000..96bd210cb6
--- /dev/null
+++ b/Samples/AccountPictureName/shared/GetAccountPicture.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get the Account Picture for the current user.
+
+
+
+
+
+
+ You can request three different types: small, large and video (dynamic image). If the type that is requested is not available, an empty file is returned.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AccountPictureName/shared/GetUserDisplayName.xaml b/Samples/AccountPictureName/shared/GetUserDisplayName.xaml
new file mode 100644
index 0000000000..822e975c1a
--- /dev/null
+++ b/Samples/AccountPictureName/shared/GetUserDisplayName.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get the display name for the current user.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AccountPictureName/shared/GetUserFirstAndLastName.xaml b/Samples/AccountPictureName/shared/GetUserFirstAndLastName.xaml
new file mode 100644
index 0000000000..37cc636fb0
--- /dev/null
+++ b/Samples/AccountPictureName/shared/GetUserFirstAndLastName.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Get the first and last name for the current user. This is only available for Microsoft Accounts. An empty string will be returned if not available.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AccountPictureName/shared/SetAccountPicture.xaml b/Samples/AccountPictureName/shared/SetAccountPicture.xaml
new file mode 100644
index 0000000000..54929d5c64
--- /dev/null
+++ b/Samples/AccountPictureName/shared/SetAccountPicture.xaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Set the Account Picture for the current logon user.
+
+
+
+
+
+
+ The SetAccountPicture method takes three parameters as input:
+ small image, large image, and video.
+ More than one type can be set in the same call,
+ but a small image must be accompanied by a large image and/or video.
+ Pass a null for parameters you don't want to set.
+ A change event can be listened to for Account Picture updates.
+ The images below change by listening to the update.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/ActivitySensor/README.md b/Samples/ActivitySensor/README.md
new file mode 100644
index 0000000000..f880f4dd18
--- /dev/null
+++ b/Samples/ActivitySensor/README.md
@@ -0,0 +1,57 @@
+
+
+# Activity Detection Sensor sample
+
+This sample demonstrates the use of the Windows.Devices.Sensors.ActivitySensor API.
+
+This sample allows the user to interact with the activity detection functionality on the system. You can choose one of four scenarios:
+
+- Current activity
+- History
+- Events
+- Background activity
+
+### Current activity
+
+Gets the default activity sensor and displays the current activity.
+
+### History
+
+Gets the activity history from at most 1 day ago. Displays the first entry, last entry, and count of entries.
+
+### Events
+
+Subscribes to reading changed events and displays the updated activity reading.
+
+### Background activity
+
+Registers a background task for activity changes. The background task runs whenever the most likely activity changes to/from any of the subscribed activities.
+
+## System requirements
+
+**Client:** Windows 10
+
+**Server:** Windows Server 2016 Technical Preview
+
+**Phone:** Windows 10
+
+## Build the sample
+
+1. Start Microsoft Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C++ or C#. Double-click the Visual Studio 2015 Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+## Run the sample
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+### Deploying the sample
+
+- Select Build > Deploy Solution.
+
+### Deploying and running the sample
+
+- To debug the sample and then run it, press F5 or select Debug > Start Debugging. To run the sample without debugging, press Ctrl+F5 or selectDebug > Start Without Debugging.
+
diff --git a/Samples/ActivitySensor/cpp/ActivitySensor.sln b/Samples/ActivitySensor/cpp/ActivitySensor.sln
new file mode 100644
index 0000000000..c33fdf8e57
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/ActivitySensor.sln
@@ -0,0 +1,57 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22418.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActivitySensor", "ActivitySensor.vcxproj", "{F710B9FD-4E6B-42D7-A99A-6D48888D48B0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ActivitySensorTasks", "Tasks\ActivitySensorTasks.vcxproj", "{1F4BC306-A3EC-4DEB-B545-0B55673243CE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|ARM = Release|ARM
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.ActiveCfg = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.Build.0 = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|ARM.Deploy.0 = Debug|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.Build.0 = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|Win32.Deploy.0 = Debug|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.ActiveCfg = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.Build.0 = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Debug|x64.Deploy.0 = Debug|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.ActiveCfg = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.Build.0 = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|ARM.Deploy.0 = Release|ARM
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.ActiveCfg = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.Build.0 = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|Win32.Deploy.0 = Release|Win32
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.ActiveCfg = Release|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.Build.0 = Release|x64
+ {F710B9FD-4E6B-42D7-A99A-6D48888D48B0}.Release|x64.Deploy.0 = Release|x64
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|ARM.ActiveCfg = Debug|ARM
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|ARM.Build.0 = Debug|ARM
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|Win32.Build.0 = Debug|Win32
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|x64.ActiveCfg = Debug|x64
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Debug|x64.Build.0 = Debug|x64
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|ARM.ActiveCfg = Release|ARM
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|ARM.Build.0 = Release|ARM
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|ARM.Deploy.0 = Release|ARM
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|Win32.ActiveCfg = Release|Win32
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|Win32.Build.0 = Release|Win32
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|Win32.Deploy.0 = Release|Win32
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|x64.ActiveCfg = Release|x64
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|x64.Build.0 = Release|x64
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}.Release|x64.Deploy.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj b/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj
new file mode 100644
index 0000000000..1bb8155c31
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj
@@ -0,0 +1,241 @@
+
+
+
+ {f710b9fd-4e6b-42d7-a99a-6d48888d48b0}
+ SDKTemplate
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.10240.0
+ 10.0.10240.0
+ true
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+ Application
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\..\SharedContent\cpp
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+
+ Scenario1_CurrentActivity.xaml
+
+
+ Scenario2_History.xaml
+
+
+ Scenario3_ChangeEvents.xaml
+
+
+ Scenario4_BackgroundActivity.xaml
+
+
+
+
+ Designer
+
+
+ Designer
+
+
+
+
+
+
+ Styles\Styles.xaml
+
+
+
+
+ Designer
+
+
+
+
+ ..\..\..\SharedContent\xaml\App.xaml
+
+
+ ..\..\..\SharedContent\cpp\MainPage.xaml
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+ Scenario1_CurrentActivity.xaml
+
+
+ Scenario2_History.xaml
+
+
+ Scenario3_ChangeEvents.xaml
+
+
+ Scenario4_BackgroundActivity.xaml
+
+
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smalltile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squaretile-sdk.png
+
+
+ Assets\storelogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ {1f4bc306-a3ec-4deb-b545-0b55673243ce}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj.filters b/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj.filters
new file mode 100644
index 0000000000..fdac2af79d
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/ActivitySensor.vcxproj.filters
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+ Assets
+
+
+
+
+
+
+
+
+
+
+
+
+ Styles
+
+
+
+
+ {5e4a576d-09b3-4eb6-95f4-3fb7a6dd1bee}
+
+
+ {2f749119-c98d-4e84-a99b-4aaeeb8c208e}
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Package.appxmanifest b/Samples/ActivitySensor/cpp/Package.appxmanifest
new file mode 100644
index 0000000000..2f991dbf3c
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Package.appxmanifest
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+ ActivitySensorCPP
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/SampleConfiguration.cpp b/Samples/ActivitySensor/cpp/SampleConfiguration.cpp
new file mode 100644
index 0000000000..cac50d4f1c
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/SampleConfiguration.cpp
@@ -0,0 +1,24 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#include "pch.h"
+#include "MainPage.xaml.h"
+#include "SampleConfiguration.h"
+
+using namespace SDKTemplate;
+
+Platform::Array^ MainPage::scenariosInner = ref new Platform::Array
+{
+ { "Current activity", "SDKTemplate.Scenario1_CurrentActivity" },
+ { "Activity history", "SDKTemplate.Scenario2_History" },
+ { "Events", "SDKTemplate.Scenario3_ChangeEvents" },
+ { "Background activity", "SDKTemplate.Scenario4_BackgroundActivity" }
+};
diff --git a/Samples/ActivitySensor/cpp/SampleConfiguration.h b/Samples/ActivitySensor/cpp/SampleConfiguration.h
new file mode 100644
index 0000000000..12012ea55b
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/SampleConfiguration.h
@@ -0,0 +1,47 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+#pragma once
+#include "pch.h"
+
+namespace SDKTemplate
+{
+ value struct Scenario;
+
+ partial ref class MainPage
+ {
+ internal:
+ static property Platform::String^ FEATURE_NAME
+ {
+ Platform::String^ get()
+ {
+ return "ActivitySensor";
+ }
+ }
+
+ static property Platform::Array^ scenarios
+ {
+ Platform::Array^ get()
+ {
+ return scenariosInner;
+ }
+ }
+
+ private:
+ static Platform::Array^ scenariosInner;
+ };
+
+ public value struct Scenario
+ {
+ Platform::String^ Title;
+ Platform::String^ ClassName;
+ };
+}
diff --git a/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml
new file mode 100644
index 0000000000..b0ea6db033
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.cpp b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.cpp
new file mode 100644
index 0000000000..b50c81db57
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.cpp
@@ -0,0 +1,87 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario1_CurrentActivity.xaml.cpp
+// Implementation of the Scenario1_CurrentActivity class
+//
+
+#include "pch.h"
+#include "Scenario1_CurrentActivity.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Concurrency;
+using namespace Platform;
+using namespace Windows::Devices::Enumeration;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+
+Scenario1_CurrentActivity::Scenario1_CurrentActivity() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+}
+
+void Scenario1_CurrentActivity::ScenarioGetCurrentActivity(Object^ sender, RoutedEventArgs^ e)
+{
+ // Reset fields and status
+ ScenarioOutput_Activity->Text = "No data";
+ ScenarioOutput_Confidence->Text = "No data";
+ ScenarioOutput_Timestamp->Text = "No data";
+ rootPage->NotifyUser("", NotifyType::StatusMessage);
+
+ // Determine if we can access activity sensors
+ auto deviceAccessInfo = DeviceAccessInformation::CreateFromDeviceClassId(GUID_ActivitySensor_ClassId);
+ if (deviceAccessInfo->CurrentStatus == DeviceAccessStatus::Allowed)
+ {
+ // Get the default activity sensor
+ create_task(ActivitySensor::GetDefaultAsync()).then([this](ActivitySensor^ activitySensor)
+ {
+ if (activitySensor != nullptr)
+ {
+ create_task(activitySensor->GetCurrentReadingAsync()).then([this](task task)
+ {
+ try
+ {
+ auto reading = task.get();
+ if (reading != nullptr)
+ {
+ ScenarioOutput_Activity->Text = reading->Activity.ToString();
+ ScenarioOutput_Confidence->Text = reading->Confidence.ToString();
+
+ auto timestampFormatter = ref new DateTimeFormatter("day month year hour minute second");
+ ScenarioOutput_Timestamp->Text = timestampFormatter->Format(reading->Timestamp);
+ }
+ }
+ catch (Platform::COMException ^ e)
+ {
+ // Some activity sensors may occassionally time out when determining the initial
+ // reading. If this happens frequently, use events instead of GetCurrentReadingAsync.
+ rootPage->NotifyUser("Could not get the current reading (likely a timeout)", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No activity sensors found", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access denied to activity sensors", NotifyType::ErrorMessage);
+ }
+}
+
diff --git a/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.h b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.h
new file mode 100644
index 0000000000..96024ea453
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario1_CurrentActivity.xaml.h
@@ -0,0 +1,39 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario1_CurrentActivity.xaml.h
+// Declaration of the Scenario1_CurrentActivity class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario1_CurrentActivity.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario1_CurrentActivity sealed
+ {
+ public:
+ Scenario1_CurrentActivity();
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+
+ void ScenarioGetCurrentActivity(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Scenario2_History.xaml b/Samples/ActivitySensor/cpp/Scenario2_History.xaml
new file mode 100644
index 0000000000..6b82d5bfc7
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario2_History.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Scenario2_History.xaml.cpp b/Samples/ActivitySensor/cpp/Scenario2_History.xaml.cpp
new file mode 100644
index 0000000000..f4e93e6aa9
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario2_History.xaml.cpp
@@ -0,0 +1,102 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario2_History.xaml.cpp
+// Implementation of the Scenario2_History class
+//
+
+#include "pch.h"
+#include "Scenario2_History.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Concurrency;
+using namespace Platform;
+using namespace Windows::Devices::Enumeration;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Globalization;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+
+Scenario2_History::Scenario2_History() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+
+ ScenarioGetActivityHistoryButton->IsEnabled = false;
+
+ // Determine if we can access activity sensors
+ auto deviceAccessInfo = DeviceAccessInformation::CreateFromDeviceClassId(GUID_ActivitySensor_ClassId);
+ if (deviceAccessInfo->CurrentStatus == DeviceAccessStatus::Allowed)
+ {
+ // Determine if an activity sensor is present
+ // This can also be done using Windows::Devices::Enumeration::DeviceInformation::FindAllAsync
+ create_task(ActivitySensor::GetDefaultAsync).then([this](task task)
+ {
+ auto activitySensor = task.get();
+ if (nullptr == activitySensor)
+ {
+ rootPage->NotifyUser("No activity sensors found", NotifyType::ErrorMessage);
+ }
+ else
+ {
+ ScenarioGetActivityHistoryButton->IsEnabled = true;
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access to activity sensors is denied", NotifyType::ErrorMessage);
+ }
+}
+
+void Scenario2_History::ScenarioGetActivityHistory(Object^ sender, RoutedEventArgs^ e)
+{
+ // Reset fields and status
+ ScenarioOutput_Count->Text = "No data";
+ ScenarioOutput_Activity1->Text = "No data";
+ ScenarioOutput_Confidence1->Text = "No data";
+ ScenarioOutput_Timestamp1->Text = "No data";
+ ScenarioOutput_ActivityN->Text = "No data";
+ ScenarioOutput_ConfidenceN->Text = "No data";
+ ScenarioOutput_TimestampN->Text = "No data";
+ rootPage->NotifyUser("", NotifyType::StatusMessage);
+
+ auto calendar = ref new Calendar();
+ calendar->SetToNow();
+ calendar->AddDays(-1);
+ auto yesterday = calendar->GetDateTime();
+
+ // Get history from yesterday onwards
+ create_task(ActivitySensor::GetSystemHistoryAsync(yesterday)).then([this](IVectorView^ history)
+ {
+ ScenarioOutput_Count->Text = history->Size.ToString();
+ if (history->Size > 0)
+ {
+ auto reading1 = history->GetAt(0);
+ ScenarioOutput_Activity1->Text = reading1->Activity.ToString();
+ ScenarioOutput_Confidence1->Text = reading1->Confidence.ToString();
+
+ auto timestampFormatter = ref new DateTimeFormatter("day month year hour minute second");
+ ScenarioOutput_Timestamp1->Text = timestampFormatter->Format(reading1->Timestamp);
+
+ auto readingN = history->GetAt(history->Size - 1);
+ ScenarioOutput_ActivityN->Text = readingN->Activity.ToString();
+ ScenarioOutput_ConfidenceN->Text = readingN->Confidence.ToString();
+ ScenarioOutput_TimestampN->Text = timestampFormatter->Format(readingN->Timestamp);
+ }
+ });
+}
+
diff --git a/Samples/ActivitySensor/cpp/Scenario2_History.xaml.h b/Samples/ActivitySensor/cpp/Scenario2_History.xaml.h
new file mode 100644
index 0000000000..3c27a95aa9
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario2_History.xaml.h
@@ -0,0 +1,39 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario2_History.xaml.h
+// Declaration of the Scenario2_History class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario2_History.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario2_History sealed
+ {
+ public:
+ Scenario2_History();
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+
+ void ScenarioGetActivityHistory(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ };
+}
diff --git a/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml
new file mode 100644
index 0000000000..2bb4386909
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.cpp b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.cpp
new file mode 100644
index 0000000000..e8d16d2c84
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.cpp
@@ -0,0 +1,200 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario3_ChangeEvents.xaml.cpp
+// Implementation of the Scenario3_ChangeEvents class
+//
+
+#include "pch.h"
+#include "Scenario3_ChangeEvents.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Concurrency;
+using namespace Platform;
+using namespace Windows::Devices::Enumeration;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+
+Scenario3_ChangeEvents::Scenario3_ChangeEvents() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+
+ // Register for access changed notifications for activity sensors
+ m_deviceAccessInfo = DeviceAccessInformation::CreateFromDeviceClassId(GUID_ActivitySensor_ClassId);
+ m_deviceAccessInfo->AccessChanged += ref new TypedEventHandler(this, &Scenario3_ChangeEvents::AccessChanged);
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario3_ChangeEvents::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ ScenarioEnableReadingChangedButton->IsEnabled = true;
+ ScenarioDisableReadingChangedButton->IsEnabled = false;
+}
+
+///
+/// Invoked when this page is no longer displayed.
+///
+///
+void Scenario3_ChangeEvents::OnNavigatedFrom(NavigationEventArgs^ e)
+{
+ // If the navigation is external to the app do not clean up.
+ // This can occur on Phone when suspending the app.
+ if (e->NavigationMode == NavigationMode::Forward && e->Uri == nullptr)
+ {
+ return;
+ }
+
+ if (ScenarioDisableReadingChangedButton->IsEnabled)
+ {
+ if (m_activitySensor != nullptr)
+ {
+ m_activitySensor->ReadingChanged::remove(m_readingToken);
+ m_readingToken = {};
+ }
+ }
+}
+
+///
+/// This is the event handler for ReadingChanged events.
+///
+///
+///
+void Scenario3_ChangeEvents::ReadingChanged(ActivitySensor^ sender, ActivitySensorReadingChangedEventArgs^ e)
+{
+ // We need to dispatch to the UI thread to display the output
+ Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, e]()
+ {
+ ActivitySensorReading^ reading = e->Reading;
+
+ ScenarioOutput_Activity->Text = reading->Activity.ToString();
+ ScenarioOutput_Confidence->Text = reading->Confidence.ToString();
+
+ auto timestampFormatter = ref new DateTimeFormatter("day month year hour minute second");
+ ScenarioOutput_ReadingTimestamp->Text = timestampFormatter->Format(reading->Timestamp);
+ }));
+}
+
+///
+/// This is the click handler for the 'Reading Changed On' button.
+///
+///
+///
+void Scenario3_ChangeEvents::ScenarioEnableReadingChanged(Object^ sender, RoutedEventArgs^ e)
+{
+ // Determine if we can access activity sensors
+ if (m_deviceAccessInfo->CurrentStatus == DeviceAccessStatus::Allowed)
+ {
+ create_task(GetActivitySensorAsync()).then([this](ActivitySensor^ sensor)
+ {
+ m_activitySensor = sensor;
+ if (m_activitySensor != nullptr)
+ {
+ m_activitySensor->SubscribedActivities->Append(ActivityType::Walking);
+ m_activitySensor->SubscribedActivities->Append(ActivityType::Running);
+ m_activitySensor->SubscribedActivities->Append(ActivityType::InVehicle);
+ m_activitySensor->SubscribedActivities->Append(ActivityType::Biking);
+ m_activitySensor->SubscribedActivities->Append(ActivityType::Fidgeting);
+
+ m_readingToken = m_activitySensor->ReadingChanged::add(
+ ref new TypedEventHandler(this,
+ &Scenario3_ChangeEvents::ReadingChanged));
+
+ // Update the buttons in the UI thread
+ Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]()
+ {
+ ScenarioEnableReadingChangedButton->IsEnabled = false;
+ ScenarioDisableReadingChangedButton->IsEnabled = true;
+ rootPage->NotifyUser("Subscribed to reading changes", NotifyType::StatusMessage);
+ }));
+ }
+ else
+ {
+ rootPage->NotifyUser("No activity sensors found", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access denied to activity sensors", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// This is the click handler for the 'Reading Changed Off' button.
+///
+///
+///
+void Scenario3_ChangeEvents::ScenarioDisableReadingChanged(Object^ sender, RoutedEventArgs^ e)
+{
+ if (m_activitySensor != nullptr)
+ {
+ m_activitySensor->ReadingChanged::remove(m_readingToken);
+ rootPage->NotifyUser("Unsubscribed from reading changes", NotifyType::StatusMessage);
+ }
+ m_readingToken = {};
+
+ ScenarioEnableReadingChangedButton->IsEnabled = true;
+ ScenarioDisableReadingChangedButton->IsEnabled = false;
+}
+
+///
+/// Invoked when the access to pedometers has changed
+///
+///
+///
+void Scenario3_ChangeEvents::AccessChanged(DeviceAccessInformation ^sender, DeviceAccessChangedEventArgs ^args)
+{
+ if (args->Status != DeviceAccessStatus::Allowed)
+ {
+ m_activitySensor = nullptr;
+
+ Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(
+ [this]()
+ {
+ ScenarioEnableReadingChangedButton->IsEnabled = true;
+ ScenarioDisableReadingChangedButton->IsEnabled = false;
+
+ rootPage->NotifyUser("Access to the activity sensor has been denied", NotifyType::ErrorMessage);
+ },
+ CallbackContext::Any));
+ }
+}
+
+///
+/// A helper function to return the activity sensor asynchronously.
+///
+task Scenario3_ChangeEvents::GetActivitySensorAsync()
+{
+ if (nullptr == m_activitySensor)
+ {
+ return create_task(ActivitySensor::GetDefaultAsync());
+ }
+ else
+ {
+ return create_task([this]() -> ActivitySensor^
+ {
+ return m_activitySensor;
+ });
+ }
+}
diff --git a/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.h b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.h
new file mode 100644
index 0000000000..3088acad06
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario3_ChangeEvents.xaml.h
@@ -0,0 +1,51 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario3_ChangeEvents.xaml.h
+// Declaration of the Scenario3_ChangeEvents class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario3_ChangeEvents.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario3_ChangeEvents sealed
+ {
+ public:
+ Scenario3_ChangeEvents();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+ virtual void OnNavigatedFrom(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ Windows::Devices::Enumeration::DeviceAccessInformation^ m_deviceAccessInfo;
+ Windows::Devices::Sensors::ActivitySensor^ m_activitySensor;
+ Windows::Foundation::EventRegistrationToken m_readingToken;
+
+ void ReadingChanged(Windows::Devices::Sensors::ActivitySensor^ sender, Windows::Devices::Sensors::ActivitySensorReadingChangedEventArgs^ e);
+ void ScenarioEnableReadingChanged(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioDisableReadingChanged(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void AccessChanged(Windows::Devices::Enumeration::DeviceAccessInformation ^sender, Windows::Devices::Enumeration::DeviceAccessChangedEventArgs ^args);
+
+ Concurrency::task GetActivitySensorAsync();
+ };
+}
diff --git a/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml
new file mode 100644
index 0000000000..7ecab01340
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.cpp b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.cpp
new file mode 100644
index 0000000000..abb86ea49d
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.cpp
@@ -0,0 +1,204 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario4_BackgroundActivity.xaml.cpp
+// Implementation of the Scenario4_BackgroundActivity class
+//
+
+#include "pch.h"
+#include "Scenario4_BackgroundActivity.xaml.h"
+
+using namespace SDKTemplate;
+
+using namespace Concurrency;
+using namespace Platform;
+using namespace Windows::ApplicationModel::Background;
+using namespace Windows::Devices::Enumeration;
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Storage;
+using namespace Windows::UI::Core;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Navigation;
+
+Scenario4_BackgroundActivity::Scenario4_BackgroundActivity() : rootPage(MainPage::Current)
+{
+ InitializeComponent();
+}
+
+///
+/// Invoked when this page is about to be displayed in a Frame.
+///
+/// Event data that describes how this page was reached. The Parameter
+/// property is typically used to configure the page.
+void Scenario4_BackgroundActivity::OnNavigatedTo(NavigationEventArgs^ e)
+{
+ for (const auto& cur : BackgroundTaskRegistration::AllTasks)
+ {
+ auto registration = dynamic_cast(cur->Value);
+ if (SampleBackgroundTaskName == registration->Name)
+ {
+ registered = true;
+ break;
+ }
+ }
+
+ UpdateUIAsync(registered ? "Registered" : "Unregistered");
+}
+
+///
+/// This is the click handler for the 'Register Task' button.
+///
+///
+///
+void Scenario4_BackgroundActivity::ScenarioRegisterTask(Object^ sender, RoutedEventArgs^ e)
+{
+ // Determine if we can access activity sensors
+ auto deviceAccessInfo = DeviceAccessInformation::CreateFromDeviceClassId(GUID_ActivitySensor_ClassId);
+ if (deviceAccessInfo->CurrentStatus == DeviceAccessStatus::Allowed)
+ {
+ // Determine if an activity sensor is present
+ // This can also be done using Windows::Devices::Enumeration::DeviceInformation::FindAllAsync
+ create_task(ActivitySensor::GetDefaultAsync).then([this](ActivitySensor^ sensor)
+ {
+ if (nullptr != sensor)
+ {
+ create_task(BackgroundExecutionManager::RequestAccessAsync()).then([this](BackgroundAccessStatus status)
+ {
+ if ((BackgroundAccessStatus::AllowedWithAlwaysOnRealTimeConnectivity == status) ||
+ (BackgroundAccessStatus::AllowedMayUseActiveRealTimeConnectivity == status))
+ {
+ RegisterBackgroundTask();
+ }
+ else
+ {
+ rootPage->NotifyUser("Background tasks may be disabled for this app", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("No activity sensors found", NotifyType::ErrorMessage);
+ }
+ });
+ }
+ else
+ {
+ rootPage->NotifyUser("Access denied to activity sensors", NotifyType::ErrorMessage);
+ }
+}
+
+///
+/// This is the click handler for the 'Unregister Task' button.
+///
+///
+///
+void Scenario4_BackgroundActivity::ScenarioUnregisterTask(Object^ sender, RoutedEventArgs^ e)
+{
+ // Loop through all background tasks and unregister any with SampleBackgroundTaskName
+ for (const auto& cur : BackgroundTaskRegistration::AllTasks)
+ {
+ auto registration = dynamic_cast(cur->Value);
+ if (SampleBackgroundTaskName == registration->Name)
+ {
+ registration->Unregister(true /*cancelTask*/);
+ registered = false;
+ }
+ }
+
+ if (!registered)
+ {
+ UpdateUIAsync("Unregistered");
+ }
+}
+
+///
+/// This is the event handler for background task completion.
+///
+/// The task that is reporting completion.
+/// The completion report arguments.
+void Scenario4_BackgroundActivity::OnCompleted(BackgroundTaskRegistration^ task, BackgroundTaskCompletedEventArgs^ args)
+{
+ String^ status = "Completed";
+ try
+ {
+ args->CheckResult();
+ }
+ catch (Exception^ e)
+ {
+ status = e->Message;
+ }
+ UpdateUIAsync(status);
+}
+
+///
+/// Registers the background task.
+///
+void Scenario4_BackgroundActivity::RegisterBackgroundTask()
+{
+ auto builder = ref new BackgroundTaskBuilder();
+ builder->Name = SampleBackgroundTaskName;
+ builder->TaskEntryPoint = SampleBackgroundTaskEntryPoint;
+
+ const unsigned int reportIntervalMs = 3000; // 3 seconds
+ auto trigger = ref new ActivitySensorTrigger(reportIntervalMs);
+
+ trigger->SubscribedActivities->Append(ActivityType::Walking);
+ trigger->SubscribedActivities->Append(ActivityType::Running);
+ trigger->SubscribedActivities->Append(ActivityType::Biking);
+
+ builder->SetTrigger(trigger);
+
+ auto task = builder->Register();
+ task->Completed += ref new BackgroundTaskCompletedEventHandler(this, &Scenario4_BackgroundActivity::OnCompleted);
+
+ registered = true;
+ UpdateUIAsync("Registered");
+}
+
+///
+/// Updates the scenario UI.
+///
+/// The status string to display.
+void Scenario4_BackgroundActivity::UpdateUIAsync(String^ status)
+{
+ // Update the buttons in the UI thread
+ Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, status]()
+ {
+ ScenarioRegisterTaskButton->IsEnabled = !registered;
+ ScenarioUnregisterTaskButton->IsEnabled = registered;
+ ScenarioOutput_TaskRegistration->Text = status;
+
+ auto settings = ApplicationData::Current->LocalSettings;
+
+ if (settings->Values->HasKey("ReportCount"))
+ {
+ ScenarioOutput_ReportCount->Text = safe_cast(settings->Values->Lookup("ReportCount")); // stored as a string
+ }
+ if (settings->Values->HasKey("TaskStatus"))
+ {
+ ScenarioOutput_TaskStatus->Text = safe_cast(settings->Values->Lookup("TaskStatus")); // stored as a string
+ }
+ if (settings->Values->HasKey("LastActivity"))
+ {
+ ScenarioOutput_LastActivity->Text = safe_cast(settings->Values->Lookup("LastActivity")); // stored as a string
+ }
+ if (settings->Values->HasKey("LastConfidence"))
+ {
+ ScenarioOutput_LastConfidence->Text = safe_cast(settings->Values->Lookup("LastConfidence")); // stored as a string
+ }
+ if (settings->Values->HasKey("LastTimestamp"))
+ {
+ ScenarioOutput_LastTimestamp->Text = safe_cast(settings->Values->Lookup("LastTimestamp")); // stored as a string
+ }
+ }));
+}
diff --git a/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.h b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.h
new file mode 100644
index 0000000000..1471149647
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Scenario4_BackgroundActivity.xaml.h
@@ -0,0 +1,50 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// Scenario4_BackgroundActivity.xaml.h
+// Declaration of the Scenario4_BackgroundActivity class
+//
+
+#pragma once
+
+#include "pch.h"
+#include "Scenario4_BackgroundActivity.g.h"
+#include "MainPage.xaml.h"
+
+namespace SDKTemplate
+{
+ static Platform::String^ SampleBackgroundTaskName = "ActivitySensorBackgroundTask";
+ static Platform::String^ SampleBackgroundTaskEntryPoint = "Tasks.ActivitySensorBackgroundTask";
+
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class Scenario4_BackgroundActivity sealed
+ {
+ public:
+ Scenario4_BackgroundActivity();
+
+ protected:
+ virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
+
+ private:
+ SDKTemplate::MainPage^ rootPage;
+ bool registered;
+
+ void ScenarioRegisterTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void ScenarioUnregisterTask(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
+ void OnCompleted(Windows::ApplicationModel::Background::BackgroundTaskRegistration^ task, Windows::ApplicationModel::Background::BackgroundTaskCompletedEventArgs^ args);
+ void RegisterBackgroundTask();
+ void UpdateUIAsync(Platform::String^ status);
+ };
+}
diff --git a/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.cpp b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.cpp
new file mode 100644
index 0000000000..ae3dae2c14
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.cpp
@@ -0,0 +1,79 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// ActivitySensorBackgroundTask.cpp
+// Implementation of the ActivitySensorBackgroundTask class
+//
+
+#include "pch.h"
+#include "ActivitySensorBackgroundTask.h"
+
+using namespace Windows::Devices::Sensors;
+using namespace Windows::Foundation;
+using namespace Windows::Globalization;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::Storage;
+
+using namespace Tasks;
+
+///
+/// The entry point of a background task.
+///
+/// The current background task instance.
+void ActivitySensorBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance)
+{
+ // Associate a cancellation handler with the background task.
+ // Even though this task isn't performing much work, it can still be cancelled.
+ taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &ActivitySensorBackgroundTask::OnCanceled);
+
+ // Read the activity reports
+ ActivitySensorTriggerDetails^ triggerDetails = safe_cast(taskInstance->TriggerDetails);
+ auto reports = triggerDetails->ReadReports();
+
+ auto settings = ApplicationData::Current->LocalSettings;
+ settings->Values->Insert("ReportCount", reports->Size.ToString());
+
+ auto timestampFormatter = ref new DateTimeFormatter("day month year hour minute second");
+ if (reports->Size > 0)
+ {
+ auto lastReading = reports->GetAt(reports->Size - 1)->Reading;
+ settings->Values->Insert("LastActivity", lastReading->Activity.ToString());
+ settings->Values->Insert("LastConfidence", lastReading->Confidence.ToString());
+ settings->Values->Insert("LastTimestamp", timestampFormatter->Format(lastReading->Timestamp));
+ }
+ else
+ {
+ settings->Values->Insert("LastActivity", "No data");
+ settings->Values->Insert("LastConfidence", "No data");
+ settings->Values->Insert("LastTimestamp", "No data");
+ }
+
+ auto calendar = ref new Calendar();
+ calendar->SetToNow();
+ settings->Values->Insert("TaskStatus", "Completed at " + timestampFormatter->Format(calendar->GetDateTime()));
+ // No deferral is held on taskInstance because we are returning immediately.
+}
+
+///
+/// Handles background task cancellation.
+///
+/// The background task instance being cancelled.
+/// The cancellation reason.
+void ActivitySensorBackgroundTask::OnCanceled(IBackgroundTaskInstance^ /*taskInstance*/, BackgroundTaskCancellationReason reason)
+{
+ auto settings = ApplicationData::Current->LocalSettings;
+ auto timestampFormatter = ref new DateTimeFormatter("day month year hour minute second");
+
+ auto calendar = ref new Calendar();
+ calendar->SetToNow();
+ settings->Values->Insert("TaskStatus", reason.ToString() + " at " + timestampFormatter->Format(calendar->GetDateTime()));
+}
diff --git a/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.h b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.h
new file mode 100644
index 0000000000..272962a7e4
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorBackgroundTask.h
@@ -0,0 +1,40 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//
+// ActivitySensorBackgroundTask.h
+// Declaration of the ActivitySensorBackgroundTask class
+//
+
+#pragma once
+
+#include "pch.h"
+
+using namespace Windows::ApplicationModel::Background;
+
+namespace Tasks
+{
+ [Windows::Foundation::Metadata::WebHostHidden]
+ public ref class ActivitySensorBackgroundTask sealed : public IBackgroundTask
+ {
+
+ public:
+ ActivitySensorBackgroundTask() {}
+
+ virtual void Run(IBackgroundTaskInstance^ taskInstance);
+ void OnCanceled(IBackgroundTaskInstance^ taskInstance, BackgroundTaskCancellationReason reason);
+
+ private:
+ ~ActivitySensorBackgroundTask() {}
+
+ IBackgroundTaskInstance^ TaskInstance;
+ };
+}
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Tasks/ActivitySensorTasks.vcxproj b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorTasks.vcxproj
new file mode 100644
index 0000000000..92bcbadac4
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Tasks/ActivitySensorTasks.vcxproj
@@ -0,0 +1,184 @@
+
+
+
+ {1F4BC306-A3EC-4DEB-B545-0B55673243CE}
+ Tasks
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.10240.0
+ 10.0.10240.0
+ true
+ 10.0.10240.0
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tasks
+ .dll
+
+
+ Tasks
+ .dll
+
+
+ Tasks
+ .dll
+
+
+ Tasks
+
+
+ Tasks
+
+
+ Tasks
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+ _WINRT_DLL;%(PreprocessorDefinitions)
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+ _WINRT_DLL;%(PreprocessorDefinitions)
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+ _WINRT_DLL;%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+ _WINRT_DLL;%(PreprocessorDefinitions)
+
+
+
+
+ /bigobj %(AdditionalOptions)
+ 4453;28204
+ _WINRT_DLL;%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cpp/Tasks/pch.cpp b/Samples/ActivitySensor/cpp/Tasks/pch.cpp
new file mode 100644
index 0000000000..ade821753a
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Tasks/pch.cpp
@@ -0,0 +1,5 @@
+//
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/ActivitySensor/cpp/Tasks/pch.h b/Samples/ActivitySensor/cpp/Tasks/pch.h
new file mode 100644
index 0000000000..3553d2ca58
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/Tasks/pch.h
@@ -0,0 +1,8 @@
+//
+// Header for standard system include files.
+//
+
+#pragma once
+
+#include
+#include
diff --git a/Samples/ActivitySensor/cpp/pch.cpp b/Samples/ActivitySensor/cpp/pch.cpp
new file mode 100644
index 0000000000..ade821753a
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/pch.cpp
@@ -0,0 +1,5 @@
+//
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/Samples/ActivitySensor/cpp/pch.h b/Samples/ActivitySensor/cpp/pch.h
new file mode 100644
index 0000000000..a080c5ca09
--- /dev/null
+++ b/Samples/ActivitySensor/cpp/pch.h
@@ -0,0 +1,13 @@
+//
+// Header for standard system include files.
+//
+
+#pragma once
+
+#include
+#include
+
+#include "App.xaml.h"
+
+// Common class ID for activity sensors
+const GUID GUID_ActivitySensor_ClassId = { 0X9D9E0118, 0X1807, 0X4F2E, 0X96, 0XE4, 0X2C, 0XE5, 0X71, 0X42, 0XE1, 0X96 };
diff --git a/Samples/ActivitySensor/cs/ActivitySensor.csproj b/Samples/ActivitySensor/cs/ActivitySensor.csproj
new file mode 100644
index 0000000000..153e9cdc1f
--- /dev/null
+++ b/Samples/ActivitySensor/cs/ActivitySensor.csproj
@@ -0,0 +1,192 @@
+
+
+
+
+ Debug
+ x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
+ AppContainerExe
+ Properties
+ ActivitySensorCS
+ ActivitySensorCS
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+ App.xaml.cs
+ App.xaml
+
+
+ MainPage.xaml.cs
+ MainPage.xaml
+
+
+ Properties\AssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+ App.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MainPage.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ {e9d6df34-56b9-4d21-9ac0-b39cdf79151a}
+ ActivitySensorTasks
+
+
+
+ 14.0
+
+
+
+
diff --git a/Samples/ActivitySensor/cs/ActivitySensor.sln b/Samples/ActivitySensor/cs/ActivitySensor.sln
new file mode 100644
index 0000000000..4c77887075
--- /dev/null
+++ b/Samples/ActivitySensor/cs/ActivitySensor.sln
@@ -0,0 +1,60 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22418.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActivitySensor", "ActivitySensor.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActivitySensorTasks", "Tasks\ActivitySensorTasks.csproj", "{E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|ARM.ActiveCfg = Debug|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|ARM.Build.0 = Debug|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|ARM.Deploy.0 = Debug|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x64.ActiveCfg = Debug|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x64.Build.0 = Debug|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x64.Deploy.0 = Debug|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x86.ActiveCfg = Debug|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x86.Build.0 = Debug|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Debug|x86.Deploy.0 = Debug|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|ARM.ActiveCfg = Release|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|ARM.Build.0 = Release|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|ARM.Deploy.0 = Release|ARM
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x64.ActiveCfg = Release|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x64.Build.0 = Release|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x64.Deploy.0 = Release|x64
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x86.ActiveCfg = Release|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x86.Build.0 = Release|x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/ActivitySensor/cs/Package.appxmanifest b/Samples/ActivitySensor/cs/Package.appxmanifest
new file mode 100644
index 0000000000..87cb7d231a
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Package.appxmanifest
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+ ActivitySensorCS
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/SampleConfiguration.cs b/Samples/ActivitySensor/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..97edcca320
--- /dev/null
+++ b/Samples/ActivitySensor/cs/SampleConfiguration.cs
@@ -0,0 +1,37 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using ActivitySensorCS;
+
+namespace SDKTemplate
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "ActivitySensorCS";
+
+ List scenarios = new List
+ {
+ new Scenario() { Title = "Current activity", ClassType = typeof(Scenario1_CurrentActivity) },
+ new Scenario() { Title = "Activity history", ClassType = typeof(Scenario2_History) },
+ new Scenario() { Title = "Events", ClassType = typeof(Scenario3_ChangeEvents) },
+ new Scenario() { Title = "Background activity", ClassType = typeof(Scenario4_BackgroundActivity) },
+ };
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml b/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml
new file mode 100644
index 0000000000..4c5b326c5e
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml.cs b/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml.cs
new file mode 100644
index 0000000000..d6ec051202
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario1_CurrentActivity.xaml.cs
@@ -0,0 +1,77 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.Devices.Enumeration;
+using Windows.Devices.Sensors;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+using SDKTemplate;
+
+namespace ActivitySensorCS
+{
+ public sealed partial class Scenario1_CurrentActivity : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ // Common class ID for activity sensors
+ Guid ActivitySensorClassId = new Guid("9D9E0118-1807-4F2E-96E4-2CE57142E196");
+
+ public Scenario1_CurrentActivity()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// This is the click handler for the 'Get Current Activity' button.
+ ///
+ ///
+ ///
+ async private void ScenarioGetCurrentActivity(object sender, RoutedEventArgs e)
+ {
+ // Reset fields and status
+ ScenarioOutput_Activity.Text = "No data";
+ ScenarioOutput_Confidence.Text = "No data";
+ ScenarioOutput_Timestamp.Text = "No data";
+ rootPage.NotifyUser("", NotifyType.StatusMessage);
+
+ // Determine if we can access activity sensors
+ var deviceAccessInfo = DeviceAccessInformation.CreateFromDeviceClassId(ActivitySensorClassId);
+ if (deviceAccessInfo.CurrentStatus == DeviceAccessStatus.Allowed)
+ {
+ // Get the default sensor
+ var activitySensor = await ActivitySensor.GetDefaultAsync();
+ if (activitySensor != null)
+ {
+ // Get the current activity reading
+ var reading = await activitySensor.GetCurrentReadingAsync();
+ if (reading != null)
+ {
+ ScenarioOutput_Activity.Text = reading.Activity.ToString();
+ ScenarioOutput_Confidence.Text = reading.Confidence.ToString();
+ ScenarioOutput_Timestamp.Text = reading.Timestamp.ToString("u");
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("No activity sensor found", NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access denied to activity sensors", NotifyType.ErrorMessage);
+ }
+ }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Scenario2_History.xaml b/Samples/ActivitySensor/cs/Scenario2_History.xaml
new file mode 100644
index 0000000000..667f9bdeb0
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario2_History.xaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/Scenario2_History.xaml.cs b/Samples/ActivitySensor/cs/Scenario2_History.xaml.cs
new file mode 100644
index 0000000000..46c3e52232
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario2_History.xaml.cs
@@ -0,0 +1,96 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.Devices.Enumeration;
+using Windows.Devices.Sensors;
+using Windows.Globalization;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+using SDKTemplate;
+
+namespace ActivitySensorCS
+{
+ public sealed partial class Scenario2_History : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ // Common class ID for activity sensors
+ Guid ActivitySensorClassId = new Guid("9D9E0118-1807-4F2E-96E4-2CE57142E196");
+
+ public Scenario2_History()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// This is the click handler for the 'Get Activity History' button.
+ ///
+ ///
+ ///
+ async private void ScenarioGetActivityHistory(object sender, RoutedEventArgs e)
+ {
+ // Reset fields and status
+ ScenarioOutput_Count.Text = "No data";
+ ScenarioOutput_Activity1.Text = "No data";
+ ScenarioOutput_Confidence1.Text = "No data";
+ ScenarioOutput_Timestamp1.Text = "No data";
+ ScenarioOutput_ActivityN.Text = "No data";
+ ScenarioOutput_ConfidenceN.Text = "No data";
+ ScenarioOutput_TimestampN.Text = "No data";
+ rootPage.NotifyUser("", NotifyType.StatusMessage);
+
+ // Determine if we can access activity sensors
+ var deviceAccessInfo = DeviceAccessInformation.CreateFromDeviceClassId(ActivitySensorClassId);
+ if (deviceAccessInfo.CurrentStatus == DeviceAccessStatus.Allowed)
+ {
+ // Determine if an activity sensor is present
+ // This can also be done using Windows::Devices::Enumeration::DeviceInformation::FindAllAsync
+ var activitySensor = await ActivitySensor.GetDefaultAsync();
+ if (activitySensor != null)
+ {
+ var calendar = new Calendar();
+ calendar.SetToNow();
+ calendar.AddDays(-1);
+ var yesterday = calendar.GetDateTime();
+
+ // Get history from yesterday onwards
+ var history = await ActivitySensor.GetSystemHistoryAsync(yesterday);
+
+ ScenarioOutput_Count.Text = history.Count.ToString();
+ if (history.Count > 0)
+ {
+ var reading1 = history[0];
+ ScenarioOutput_Activity1.Text = reading1.Activity.ToString();
+ ScenarioOutput_Confidence1.Text = reading1.Confidence.ToString();
+ ScenarioOutput_Timestamp1.Text = reading1.Timestamp.ToString("u");
+
+ var readingN = history[history.Count - 1];
+ ScenarioOutput_ActivityN.Text = readingN.Activity.ToString();
+ ScenarioOutput_ConfidenceN.Text = readingN.Confidence.ToString();
+ ScenarioOutput_TimestampN.Text = readingN.Timestamp.ToString("u");
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("No activity sensors found", NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access to activity sensors is denied", NotifyType.ErrorMessage);
+ }
+ }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml b/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml
new file mode 100644
index 0000000000..403896bb68
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml.cs b/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml.cs
new file mode 100644
index 0000000000..0563f2d422
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario3_ChangeEvents.xaml.cs
@@ -0,0 +1,170 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.Devices.Enumeration;
+using Windows.Devices.Sensors;
+using Windows.Foundation;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+using SDKTemplate;
+
+namespace ActivitySensorCS
+{
+ public sealed partial class Scenario3_ChangeEvents : Page
+ {
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+
+ // Common class ID for activity sensors
+ Guid ActivitySensorClassId = new Guid("9D9E0118-1807-4F2E-96E4-2CE57142E196");
+
+ private DeviceAccessInformation _deviceAccessInformation;
+ private ActivitySensor _activitySensor;
+
+ public Scenario3_ChangeEvents()
+ {
+ this.InitializeComponent();
+ _activitySensor = null;
+
+ // Register for access changed notifications for activity sensors
+ _deviceAccessInformation = DeviceAccessInformation.CreateFromDeviceClassId(ActivitySensorClassId);
+ _deviceAccessInformation.AccessChanged += new TypedEventHandler(AccessChanged);
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ScenarioEnableReadingChangedButton.IsEnabled = true;
+ ScenarioDisableReadingChangedButton.IsEnabled = false;
+ }
+
+ ///
+ /// Invoked immediately before the Page is unloaded and is no longer the current source of a parent Frame.
+ ///
+ ///
+ /// Event data that can be examined by overriding code. The event data is representative
+ /// of the navigation that will unload the current Page unless canceled. The
+ /// navigation can potentially be canceled by setting Cancel.
+ ///
+ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
+ {
+ if (ScenarioDisableReadingChangedButton.IsEnabled && _activitySensor != null)
+ {
+ _activitySensor.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+ }
+
+ base.OnNavigatingFrom(e);
+ }
+
+ ///
+ /// This is the event handler for ReadingChanged events.
+ ///
+ ///
+ ///
+ async private void ReadingChanged(object sender, ActivitySensorReadingChangedEventArgs e)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ ActivitySensorReading reading = e.Reading;
+ ScenarioOutput_Activity.Text = reading.Activity.ToString();
+ ScenarioOutput_Confidence.Text = reading.Confidence.ToString();
+ ScenarioOutput_ReadingTimestamp.Text = reading.Timestamp.ToString("u");
+ });
+ }
+
+ ///
+ /// This is the click handler for the 'Reading Changed On' button.
+ ///
+ ///
+ ///
+ private async void ScenarioEnableReadingChanged(object sender, RoutedEventArgs e)
+ {
+ // Determine if we can access activity sensors
+ if (_deviceAccessInformation.CurrentStatus == DeviceAccessStatus.Allowed)
+ {
+ if (_activitySensor == null)
+ {
+ _activitySensor = await ActivitySensor.GetDefaultAsync();
+ }
+
+ if (_activitySensor != null)
+ {
+ _activitySensor.SubscribedActivities.Add(ActivityType.Walking);
+ _activitySensor.SubscribedActivities.Add(ActivityType.Running);
+ _activitySensor.SubscribedActivities.Add(ActivityType.InVehicle);
+ _activitySensor.SubscribedActivities.Add(ActivityType.Biking);
+ _activitySensor.SubscribedActivities.Add(ActivityType.Fidgeting);
+
+ _activitySensor.ReadingChanged += new TypedEventHandler(ReadingChanged);
+
+ ScenarioEnableReadingChangedButton.IsEnabled = false;
+ ScenarioDisableReadingChangedButton.IsEnabled = true;
+ rootPage.NotifyUser("Subscribed to reading changes", NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser("No activity sensor found", NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access denied to activity sensors", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Reading Changed Off' button.
+ ///
+ ///
+ ///
+ private void ScenarioDisableReadingChanged(object sender, RoutedEventArgs e)
+ {
+ if (_activitySensor != null)
+ {
+ _activitySensor.ReadingChanged -= new TypedEventHandler(ReadingChanged);
+ rootPage.NotifyUser("Unsubscribed from reading changes", NotifyType.StatusMessage);
+ }
+
+ ScenarioEnableReadingChangedButton.IsEnabled = true;
+ ScenarioDisableReadingChangedButton.IsEnabled = false;
+ }
+
+ ///
+ /// This is the event handler for AccessChanged events.
+ ///
+ ///
+ ///
+ private async void AccessChanged(DeviceAccessInformation sender, DeviceAccessChangedEventArgs e)
+ {
+ var status = e.Status;
+ if (status != DeviceAccessStatus.Allowed)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Access denied to activity sensors", NotifyType.ErrorMessage);
+ _activitySensor = null;
+
+ ScenarioEnableReadingChangedButton.IsEnabled = true;
+ ScenarioDisableReadingChangedButton.IsEnabled = false;
+ });
+ }
+ }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml b/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml
new file mode 100644
index 0000000000..e20a330645
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml.cs b/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml.cs
new file mode 100644
index 0000000000..f4349927cd
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Scenario4_BackgroundActivity.xaml.cs
@@ -0,0 +1,211 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.ApplicationModel.Background;
+using Windows.Devices.Enumeration;
+using Windows.Devices.Sensors;
+using Windows.Storage;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+using SDKTemplate;
+
+namespace ActivitySensorCS
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario4_BackgroundActivity : Page
+ {
+ public const string SampleBackgroundTaskName = "ActivitySensorBackgroundTask";
+ public const string SampleBackgroundTaskEntryPoint = "Tasks.ActivitySensorBackgroundTask";
+
+ // Common class ID for activity sensors
+ Guid ActivitySensorClassId = new Guid("9D9E0118-1807-4F2E-96E4-2CE57142E196");
+
+ // A pointer back to the main page. This is needed if you want to call methods in MainPage such
+ // as NotifyUser()
+ MainPage rootPage = MainPage.Current;
+ bool registered = false;
+
+ public Scenario4_BackgroundActivity()
+ {
+ this.InitializeComponent();
+ }
+
+ ///
+ /// Invoked when this page is about to be displayed in a Frame.
+ ///
+ /// Event data that describes how this page was reached. The Parameter
+ /// property is typically used to configure the page.
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ foreach (var task in BackgroundTaskRegistration.AllTasks)
+ {
+ if (task.Value.Name == Scenario4_BackgroundActivity.SampleBackgroundTaskName)
+ {
+ registered = true;
+ break;
+ }
+ }
+
+ UpdateUIAsync(registered ? "Registered" : "Unregistered");
+ }
+
+ ///
+ /// This is the click handler for the 'Register Task' button.
+ ///
+ ///
+ ///
+ async private void ScenarioRegisterTask(object sender, RoutedEventArgs e)
+ {
+ // Determine if we can access activity sensors
+ var deviceAccessInfo = DeviceAccessInformation.CreateFromDeviceClassId(ActivitySensorClassId);
+ if (deviceAccessInfo.CurrentStatus == DeviceAccessStatus.Allowed)
+ {
+ // Determine if an activity sensor is present
+ // This can also be done using Windows::Devices::Enumeration::DeviceInformation::FindAllAsync
+ var activitySensor = await ActivitySensor.GetDefaultAsync();
+ if (activitySensor != null)
+ {
+ var status = await BackgroundExecutionManager.RequestAccessAsync();
+
+ if ((BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity == status) ||
+ (BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity == status))
+ {
+ RegisterBackgroundTask();
+ }
+ else
+ {
+ rootPage.NotifyUser("Background tasks may be disabled for this app", NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("No activity sensors found", NotifyType.ErrorMessage);
+ }
+ }
+ else
+ {
+ rootPage.NotifyUser("Access denied to activity sensors", NotifyType.ErrorMessage);
+ }
+ }
+
+ ///
+ /// This is the click handler for the 'Unregister Task' button.
+ ///
+ ///
+ ///
+ private void ScenarioUnregisterTask(object sender, RoutedEventArgs e)
+ {
+ // Loop through all background tasks and unregister any with SampleBackgroundTaskName
+ foreach (var cur in BackgroundTaskRegistration.AllTasks)
+ {
+ if (SampleBackgroundTaskName == cur.Value.Name)
+ {
+ cur.Value.Unregister(true /*cancelTask*/);
+ registered = false;
+ }
+ }
+
+ if (!registered)
+ {
+ UpdateUIAsync("Unregistered");
+ }
+ }
+
+ ///
+ /// This is the event handler for background task completion.
+ ///
+ /// The task that is reporting completion.
+ /// The completion report arguments.
+ private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
+ {
+ string status = "Completed";
+ try
+ {
+ args.CheckResult();
+ }
+ catch (Exception e)
+ {
+ status = e.Message;
+ }
+ UpdateUIAsync(status);
+ }
+
+ ///
+ /// Registers the background task.
+ ///
+ private void RegisterBackgroundTask()
+ {
+ var builder = new BackgroundTaskBuilder()
+ {
+ Name = SampleBackgroundTaskName,
+ TaskEntryPoint = SampleBackgroundTaskEntryPoint
+ };
+
+ const UInt32 reportIntervalMs = 3000; // 3 seconds
+ var trigger = new ActivitySensorTrigger(reportIntervalMs);
+
+ trigger.SubscribedActivities.Add(ActivityType.Walking);
+ trigger.SubscribedActivities.Add(ActivityType.Running);
+ trigger.SubscribedActivities.Add(ActivityType.Biking);
+
+ builder.SetTrigger(trigger);
+
+ BackgroundTaskRegistration task = builder.Register();
+ task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);
+
+ registered = true;
+ UpdateUIAsync("Registered");
+ }
+
+ ///
+ /// Updates the scenario UI.
+ ///
+ /// The status string to display.
+ async private void UpdateUIAsync(string status)
+ {
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ ScenarioRegisterTaskButton.IsEnabled = !registered;
+ ScenarioUnregisterTaskButton.IsEnabled = registered;
+ ScenarioOutput_TaskRegistration.Text = status;
+
+ var settings = ApplicationData.Current.LocalSettings;
+
+ if (settings.Values.ContainsKey("ReportCount"))
+ {
+ ScenarioOutput_ReportCount.Text = settings.Values["ReportCount"].ToString(); // stored as a string
+ }
+ if (settings.Values.ContainsKey("TaskStatus"))
+ {
+ ScenarioOutput_TaskStatus.Text = settings.Values["TaskStatus"].ToString(); // stored as a string
+ }
+ if (settings.Values.ContainsKey("LastActivity"))
+ {
+ ScenarioOutput_LastActivity.Text = (string)settings.Values["LastActivity"]; // stored as a string
+ }
+ if (settings.Values.ContainsKey("LastConfidence"))
+ {
+ ScenarioOutput_LastConfidence.Text = (string)settings.Values["LastConfidence"]; // stored as a string
+ }
+ if (settings.Values.ContainsKey("LastTimestamp"))
+ {
+ ScenarioOutput_LastTimestamp.Text = settings.Values["LastTimestamp"].ToString(); // stored as a string
+ }
+ });
+ }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Tasks/ActivitySensorBackgroundTask.cs b/Samples/ActivitySensor/cs/Tasks/ActivitySensorBackgroundTask.cs
new file mode 100644
index 0000000000..a8b1536800
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Tasks/ActivitySensorBackgroundTask.cs
@@ -0,0 +1,71 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Diagnostics;
+using Windows.ApplicationModel.Background;
+using Windows.Devices.Sensors;
+using Windows.Storage;
+
+namespace Tasks
+{
+ public sealed class ActivitySensorBackgroundTask : IBackgroundTask
+ {
+ ///
+ /// The entry point of a background task.
+ ///
+ /// The current background task instance.
+ public void Run(IBackgroundTaskInstance taskInstance)
+ {
+ Debug.WriteLine("Background " + taskInstance.Task.Name + " Starting...");
+
+ // Associate a cancellation handler with the background task.
+ // Even though this task isn't performing much work, it can still be cancelled.
+ taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
+
+ // Read the activity reports
+ ActivitySensorTriggerDetails triggerDetails = taskInstance.TriggerDetails as ActivitySensorTriggerDetails;
+ var reports = triggerDetails.ReadReports();
+
+ var settings = ApplicationData.Current.LocalSettings;
+ settings.Values["ReportCount"] = reports.Count;
+ if (reports.Count > 0)
+ {
+ var lastReading = reports[reports.Count - 1].Reading;
+ settings.Values["LastActivity"] = lastReading.Activity.ToString();
+ settings.Values["LastConfidence"] = lastReading.Confidence.ToString();
+ settings.Values["LastTimestamp"] = lastReading.Timestamp.ToString("u");
+ }
+ else
+ {
+ settings.Values["LastActivity"] = "No data";
+ settings.Values["LastConfidence"] = "No data";
+ settings.Values["LastTimestamp"] = "No data";
+ }
+
+ settings.Values["TaskStatus"] = "Completed at " + DateTime.Now.ToString("u");
+
+ // No deferral is held on taskInstance because we are returning immediately.
+ }
+
+ ///
+ /// Handles background task cancellation.
+ ///
+ /// The background task instance being cancelled.
+ /// The cancellation reason.
+ private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
+ {
+ var settings = ApplicationData.Current.LocalSettings;
+ Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested...");
+ settings.Values["TaskStatus"] = reason.ToString() + " at " + DateTime.Now.ToString("u");
+ }
+ }
+}
diff --git a/Samples/ActivitySensor/cs/Tasks/ActivitySensorTasks.csproj b/Samples/ActivitySensor/cs/Tasks/ActivitySensorTasks.csproj
new file mode 100644
index 0000000000..50f9ca5440
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Tasks/ActivitySensorTasks.csproj
@@ -0,0 +1,111 @@
+
+
+
+
+ Debug
+ x86
+ {E9D6DF34-56B9-4D21-9AC0-B39CDF79151A}
+ winmdobj
+ Properties
+ Tasks
+ ActivitySensorTasksCS
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;WINDOWS_UAP;NETFX_CORE;WINDOWS_APP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+
+
+
+ 14.0
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/Tasks/Properties/AssemblyInfo.cs b/Samples/ActivitySensor/cs/Tasks/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..727c443ca9
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Tasks/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tasks")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft Corporation")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Samples/ActivitySensor/cs/Tasks/project.json b/Samples/ActivitySensor/cs/Tasks/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/ActivitySensor/cs/Tasks/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/ActivitySensor/cs/project.json b/Samples/ActivitySensor/cs/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/ActivitySensor/cs/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/README.md b/Samples/AdaptiveStreaming/README.md
new file mode 100644
index 0000000000..e7f58dd2f4
--- /dev/null
+++ b/Samples/AdaptiveStreaming/README.md
@@ -0,0 +1,49 @@
+
+
+# Adaptive Streaming Sample
+
+How to create and use an AdaptiveMediaSource to playback HLS and DASH content over HTTP.
+
+Specifically, this sample covers:
+
+- Scenario 1: Basic Adaptive Streaming
+- Scenario 2: Querying and setting bitrates for streaming thresholds
+- Scenario 3: Registering for streaming events
+ Modifying the responsiveness of the streaming algorithm
+ Setting custom headers and modifying resource requests
+- Scenario 4: Using Adaptive Streaming with PlayReady DRM
+
+Related topics
+--------------
+
+
+[Windows.Media.Streaming.Adaptive namespace](https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.streaming.adaptive.aspx)
+
+System requirements
+-----------------------------
+
+Client:
+Windows 10
+Windows Phone 10
+
+Build the sample
+----------------
+
+1. Start Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C\# or JavaScript. Double-click the Visual Studio 2015 Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+Run the sample
+--------------
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+**Deploying the sample**
+1. Select **Build** \> **Deploy Solution**.
+
+**Deploying and running the sample**
+1. To debug the sample and then run it, press F5 or select **Debug** \> **Start Debugging**. To run the sample without debugging, press Ctrl+F5 or select**Debug** \> **Start Without Debugging**.
+
+
diff --git a/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.csproj b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.csproj
new file mode 100644
index 0000000000..02b8106d42
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.csproj
@@ -0,0 +1,199 @@
+
+
+
+
+ Debug
+ x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
+ AppContainerExe
+ Properties
+ AdaptiveStreaming
+ AdaptiveStreaming
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+ App.xaml.cs
+ App.xaml
+
+
+ MainPage.xaml.cs
+ MainPage.xaml
+
+
+
+ Properties\AssemblyInfo.cs
+
+
+
+ Scenario1.xaml
+
+
+ Scenario2.xaml
+
+
+ Scenario3.xaml
+
+
+ Scenario4.xaml
+
+
+
+
+ Designer
+
+
+
+
+ App.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MainPage.xaml
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\microsoft-sdk.png
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+ Assets\windows-sdk.png
+
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln
new file mode 100644
index 0000000000..6e3c4c1c1a
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/AdaptiveStreaming.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdaptiveStreaming", "AdaptiveStreaming.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/AdaptiveStreaming/cs/Package.appxmanifest b/Samples/AdaptiveStreaming/cs/Package.appxmanifest
new file mode 100644
index 0000000000..900aa6971f
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Package.appxmanifest
@@ -0,0 +1,31 @@
+
+
+
+
+
+ AdaptiveStreaming
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/cs/PlayReady/CommonLicenseRequest.cs b/Samples/AdaptiveStreaming/cs/PlayReady/CommonLicenseRequest.cs
new file mode 100644
index 0000000000..f1f3060cdc
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/PlayReady/CommonLicenseRequest.cs
@@ -0,0 +1,66 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+
+
+using System;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace LicenseRequest
+{
+ public class CommonLicenseRequest
+ {
+ private string _lastErrorMessage;
+ public string GetLastErrorMessage()
+ {
+ return _lastErrorMessage;
+ }
+ public CommonLicenseRequest()
+ {
+ _lastErrorMessage = string.Empty;
+ }
+ ///
+ /// Invoked to acquire the PlayReady license.
+ ///
+ /// License Server URI to retrieve the PlayReady license.
+ /// HttpContent including the Challenge transmitted to the PlayReady server.
+ public async virtual Task AcquireLicense(Uri licenseServerUri, HttpContent httpRequestContent)
+ {
+ try
+ {
+ HttpClient httpClient = new HttpClient();
+ httpClient.DefaultRequestHeaders.Add("msprdrm_server_redirect_compat", "false");
+ httpClient.DefaultRequestHeaders.Add("msprdrm_server_exception_compat", "false");
+
+ HttpResponseMessage response = await httpClient.PostAsync(licenseServerUri, httpRequestContent);
+ response.EnsureSuccessStatusCode();
+
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ _lastErrorMessage = string.Empty;
+ return response.Content;
+ }
+ else
+ {
+ _lastErrorMessage = "AcquireLicense - Http Response Status Code: " + response.StatusCode.ToString();
+ }
+ }
+ catch (Exception exception)
+ {
+ _lastErrorMessage = exception.Message;
+ return null;
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/cs/SampleConfiguration.cs b/Samples/AdaptiveStreaming/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..51277eeaa1
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/SampleConfiguration.cs
@@ -0,0 +1,37 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using AdaptiveStreaming;
+
+namespace SDKTemplate
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "AdaptiveStreaming";
+
+ List scenarios = new List
+ {
+ new Scenario() { Title="Basic HLS/DASH Playback", ClassType=typeof(Scenario1)},
+ new Scenario() { Title="Configuring HLS/DASH Playback", ClassType=typeof(Scenario2)},
+ new Scenario() { Title="Customized Resource Acquisiton", ClassType=typeof(Scenario3)},
+ new Scenario() { Title="HLS/DASH Playback with PlayReady", ClassType=typeof(Scenario4)}
+ };
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+}
diff --git a/Samples/AdaptiveStreaming/cs/Scenario1.xaml b/Samples/AdaptiveStreaming/cs/Scenario1.xaml
new file mode 100644
index 0000000000..0cf7fc460f
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario1.xaml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Play
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdaptiveStreaming/cs/Scenario1.xaml.cs b/Samples/AdaptiveStreaming/cs/Scenario1.xaml.cs
new file mode 100644
index 0000000000..02a3f803dd
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario1.xaml.cs
@@ -0,0 +1,44 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace AdaptiveStreaming
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario1 : Page
+ {
+ private MainPage rootPage;
+
+ public Scenario1()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ private void btnPlay_Click(object sender, RoutedEventArgs e)
+ {
+ System.Uri manifest = new System.Uri(txtInputURL.Text);
+ mePlayer.Source = manifest;
+ }
+ }
+}
diff --git a/Samples/AdaptiveStreaming/cs/Scenario2.xaml b/Samples/AdaptiveStreaming/cs/Scenario2.xaml
new file mode 100644
index 0000000000..07e9a75f19
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario2.xaml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1) Creating an AdaptiveMediaSource object and binding this to a MediaElement for playback
+
+ 2) Querying for available bitrates, setting initial bitrate and limit min/max bitrates
+
+ 3) Registering for download requests and bitrate changes
+
+ 4) Modify bandwidth measurement window to control responsiveness of streaming algorithm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Play
+
+
+
+
+
+
+
+
+ Set Initial Bitrate
+
+ Set Minimum Bitrate
+
+ Set Maximum Bitrate
+
+ Set Measurement Window (seconds)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdaptiveStreaming/cs/Scenario2.xaml.cs b/Samples/AdaptiveStreaming/cs/Scenario2.xaml.cs
new file mode 100644
index 0000000000..7df3718aa6
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario2.xaml.cs
@@ -0,0 +1,212 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+
+using System;
+using Windows.Media.Streaming.Adaptive;
+using Windows.UI.Core;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace AdaptiveStreaming
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario2 : Page
+ {
+ private MainPage rootPage;
+ AdaptiveMediaSource ams = null; //ams represents the AdaptiveMedaSource used throughout this sample
+
+ public Scenario2()
+ {
+ this.InitializeComponent();
+ }
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ private void log(string s)
+ {
+ TextBlock text = new TextBlock();
+ text.Text = s;
+ text.TextWrapping = TextWrapping.WrapWholeWords;
+ stkOutput.Children.Add(text);
+ }
+
+ private void btnPlay_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (string.IsNullOrEmpty(txtInputURL.Text))
+ {
+ rootPage.NotifyUser("Specify a URI to play", NotifyType.ErrorMessage);
+ return;
+ }
+
+ InitializeAdaptiveMediaSource(new System.Uri(txtInputURL.Text), mePlayer);
+ }
+
+ async private void InitializeAdaptiveMediaSource(System.Uri uri, MediaElement m)
+ {
+ AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri);
+ if(result.Status == AdaptiveMediaSourceCreationStatus.Success)
+ {
+ ams = result.MediaSource;
+ m.SetMediaStreamSource(ams);
+
+ outputBitrates(); //query for available bitrates and output to the log
+ txtDownloadBitrate.Text = ams.InitialBitrate.ToString();
+ txtPlaybackBitrate.Text = ams.InitialBitrate.ToString();
+
+ //Register for download requests
+ ams.DownloadRequested += DownloadRequested;
+
+ //Register for bitrate change events
+ ams.DownloadBitrateChanged += DownloadBitrateChanged;
+ ams.PlaybackBitrateChanged += PlaybackBitrateChanged;
+ }
+ else
+ {
+ rootPage.NotifyUser("Error creating the AdaptiveMediaSource\n\t" + result.Status, NotifyType.ErrorMessage);
+ }
+ }
+
+ private void DownloadRequested(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadRequestedEventArgs args)
+ {
+ UpdateBitrateUI(txtMeasuredBandwidth, (uint)ams.InboundBitsPerSecond);
+ }
+
+ private void DownloadBitrateChanged(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadBitrateChangedEventArgs args)
+ {
+ UpdateBitrateUI(txtDownloadBitrate, args.NewValue);
+ }
+
+ private void PlaybackBitrateChanged(AdaptiveMediaSource sender, AdaptiveMediaSourcePlaybackBitrateChangedEventArgs args)
+ {
+ UpdateBitrateUI(txtPlaybackBitrate, args.NewValue);
+ }
+
+ private async void UpdateBitrateUI(TextBlock t, uint newBitrate)
+ {
+ await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
+ {
+ t.Text = newBitrate.ToString();
+ }));
+ }
+
+ private void outputBitrates()
+ {
+ if (ams != null)
+ {
+ string bitrates = "Available bitrates: ";
+ foreach (var b in ams.AvailableBitrates)
+ {
+ bitrates += b + " ";
+ }
+ log(bitrates);
+ }
+ else
+ rootPage.NotifyUser("Error: Adaptive Media Source is not initialized.", NotifyType.ErrorMessage);
+ }
+
+ private void btnSetInitialBitrate_Click(object sender, RoutedEventArgs e)
+ {
+ if(ams != null)
+ {
+ uint bitrate;
+ if (uint.TryParse(txtInitialBitrate.Text, out bitrate))
+ try {
+ ams.InitialBitrate = bitrate;
+ log("Initial bitrate set to " + bitrate);
+ } catch (Exception)
+ {
+ log("Initial bitrate must match a value from the manifest");
+ }
+ else
+ log("Initial bitrate must be set to a positive integer");
+ }
+ else
+ rootPage.NotifyUser("Error: Adaptive Media Source is not initialized.", NotifyType.ErrorMessage);
+ }
+
+ private void btnSetMinBitrate_Click(object sender, RoutedEventArgs e)
+ {
+ if (ams != null)
+ {
+ uint bitrate;
+ if (uint.TryParse(txtMinBitrate.Text, out bitrate))
+ {
+ uint minbitrate = ams.AvailableBitrates[0];
+ foreach (var b in ams.AvailableBitrates) //iterate through the list of bitrates until the min valid bitrate is found
+ {
+ if(b >= bitrate)
+ {
+ minbitrate = b;
+ break;
+ }
+ }
+ ams.DesiredMinBitrate = minbitrate;
+ log("Min bitrate set to " + minbitrate);
+ }
+ else
+ log("Min bitrate must be a positive integer");
+ }
+ else
+ rootPage.NotifyUser("Error: Adaptive Media Source is not initialized.", NotifyType.ErrorMessage);
+ }
+
+ private void btnSetMaxBitrate_Click(object sender, RoutedEventArgs e)
+ {
+ if (ams != null)
+ {
+ uint bitrate;
+ if (uint.TryParse(txtMaxBitrate.Text, out bitrate))
+ {
+ uint maxbitrate = ams.AvailableBitrates[ams.AvailableBitrates.Count-1]; //start with the max bitrate and work our way down
+ foreach (var b in ams.AvailableBitrates) //iterate through the list of bitrates until the max valid bitrate is found
+ {
+ if (b <= bitrate)
+ maxbitrate = b;
+ else
+ break;
+ }
+ ams.DesiredMaxBitrate = maxbitrate;
+ log("Max bitrate set to " + maxbitrate);
+ }
+ else
+ log("Max bitrate must be a positive integer");
+ }
+ else
+ rootPage.NotifyUser("Error: Adaptive Media Source is not initialized.", NotifyType.ErrorMessage);
+ }
+
+ private void btnSetBandwidthMeasurementWindow_Click(object sender, RoutedEventArgs e)
+ {
+ if (ams != null)
+ {
+ int windowSize;
+ if (int.TryParse(txtBandwidthMeasurementWindow.Text, out windowSize))
+ {
+ ams.InboundBitsPerSecondWindow = new TimeSpan(0, 0, windowSize);
+ log("Bandwidth measurement window size set to " + windowSize);
+ }
+ else
+ log("Bandwidth measurement window size must be set to an int");
+ }
+ else
+ rootPage.NotifyUser("Error: Adaptive Media Source is not initialized.", NotifyType.ErrorMessage);
+ }
+ }
+}
diff --git a/Samples/AdaptiveStreaming/cs/Scenario3.xaml b/Samples/AdaptiveStreaming/cs/Scenario3.xaml
new file mode 100644
index 0000000000..6a4971d123
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario3.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Demonstrates:
+
+ 1) Creating an AdaptiveMediaSource object and binding this to a MediaElement for playback
+
+ 2) Registering for download success and failure events
+
+ 3) Setting custom headers via HttpClient
+
+ 4) Customizing resource requests
+
+
+
+
+
+
+
+
+
+
+
+
+ Play
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdaptiveStreaming/cs/Scenario3.xaml.cs b/Samples/AdaptiveStreaming/cs/Scenario3.xaml.cs
new file mode 100644
index 0000000000..0dabb943e0
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario3.xaml.cs
@@ -0,0 +1,108 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+
+using System;
+using Windows.Media.Streaming.Adaptive;
+using Windows.UI.Core;
+
+namespace AdaptiveStreaming
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario3 : Page
+ {
+ private MainPage rootPage;
+ AdaptiveMediaSource ams = null; //ams represents the AdaptiveMedaSource used throughout this sample
+ Windows.Web.Http.HttpClient httpClient = null; //used to customize download requests
+
+ public Scenario3()
+ {
+ this.InitializeComponent();
+ }
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+ async private void log(string s)
+ {
+ await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
+ {
+ TextBlock text = new TextBlock();
+ text.Text = s;
+ text.TextWrapping = TextWrapping.WrapWholeWords;
+ stkOutput.Children.Add(text);
+ }));
+ }
+
+ private void btnPlay_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (string.IsNullOrEmpty(txtInputURL.Text))
+ {
+ rootPage.NotifyUser("Specify a URI to play", NotifyType.ErrorMessage);
+ return;
+ }
+
+ InitializeAdaptiveMediaSource(new System.Uri(txtInputURL.Text), mePlayer);
+ }
+
+ async private void InitializeAdaptiveMediaSource(System.Uri uri, MediaElement m)
+ {
+ httpClient = new Windows.Web.Http.HttpClient();
+ httpClient.DefaultRequestHeaders.TryAppendWithoutValidation("X-CustomHeader", "This is a custom header");
+
+ AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri, httpClient);
+ if (result.Status == AdaptiveMediaSourceCreationStatus.Success)
+ {
+ ams = result.MediaSource;
+ m.SetMediaStreamSource(ams);
+
+ //Register for download requested event
+ ams.DownloadRequested += DownloadRequested;
+
+ //Register for download success and failure events
+ ams.DownloadCompleted += DownloadCompleted;
+ ams.DownloadFailed += DownloadFailed;
+ }
+ else
+ {
+ rootPage.NotifyUser("Error creating the AdaptiveMediaSource\n\t" + result.Status, NotifyType.ErrorMessage);
+ }
+ }
+
+ private void DownloadRequested(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadRequestedEventArgs args)
+ {
+ // rewrite key URIs to replace http:// with https://
+ if (args.ResourceType == AdaptiveMediaSourceResourceType.Key)
+ {
+ string originalUri = args.ResourceUri.ToString();
+ string secureUri = originalUri.Replace("http:", "https:");
+
+ // override the URI by setting property on the result sub object
+ args.Result.ResourceUri = new Uri(secureUri);
+ }
+ }
+
+ private void DownloadCompleted(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadCompletedEventArgs args)
+ {
+ log("Download Completed. Resource Type: " + args.ResourceType + " Resource URI: " + args.ResourceUri);
+ }
+ private void DownloadFailed(AdaptiveMediaSource sender, AdaptiveMediaSourceDownloadFailedEventArgs args)
+ {
+ log("Download Failured. Resource Type: " + args.ResourceType + " Resource URI: " + args.ResourceUri + "\nHTTP Response:\n" + args.HttpResponseMessage);
+ }
+ }
+}
diff --git a/Samples/AdaptiveStreaming/cs/Scenario4.xaml b/Samples/AdaptiveStreaming/cs/Scenario4.xaml
new file mode 100644
index 0000000000..b936b47aee
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario4.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Demonstrates enabling HLS/DASH playback with PlayReady DRM
+
+
+
+
+
+
+
+
+
+
+
+
+ Play
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdaptiveStreaming/cs/Scenario4.xaml.cs b/Samples/AdaptiveStreaming/cs/Scenario4.xaml.cs
new file mode 100644
index 0000000000..2d30ee076f
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/Scenario4.xaml.cs
@@ -0,0 +1,286 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using SDKTemplate;
+
+using System;
+using Windows.Media.Streaming.Adaptive;
+using Windows.UI.Core;
+
+
+//Simplifies call to the MediaProtectionManager
+using Windows.Media.Protection;
+using Windows.Media.Protection.PlayReady;
+using System.Net.Http;
+using Windows.Foundation.Collections;
+using System.Net.Http.Headers;
+using LicenseRequest;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace AdaptiveStreaming
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class Scenario4 : Page
+ {
+ private MainPage rootPage;
+ AdaptiveMediaSource ams = null; //ams represents the AdaptiveMedaSource used throughout this scenario
+
+ private MediaProtectionManager protectionManager = null;
+ MediaProtectionServiceCompletion serviceCompletionNotifier = null;
+ private string playReadyLicenseUrl = "";
+ private string playReadyChallengeCustomData = "";
+
+
+ private const int MSPR_E_CONTENT_ENABLING_ACTION_REQUIRED = -2147174251;
+
+ public Scenario4()
+ {
+ this.InitializeComponent();
+ }
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+ async private void log(string s)
+ {
+ await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
+ {
+ TextBlock text = new TextBlock();
+ text.Text = s;
+ text.TextWrapping = TextWrapping.WrapWholeWords;
+ stkOutput.Children.Add(text);
+ }));
+ }
+
+ private void btnPlay_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ if (string.IsNullOrEmpty(txtInputURL.Text))
+ {
+ rootPage.NotifyUser("Specify a URI to play", NotifyType.ErrorMessage);
+ return;
+ }
+
+ InitializeAdaptiveMediaSource(new System.Uri(txtInputURL.Text), mePlayer);
+ }
+
+ async private void InitializeAdaptiveMediaSource(System.Uri uri, MediaElement m)
+ {
+
+ AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri);
+ if (result.Status == AdaptiveMediaSourceCreationStatus.Success)
+ {
+ ams = result.MediaSource;
+ SetUpProtectionManager(ref m);
+ m.SetMediaStreamSource(ams);
+ }
+ else
+ {
+ rootPage.NotifyUser("Error creating the AdaptiveMediaSource\n\t" + result.Status, NotifyType.ErrorMessage);
+ }
+ }
+
+ private void SetUpProtectionManager(ref MediaElement m)
+ {
+ log("Enter SetUpProtectionManager");
+
+ log("Creating protection system mappings...");
+ protectionManager = new MediaProtectionManager();
+
+ protectionManager.ComponentLoadFailed += new ComponentLoadFailedEventHandler(ProtectionManager_ComponentLoadFailed);
+ protectionManager.ServiceRequested += new ServiceRequestedEventHandler(ProtectionManager_ServiceRequested);
+
+ //Setup PlayReady as the ProtectionSystem to use by MF.
+ //The code here is mandatory and should be just copied directly over to the app
+ Windows.Foundation.Collections.PropertySet cpSystems = new Windows.Foundation.Collections.PropertySet();
+
+ cpSystems.Add("{F4637010-03C3-42CD-B932-B48ADF3A6A54}", "Windows.Media.Protection.PlayReady.PlayReadyWinRTTrustedInput");
+ protectionManager.Properties.Add("Windows.Media.Protection.MediaProtectionSystemIdMapping", cpSystems);
+
+ //Use by the media stream source about how to create ITA InitData.
+ //See here for more detai: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376846%28v=vs.85%29.aspx
+ protectionManager.Properties.Add("Windows.Media.Protection.MediaProtectionSystemId", "{F4637010-03C3-42CD-B932-B48ADF3A6A54}");
+
+ // Setup the container GUID that's in the PPSH box
+ protectionManager.Properties.Add("Windows.Media.Protection.MediaProtectionContainerGuid", "{9A04F079-9840-4286-AB92-E65BE0885F95}");
+
+ m.ProtectionManager = protectionManager;
+
+ log("Leave SetUpProtectionManager");
+ }
+
+ private async void ProtectionManager_ServiceRequested(MediaProtectionManager sender, ServiceRequestedEventArgs e)
+ {
+ log("Enter ProtectionManager_ServiceRequested");
+
+ if (e.Request is PlayReadyIndividualizationServiceRequest)
+ {
+ PlayReadyIndividualizationServiceRequest IndivRequest = e.Request as PlayReadyIndividualizationServiceRequest;
+ bool bResultIndiv = await ReactiveIndivRequest(IndivRequest, e.Completion);
+ }
+ else if (e.Request is PlayReadyLicenseAcquisitionServiceRequest)
+ {
+ PlayReadyLicenseAcquisitionServiceRequest licenseRequest = e.Request as PlayReadyLicenseAcquisitionServiceRequest;
+ LicenseAcquisitionRequest(licenseRequest, e.Completion, playReadyLicenseUrl, playReadyChallengeCustomData);
+ }
+
+ log("Leave ProtectionManager_ServiceRequested");
+ }
+
+ private void ProtectionManager_ComponentLoadFailed(MediaProtectionManager sender, ComponentLoadFailedEventArgs e)
+ {
+ log("Enter ProtectionManager_ComponentLoadFailed");
+ log(e.Information.ToString());
+
+ // List the failing components - RevocationAndRenewalInformation
+ for (int i = 0; i < e.Information.Items.Count; i++)
+ {
+ log(e.Information.Items[i].Name + "\nReasons=0x" + e.Information.Items[i].Reasons + "\n"
+ + "Renewal Id=" + e.Information.Items[i].RenewalId);
+
+ }
+ e.Completion.Complete(false);
+
+ log("Leave ProtectionManager_ComponentLoadFailed");
+ }
+
+ ///
+ /// Invoked to acquire the PlayReady License
+ ///
+ async void LicenseAcquisitionRequest(PlayReadyLicenseAcquisitionServiceRequest licenseRequest, MediaProtectionServiceCompletion CompletionNotifier, string Url, string ChallengeCustomData)
+ {
+ bool bResult = false;
+ string ExceptionMessage = string.Empty;
+
+ try
+ {
+ if (!string.IsNullOrEmpty(Url))
+ {
+ log("ProtectionManager PlayReady Manual License Acquisition Service Request in progress - URL: " + Url);
+
+ if (!string.IsNullOrEmpty(ChallengeCustomData))
+ {
+ System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
+ byte[] b = encoding.GetBytes(ChallengeCustomData);
+ licenseRequest.ChallengeCustomData = Convert.ToBase64String(b, 0, b.Length);
+ }
+
+ PlayReadySoapMessage soapMessage = licenseRequest.GenerateManualEnablingChallenge();
+
+ byte[] messageBytes = soapMessage.GetMessageBody();
+ HttpContent httpContent = new ByteArrayContent(messageBytes);
+
+ IPropertySet propertySetHeaders = soapMessage.MessageHeaders;
+ foreach (string strHeaderName in propertySetHeaders.Keys)
+ {
+ string strHeaderValue = propertySetHeaders[strHeaderName].ToString();
+
+ // The Add method throws an ArgumentException try to set protected headers like "Content-Type"
+ // so set it via "ContentType" property
+ if (strHeaderName.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
+ httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse(strHeaderValue);
+ else
+ httpContent.Headers.Add(strHeaderName.ToString(), strHeaderValue);
+ }
+ CommonLicenseRequest licenseAcquision = new CommonLicenseRequest();
+ HttpContent responseHttpContent = await licenseAcquision.AcquireLicense(new Uri(Url), httpContent);
+ if (responseHttpContent != null)
+ {
+ Exception exResult = licenseRequest.ProcessManualEnablingResponse(await responseHttpContent.ReadAsByteArrayAsync());
+ if (exResult != null)
+ {
+ throw exResult;
+ }
+ bResult = true;
+ }
+ else
+ ExceptionMessage = licenseAcquision.GetLastErrorMessage();
+ }
+ else
+ {
+ log ("ProtectionManager PlayReady License Acquisition Service Request in progress - URL: " + licenseRequest.Uri.ToString());
+ await licenseRequest.BeginServiceRequest();
+ bResult = true;
+ }
+ }
+ catch (Exception e)
+ {
+ ExceptionMessage = e.Message;
+ }
+
+ if (bResult == true)
+ log(!string.IsNullOrEmpty(Url) ? "ProtectionManager Manual PlayReady License Acquisition Service Request successful" :
+ "ProtectionManager PlayReady License Acquisition Service Request successful");
+ else
+ log(!string.IsNullOrEmpty(Url) ? "ProtectionManager Manual PlayReady License Acquisition Service Request failed: " + ExceptionMessage :
+ "ProtectionManager PlayReady License Acquisition Service Request failed: " + ExceptionMessage);
+ CompletionNotifier.Complete(bResult);
+ }
+ ///
+ /// Proactive Individualization Request
+ ///
+ async void ProActiveIndivRequest()
+ {
+ PlayReadyIndividualizationServiceRequest indivRequest = new PlayReadyIndividualizationServiceRequest();
+ log("ProtectionManager PlayReady ProActive Individualization Service Request in progress...");
+ bool bResultIndiv = await ReactiveIndivRequest(indivRequest, null);
+ if (bResultIndiv == true)
+ log("ProtectionManager PlayReady ProActive Individualization Service Request successful");
+ else
+ log("ProtectionManager PlayReady ProActive Individualization Service Request failed");
+
+ }
+ ///
+ /// Invoked to send the Individualization Request
+ ///
+ async Task ReactiveIndivRequest(PlayReadyIndividualizationServiceRequest IndivRequest, MediaProtectionServiceCompletion CompletionNotifier)
+ {
+ bool bResult = false;
+ Exception exception = null;
+ log("ProtectionManager PlayReady Individualization Service Request in progress...");
+ try
+ {
+ await IndivRequest.BeginServiceRequest();
+ }
+ catch (Exception ex)
+ {
+ exception = ex;
+ }
+ finally
+ {
+ if (exception == null)
+ {
+ bResult = true;
+ }
+ else
+ {
+ COMException comException = exception as COMException;
+ if (comException != null && comException.HResult == MSPR_E_CONTENT_ENABLING_ACTION_REQUIRED)
+ {
+ IndivRequest.NextServiceRequest();
+ }
+ }
+ }
+ if (bResult == true)
+ log("ProtectionManager PlayReady Individualization Service Request successful");
+ else
+ log("ProtectionManager PlayReady Individualization Service Request failed");
+ if (CompletionNotifier != null) CompletionNotifier.Complete(bResult);
+ return bResult;
+
+ }
+ }
+}
diff --git a/Samples/AdaptiveStreaming/cs/project.json b/Samples/AdaptiveStreaming/cs/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/AdaptiveStreaming/cs/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/AdaptiveStreaming.jsproj b/Samples/AdaptiveStreaming/js/AdaptiveStreaming.jsproj
new file mode 100644
index 0000000000..10c5647ca5
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/AdaptiveStreaming.jsproj
@@ -0,0 +1,148 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ Debug
+ ARM
+
+
+ Debug
+ x64
+
+
+ Debug
+ x86
+
+
+ Release
+ AnyCPU
+
+
+ Release
+ ARM
+
+
+ Release
+ x64
+
+
+ Release
+ x86
+
+
+
+ c2adb9af-edb3-4e57-8056-9d0531d4a6b2
+
+
+
+ 14.0
+
+
+
+
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ $(VersionNumberMajor).$(VersionNumberMinor)
+ en-US
+
+
+
+ Designer
+
+
+
+
+
+ default.html
+
+
+
+
+
+ images\microsoft-sdk.png
+
+
+ images\smallTile-sdk.png
+
+
+ images\splash-sdk.png
+
+
+ images\storeLogo-sdk.png
+
+
+ images\tile-sdk.png
+
+
+ images\windows-sdk.png
+
+
+ js\default.js
+
+
+ css\default.css
+
+
+
+
+
+
+
+ Microsoft.WinJS.4.0\css\ui-dark.css
+
+
+ Microsoft.WinJS.4.0\css\ui-light.css
+
+
+ Microsoft.WinJS.4.0\js\en-US\ui.strings.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense-setup.js
+
+
+ Microsoft.WinJS.4.0\js\WinJS.intellisense.js
+
+
+ Microsoft.WinJS.4.0\fonts\Symbols.ttf
+
+
+ Microsoft.WinJS.4.0\js\base.js
+
+
+ Microsoft.WinJS.4.0\js\ui.js
+
+
+ sample-utils\footer.html
+
+
+ sample-utils\header.html
+
+
+ sample-utils\sample-utils.js
+
+
+ sample-utils\scenario-select.css
+
+
+ sample-utils\scenario-select.html
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/AdaptiveStreaming.sln b/Samples/AdaptiveStreaming/js/AdaptiveStreaming.sln
new file mode 100644
index 0000000000..0edef349c7
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/AdaptiveStreaming.sln
@@ -0,0 +1,48 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "AdaptiveStreaming", "AdaptiveStreaming.jsproj", "{C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.ActiveCfg = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.Build.0 = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|ARM.Deploy.0 = Debug|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.ActiveCfg = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.Build.0 = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x64.Deploy.0 = Debug|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.ActiveCfg = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.Build.0 = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Debug|x86.Deploy.0 = Debug|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.ActiveCfg = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.Build.0 = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|ARM.Deploy.0 = Release|ARM
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.ActiveCfg = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.Build.0 = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x64.Deploy.0 = Release|x64
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.ActiveCfg = Release|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.Build.0 = Release|x86
+ {C2ADB9AF-EDB3-4E57-8056-9D0531D4A6B2}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/css/placeholder.txt b/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/css/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/fonts/placeholder b/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/fonts/placeholder
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/js/en-us/placeholder.txt b/Samples/AdaptiveStreaming/js/Microsoft.WinJS.4.0/js/en-us/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AdaptiveStreaming/js/css/default.css b/Samples/AdaptiveStreaming/js/css/default.css
new file mode 100644
index 0000000000..400a713e22
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/css/default.css
@@ -0,0 +1,114 @@
+/*
+Copyright (c) Microsoft Corporation. All rights reserved
+*/
+
+#header {
+ padding: 15px 0px 30px 52px;
+}
+
+#statusMessage {
+ padding: 10px;
+ font-size: 12px;
+ font-weight: 600;
+}
+
+#footer {
+ padding: 25px 10px;
+}
+
+ #footer span {
+ font-size: 12px;
+ }
+
+ #footer .links {
+ color: rgb(153,153,153);
+ }
+
+ #footer .links a {
+ color: rgb(153,153,153);
+ font-size: 12px;
+ text-decoration: none;
+ }
+
+ #footer .links .pipe {
+ font-size: 9px;
+ }
+
+button.splitViewButton {
+ position: absolute;
+ height: 48px;
+ width: 48px;
+ min-height: 0;
+ min-width: 0;
+ padding: 0;
+ border: none;
+ margin: 0;
+ background-color: transparent;
+}
+
+ button.splitViewButton:hover {
+ background-color: rgba(255,255,255, 0.1);
+ }
+
+ button.splitViewButton:active {
+ background-color: rgba(255,255,255, 0.2);
+ }
+
+ button.splitViewButton:after {
+ position: relative;
+ font-size: 24px;
+ font-family: 'Segoe MDL2 Assets';
+ content: "\E700";
+ }
+
+.win-splitview-pane {
+ display: flex;
+ flex-direction: column;
+}
+
+ .win-splitview-pane #scenarioPane {
+ flex-grow: 1;
+ height: 0px;
+ }
+
+.win-splitview-pane-closed #header,
+.win-splitview-pane-closed #footer {
+ display: none;
+}
+
+.win-splitview-content .splitViewButton {
+ display: none;
+}
+
+.hiding .win-splitview-content .splitViewButton,
+.win-splitview-pane-closed .win-splitview-content .splitViewButton {
+ display: block;
+}
+
+#contentWrapper {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+#statusBox {
+ flex-shrink: 0;
+}
+
+#contentHost {
+ margin: 10px;
+ padding: 0px 42px 10px 42px;
+ height: 100%;
+ overflow-y: auto;
+}
+
+ #contentHost #sampleHeader, #featureLabel {
+ font: 20pt/24pt "Segoe UI";
+ font-weight: 300;
+ white-space: normal;
+ }
+
+ #contentHost #scenarioDescription {
+ font: 11pt/15pt "Segoe UI";
+ font-weight: 300;
+ }
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/css/scenario1.css b/Samples/AdaptiveStreaming/js/css/scenario1.css
new file mode 100644
index 0000000000..e3a9451a7d
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/css/scenario1.css
@@ -0,0 +1,11 @@
+/*
+Copyright (c) Microsoft Corporation. All rights reserved
+*/
+
+/* styles */
+
+button {
+ width: 50px;
+ font-size: 12px;
+}
+
diff --git a/Samples/AdaptiveStreaming/js/css/scenario2.css b/Samples/AdaptiveStreaming/js/css/scenario2.css
new file mode 100644
index 0000000000..e385fbc2a2
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/css/scenario2.css
@@ -0,0 +1,10 @@
+/*
+Copyright (c) Microsoft Corporation. All rights reserved
+*/
+
+/* styles */
+
+textarea
+{
+ width: 640px;
+}
diff --git a/Samples/AdaptiveStreaming/js/css/scenario3.css b/Samples/AdaptiveStreaming/js/css/scenario3.css
new file mode 100644
index 0000000000..b5c20bc6de
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/css/scenario3.css
@@ -0,0 +1,10 @@
+/*
+Copyright (c) Microsoft Corporation. All rights reserved
+*/
+
+/* styles */
+
+textarea
+{
+ width: 640px;
+}
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/html/scenario1.html b/Samples/AdaptiveStreaming/js/html/scenario1.html
new file mode 100644
index 0000000000..af6adfebff
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/html/scenario1.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Demonstrates enabling basic HLS/DASH playback by setting the source of a video tag to a manifest file.
+ Choose an item from the list, or provide your own URL. Then click Play.
+
+
+
+ Source:
+
+ --Choose Clip--
+ Azure Media Services Overview (aapl) - HLS
+ Azure Media Services Overview (aapl-v3) - HLS
+ Big Buck Bunny (aapl)- HLS
+ Big Buck Bunny (aapl-v3)- HLS
+ Big Buck Bunny - DASH
+ Elephant's Dream - DASH
+ Sintel Trailer - DASH
+ A-Team Trailer - DASH
+
+
+
+
Play
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/html/scenario2.html b/Samples/AdaptiveStreaming/js/html/scenario2.html
new file mode 100644
index 0000000000..7456fe12a7
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/html/scenario2.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1) Creating an AdaptiveMediaSource object and binding this to a video source for playback
+ 2) Querying for available bitrates, setting initial bitrate and limit min/max bitrates
+ 3) Registering for download requests and bitrate changes
+ 4) Modify bandwidth measurement window to control responsiveness of streaming algorithm
+
+
+
+
+
+
+ --Choose Clip--
+ Azure Media Services Overview (aapl) - HLS
+ Azure Media Services Overview (aapl-v3) - HLS
+ Big Buck Bunny (aapl)- HLS
+ Big Buck Bunny (aapl-v3)- HLS
+ Big Buck Bunny - DASH
+ Elephant's Dream - DASH
+ Sintel Trailer - DASH
+ A-Team Trailer - DASH
+
+
+
+
Set Source
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/html/scenario3.html b/Samples/AdaptiveStreaming/js/html/scenario3.html
new file mode 100644
index 0000000000..427867ce84
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/html/scenario3.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1) Creating an AdaptiveMediaSource object and binding this to a video source for playback
+ 2) Registering for download success and failure events
+ 3) Setting custom headers via HttpClient
+ 4) Customizing resource requests
+
+
+
+
+
+ Source:
+
+ --Choose Clip--
+ Azure Media Services Overview (aapl) - HLS
+ Azure Media Services Overview (aapl-v3) - HLS
+ Big Buck Bunny (aapl)- HLS
+ Big Buck Bunny (aapl-v3)- HLS
+ Big Buck Bunny - DASH
+ Elephant's Dream - DASH
+ Sintel Trailer - DASH
+ A-Team Trailer - DASH
+
+
+
+
Play
+
+
+
+
+
+
+
+
+
+
+
+ Clear Log
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/html/scenario4.html b/Samples/AdaptiveStreaming/js/html/scenario4.html
new file mode 100644
index 0000000000..afe985cbd1
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/html/scenario4.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Demonstrates enabling basic DASH playback with PlayReady DRM.
+ Choose an item from the list, or provide your own URL. Then click Play.
+
+
+
+
+ Source:
+
+ --Choose Clip--
+ Tears of Steel - DASH
+ Sintel Trailer - DASH
+
+
+
+
Play
+
+
+
+
+
+
+
+
+
+
+
+ Clear Log
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/images/placeholder.txt b/Samples/AdaptiveStreaming/js/images/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AdaptiveStreaming/js/js/sample-configuration.js b/Samples/AdaptiveStreaming/js/js/sample-configuration.js
new file mode 100644
index 0000000000..d5ceab60c3
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/js/sample-configuration.js
@@ -0,0 +1,19 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+
+ var sampleTitle = "Adaptive Streaming";
+
+ var scenarios = [
+ { url: "/html/scenario1.html", title: "Basic HLS/DASH Playback" },
+ { url: "/html/scenario2.html", title: "Configuring HLS/DASH Playback" },
+ { url: "/html/scenario3.html", title: "Customized Resource Acquisition" },
+ { url: "/html/scenario4.html", title: "Playback with PlayReady DRM" }
+ ];
+
+ WinJS.Namespace.define("SdkSample", {
+ sampleTitle: sampleTitle,
+ scenarios: new WinJS.Binding.List(scenarios)
+ });
+})();
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/js/scenario1.js b/Samples/AdaptiveStreaming/js/js/scenario1.js
new file mode 100644
index 0000000000..9a92e5981e
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/js/scenario1.js
@@ -0,0 +1,112 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/scenario1.html", {
+ ready: function (element, options) {
+ document.getElementById("clip_selection").addEventListener("change", onClipSelection, false);
+ document.getElementById("setsrc_button").addEventListener("click", setSource, false);
+ }
+ });
+
+ var AdaptiveStreaming = Windows.Media.Streaming.Adaptive;
+ var url = null;
+ var mediaSource = null;
+
+ function onClipSelection() {
+ var src_textbox = document.getElementById("src_textbox");
+ var clip_selection = document.getElementById("clip_selection");
+
+ for (var i = 0; i < clip_selection.options.length; ++i) {
+ if (clip_selection.options[i].selected) {
+ src_textbox.value = clip_selection.options[i].value;
+ }
+ }
+ }
+
+ function mapAdaptiveMediaSourceCreationStatus(status) {
+ var strings = ["Success",
+ "ManifestDownloadFailure",
+ "ManifestParseFailure",
+ "UnsupportedManifestContentType",
+ "UnsupportedManifestVersion",
+ "UnsupportedManifestProfile",
+ "UnknownFailure"];
+
+ if (status < 0 || status > strings.length) {
+ return "Unknown AdaptiveMediaSourceCreationStatus";
+ }
+
+ return strings[status];
+ }
+
+ function attachMediaSource() {
+ try {
+ if (mediaSource != null) {
+ var vid = document.getElementById("video_player1");
+
+ vid.src = URL.createObjectURL(mediaSource, { oneTimeOnly: true });
+ WinJS.log && WinJS.log("Set media element src to the AdaptiveMediaSource for url: " + url, "sample", "status");
+ }
+ } catch (e) {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function onMediaSourceCreated(result) {
+ if (result.status === AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.success) {
+
+ WinJS.log && WinJS.log("AdaptiveMediaSource.createFromUriAsync completed with status: " + result.status + " - " + mapAdaptiveMediaSourceCreationStatus(result.status), "sample", "status");
+ mediaSource = result.mediaSource;
+ attachMediaSource();
+
+ } else {
+ var errorString = "";
+ var httpResponseMessage = result.httpResponseMessage;
+
+ if (httpResponseMessage != null) {
+ errorString = " (HTTP response: " + httpResponseMessage.statusCode + " - " + httpResponseMessage.reasonPhrase;
+
+ if (httpResponseMessage.isSuccessStatusCode &&
+ result.status == AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.unsupportedManifestContentType &&
+ httpResponseMessage.content != null) {
+ errorString += "; Content-Type: " + httpResponseMessage.content.headers.contentType;
+ }
+
+ errorString += ")";
+
+ }
+ WinJS.log && WinJS.log("Failed to create adaptive media source: " + mapAdaptiveMediaSourceCreationStatus(result.status) + errorString, "sample", "error");
+ }
+ }
+
+ function loadMediaSourceFromUri() {
+ try {
+ var src_textbox = document.getElementById("src_textbox");
+ var vid = document.getElementById("video_player1");
+
+ url = new Windows.Foundation.Uri(src_textbox.value);
+
+ mediaSource = null;
+ vid.removeAttribute("src");
+
+ WinJS.log && WinJS.log("Creating AdaptiveMediaSource for url: " + url, "sample", "status");
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync(url).done(
+ function completed(result) {
+ onMediaSourceCreated(result);
+ });
+
+ } catch (e) {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function setSource() {
+ loadMediaSourceFromUri();
+ }
+
+
+})();
+
+
diff --git a/Samples/AdaptiveStreaming/js/js/scenario2.js b/Samples/AdaptiveStreaming/js/js/scenario2.js
new file mode 100644
index 0000000000..d63fc24a1e
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/js/scenario2.js
@@ -0,0 +1,333 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/scenario2.html", {
+ ready: function (element, options) {
+ document.getElementById("clip_selection").addEventListener("change", onClipSelection, false);
+ document.getElementById("setsrc_button").addEventListener("click", setSource, false);
+ document.getElementById("clear_button").addEventListener("click", clearEvents, false);
+ document.getElementById("bitrate_selection").addEventListener("change", onInitialBitrateSelection, false);
+ document.getElementById("min_bitrate_button").addEventListener("click", setDesiredMinBitrate, false);
+ document.getElementById("max_bitrate_button").addEventListener("click", setDesiredMaxBitrate, false);
+ document.getElementById("bw_measurement_button").addEventListener("click", setBwMeasurmentWindow, false);
+ }
+ });
+
+ var AdaptiveStreaming = Windows.Media.Streaming.Adaptive;
+ var url = null;
+ var mediaSource = null;
+
+ var event_id = 1;
+
+ var availableBitrates = null;
+
+ var isInitialBitrateSet = false;
+ var initialBitrate;
+
+ var minBitrate = null;
+ var maxBitrate = null;
+ var bwMeasurementWindow = null;
+
+ function secondsToMiliseconds(seconds)
+ {
+ return seconds * 1000;
+ }
+
+ function setBwMeasurmentWindow() {
+ try {
+ if (mediaSource != null) {
+ var windowSize = document.getElementById("bw_measurement_textbox").value;
+ if (windowSize != "")
+ {
+ mediaSource.inboundBitsPerSecondWindow = secondsToMiliseconds(windowSize);
+ }
+ else
+ {
+ //default is 30 seconds
+ mediaSource.inboundBitsPerSecondWindow = secondsToMiliseconds(30);
+ }
+
+ bwMeasurementWindow = windowSize;
+ logEvent("Inbound bits per second window set to " + mediaSource.inboundBitsPerSecondWindow + " miliseconds");
+ }
+ else
+ {
+ WinJS.log && WinJS.log("Adaptive Media Source is not set.", "sample", "error");
+ }
+ } catch (e)
+ {
+ logEvent("EXCEPTION: " + e.toString());
+ }
+ }
+
+ function setDesiredMinBitrate()
+ {
+ try {
+ if (mediaSource != null)
+ {
+ var bitrate = document.getElementById("min_bitrate_textbox").value;
+ if (bitrate != "")
+ {
+ mediaSource.desiredMinBitrate = bitrate;
+ }
+ else
+ {
+ mediaSource.desiredMinBitrate = null;
+ }
+
+ minBitrate = bitrate;
+ logEvent("Min bitrate set to " + mediaSource.desiredMinBitrate);
+ }
+ else
+ {
+ WinJS.log && WinJS.log("Adaptive Media Source is not set.", "sample", "error");
+ }
+ }
+ catch (e)
+ {
+ logEvent("EXCEPTION: " + e.toString());
+ }
+ }
+
+ function setDesiredMaxBitrate()
+ {
+ try {
+ if (mediaSource != null)
+ {
+ var bitrate = document.getElementById("max_bitrate_textbox").value;
+ if (bitrate != "")
+ {
+ mediaSource.desiredMaxBitrate = bitrate;
+ }
+ else
+ {
+ mediaSource.desiredMaxBitrate = null;
+ }
+ maxBitrate = bitrate;
+ logEvent("Max bitrate set to " + mediaSource.desiredMaxBitrate);
+ }
+ else
+ {
+ WinJS.log && WinJS.log("Adaptive Media Source is not set.", "sample", "error");
+ }
+ }
+ catch (e)
+ {
+ logEvent("EXCEPTION: " + e.toString());
+ }
+ }
+
+ function onInitialBitrateSelection()
+ {
+ isInitialBitrateSet = true;
+
+ var initialBitrateSelection;
+
+ var initial_bitrate_selection = document.getElementById("bitrate_selection");
+
+ for (var i = 0; i < initial_bitrate_selection.options.length; ++i)
+ {
+ if (initial_bitrate_selection.options[i].selected)
+ {
+ initialBitrate = initial_bitrate_selection.options[i].value;
+ }
+ }
+ loadMediaSourceFromUri();
+
+ }
+
+ function populateInitialBitrate()
+ {
+
+ var bitrate_selection = document.getElementById("bitrate_selection");
+ if (bitrate_selection == null)
+ return;
+
+ bitrate_selection.options.length = 1;
+
+ if (mediaSource == null)
+ {
+ WinJS.log && WinJS.log("Adaptive Media Source is not set.", "sample", "error");
+ }
+ else
+ {
+ availableBitrates.forEach(function (bitrate) {
+ var option = document.createElement("option");
+ option.text = bitrate;
+ option.value = bitrate;
+
+ bitrate_selection.add(option);
+ });
+
+ }
+ }
+
+ function clearEvents()
+ {
+ var events_textarea = document.getElementById("events_textarea");
+ events_textarea.value = "";
+ event_id = 1;
+ }
+
+ function logEvent(str)
+ {
+ var events_textarea = document.getElementById("events_textarea");
+ if (events_textarea != null) {
+ events_textarea.value += "[" + event_id + "] " + str + "\n";
+ event_id++;
+ }
+ }
+
+ function onClipSelection()
+ {
+ var src_textbox = document.getElementById("src_textbox");
+ var clip_selection = document.getElementById("clip_selection");
+
+ for (var i = 0; i < clip_selection.options.length; ++i)
+ {
+ if (clip_selection.options[i].selected)
+ {
+ src_textbox.value = clip_selection.options[i].value;
+ }
+ }
+ }
+
+ function mapAdaptiveMediaSourceCreationStatus(status)
+ {
+ var strings = ["Success",
+ "ManifestDownloadFailure",
+ "ManifestParseFailure",
+ "UnsupportedManifestContentType",
+ "UnsupportedManifestVersion",
+ "UnsupportedManifestProfile",
+ "UnknownFailure"];
+
+ if (status < 0 || status > strings.length)
+ {
+ return "Unknown AdaptiveMediaSourceCreationStatus";
+ }
+
+ return strings[status];
+ }
+
+ function attachMediaSource()
+ {
+ try
+ {
+ if (mediaSource != null)
+ {
+ var vid = document.getElementById("video_player2");
+
+ vid.src = URL.createObjectURL(mediaSource, { oneTimeOnly: true });
+ logEvent("Set media element src to the AdaptiveMediaSource for url: " + url);
+ }
+ }
+ catch (e)
+ {
+ logEvent("EXCEPTION: " + e.toString());
+ }
+ }
+
+ function onMediaSourceCreated(result)
+ {
+ if (result.status === AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.success)
+ {
+
+ logEvent("AdaptiveMediaSource.createFromUriAsync completed with status: " + result.status + " - " + mapAdaptiveMediaSourceCreationStatus(result.status));
+ mediaSource = result.mediaSource;
+ if (isInitialBitrateSet)
+ {
+ mediaSource.initialBitrate = initialBitrate;
+ isInitialBitrateSet = false;
+ }
+
+ logEvent("Selecting bitrate: " + mediaSource.initialBitrate);
+
+ var bitrates = "";
+ availableBitrates = mediaSource.availableBitrates;
+ availableBitrates.forEach(function (bitrate)
+ {
+ if (bitrates == "")
+ {
+ bitrates = bitrate;
+ } else
+ {
+ bitrates += ", " + bitrate;
+ }
+
+ });
+
+ logEvent("Available bitrates: " + bitrates);
+
+ populateInitialBitrate();
+
+ mediaSource.desiredMinBitrate = minBitrate;
+
+ mediaSource.desiredMaxBitrate = maxBitrate;
+
+ if (bwMeasurementWindow != null)
+ {
+ mediaSource.inboundBitsPerSecondWindow = bwMeasurementWindow;
+ }
+
+ attachMediaSource();
+
+ }
+ else
+ {
+ var errorString = "";
+ var httpResponseMessage = result.httpResponseMessage;
+
+ if (httpResponseMessage != null)
+ {
+ errorString = " (HTTP response: " + httpResponseMessage.statusCode + " - " + httpResponseMessage.reasonPhrase;
+
+ if (httpResponseMessage.isSuccessStatusCode &&
+ result.status == AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.unsupportedManifestContentType &&
+ httpResponseMessage.content != null)
+ {
+ errorString += "; Content-Type: " + httpResponseMessage.content.headers.contentType;
+ }
+
+ errorString += ")";
+
+ }
+ logEvent("Failed to create adaptive media source: " + mapAdaptiveMediaSourceCreationStatus(result.status) + errorString);
+ }
+ }
+
+ function loadMediaSourceFromUri()
+ {
+ try
+ {
+ var src_textbox = document.getElementById("src_textbox");
+ var vid = document.getElementById("video_player2");
+
+ url = new Windows.Foundation.Uri(src_textbox.value);
+
+ mediaSource = null;
+ vid.removeAttribute("src");
+
+ WinJS.log && WinJS.log("Creating AdaptiveMediaSource for url: " + url, "sample", "status");
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync(url).done(
+ function completed(result)
+ {
+ onMediaSourceCreated(result);
+ });
+
+ }
+ catch (e)
+ {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function setSource()
+ {
+ loadMediaSourceFromUri();
+ }
+
+
+})();
diff --git a/Samples/AdaptiveStreaming/js/js/scenario3.js b/Samples/AdaptiveStreaming/js/js/scenario3.js
new file mode 100644
index 0000000000..f6a6aca7f9
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/js/scenario3.js
@@ -0,0 +1,217 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/scenario3.html", {
+ ready: function (element, options) {
+ document.getElementById("clip_selection").addEventListener("change", onClipSelection, false);
+ document.getElementById("setsrc_button").addEventListener("click", setSource, false);
+ }
+ });
+
+ var AdaptiveStreaming = Windows.Media.Streaming.Adaptive;
+ var url = null;
+ var mediaSource = null;
+ var event_id = 1;
+
+ function onDownloadRequested(event)
+ {
+ try
+ {
+ // rewrite key URIs to replace http:// with https://
+ if (event.resourceType === AdaptiveStreaming.AdaptiveMediaSourceResourceType.key)
+ {
+ var originalUri = args.resourceUri;
+ var secureUri = originalUri.replace("http:", "https:");
+
+ //override the URI by setting property on the result sub object
+ args.result.resourceUri = new Windows.Foundation.Uri(secureUri);
+ }
+ }
+ catch (e)
+ {
+ logEvent("EXCEPTION: " + e.toString());
+ }
+ }
+
+ function onDownloadCompleted(event)
+ {
+ if (event.resourceByteRangeOffset == null)
+ {
+ logEvent("Download completed for " + mapResourceType(event.resourceType)
+ + " URI: " + event.resourceUri);
+ }
+ else
+ {
+ logEvent("Byte range completed for " + mapResourceType(event.resourceType)
+ + " URI: " + event.resourceUri + " offset: " + event.resourceByteRangeOffset
+ + " length: " + event.resourceByteRangeLength);
+ }
+ }
+
+ function onDownloadFailed(event)
+ {
+ if (event.resourceByteRangeOffset == null) {
+ logEvent("Download failed for " + mapResourceType(event.resourceType)
+ + " URI: " + event.resourceUri);
+ }
+ else {
+ logEvent("Byte range failed for " + mapResourceType(event.resourceType)
+ + " URI: " + event.resourceUri + " offset: " + event.resourceByteRangeOffset
+ + " length: " + event.resourceByteRangeLength);
+ }
+ }
+
+ function clearEvents()
+ {
+ var events_textarea = document.getElementById("events_textarea");
+ events_textarea.value = "";
+ event_id = 1;
+ }
+
+ function logEvent(str)
+ {
+ var events_textarea = document.getElementById("events_textarea");
+ if (events_textarea != null) {
+ events_textarea.value += "[" + event_id + "] " + str + "\n";
+ event_id++;
+ }
+ }
+
+ function onClipSelection()
+ {
+ var src_textbox = document.getElementById("src_textbox");
+ var clip_selection = document.getElementById("clip_selection");
+
+ for (var i = 0; i < clip_selection.options.length; ++i)
+ {
+ if (clip_selection.options[i].selected)
+ {
+ src_textbox.value = clip_selection.options[i].value;
+ }
+ }
+ }
+
+ function mapResourceType(resourceType)
+ {
+ var strings = ["Manifest",
+ "INIT segment",
+ "MEDIA segment",
+ "Key",
+ "IV"];
+
+ if (resourceType < 0 || resourceType > strings.length)
+ {
+ return "Unknown Resource Type";
+ }
+
+ return strings[resourceType];
+ }
+
+ function mapAdaptiveMediaSourceCreationStatus(status)
+ {
+ var strings = ["Success",
+ "ManifestDownloadFailure",
+ "ManifestParseFailure",
+ "UnsupportedManifestContentType",
+ "UnsupportedManifestVersion",
+ "UnsupportedManifestProfile",
+ "UnknownFailure"];
+
+ if (status < 0 || status > strings.length)
+ {
+ return "Unknown AdaptiveMediaSourceCreationStatus";
+ }
+
+ return strings[status];
+ }
+
+ function attachMediaSource()
+ {
+ try
+ {
+ if (mediaSource != null)
+ {
+ var vid = document.getElementById("video_player3");
+
+ vid.src = URL.createObjectURL(mediaSource, { oneTimeOnly: true });
+ WinJS.log && WinJS.log("Set media element src to the AdaptiveMediaSource for url: " + url, "sample", "status");
+ }
+ }
+ catch (e)
+ {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function onMediaSourceCreated(result)
+ {
+ if (result.status === AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.success)
+ {
+
+ WinJS.log && WinJS.log("AdaptiveMediaSource.createFromUriAsync completed with status: " + result.status + " - " + mapAdaptiveMediaSourceCreationStatus(result.status), "sample", "status");
+ mediaSource = result.mediaSource;
+ attachMediaSource();
+
+ //Register for download requested, success, and failure events
+ mediaSource.addEventListener("downloadrequested", onDownloadRequested, false);
+ mediaSource.addEventListener("downloadcompleted", onDownloadCompleted, false);
+ mediaSource.addEventListener("downloadfailed", onDownloadFailed, false);
+ }
+ else
+ {
+ var errorString = "";
+ var httpResponseMessage = result.httpResponseMessage;
+
+ if (httpResponseMessage != null)
+ {
+ errorString = " (HTTP response: " + httpResponseMessage.statusCode + " - " + httpResponseMessage.reasonPhrase;
+
+ if (httpResponseMessage.isSuccessStatusCode &&
+ result.status == AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.unsupportedManifestContentType &&
+ httpResponseMessage.content != null)
+ {
+ errorString += "; Content-Type: " + httpResponseMessage.content.headers.contentType;
+ }
+
+ errorString += ")";
+
+ }
+ WinJS.log && WinJS.log("Failed to create adaptive media source: " + mapAdaptiveMediaSourceCreationStatus(result.status) + errorString, "sample", "error");
+ }
+ }
+
+ function loadMediaSourceFromUri()
+ {
+ try
+ {
+ var src_textbox = document.getElementById("src_textbox");
+ var vid = document.getElementById("video_player3");
+
+ url = new Windows.Foundation.Uri(src_textbox.value);
+
+ mediaSource = null;
+ vid.removeAttribute("src");
+
+ WinJS.log && WinJS.log("Creating AdaptiveMediaSource for url: " + url, "sample", "status");
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync(url).done(
+ function completed(result)
+ {
+ onMediaSourceCreated(result);
+ });
+
+ }
+ catch (e)
+ {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function setSource()
+ {
+ loadMediaSourceFromUri();
+ }
+
+
+})();
diff --git a/Samples/AdaptiveStreaming/js/js/scenario4.js b/Samples/AdaptiveStreaming/js/js/scenario4.js
new file mode 100644
index 0000000000..911c3012f8
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/js/scenario4.js
@@ -0,0 +1,239 @@
+//// Copyright (c) Microsoft Corporation. All rights reserved
+
+(function () {
+ "use strict";
+ var page = WinJS.UI.Pages.define("/html/scenario4.html", {
+ ready: function (element, options) {
+ document.getElementById("clip_selection").addEventListener("change", onClipSelection, false);
+ document.getElementById("setsrc_button").addEventListener("click", setSource, false);
+ }
+ });
+
+ var AdaptiveStreaming = Windows.Media.Streaming.Adaptive;
+ var url = null;
+ var mediaSource = null;
+ var event_id = 1;
+
+
+ function clearEvents() {
+ var events_textarea = document.getElementById("events_textarea");
+ events_textarea.value = "";
+ event_id = 1;
+ }
+
+ function logEvent(str) {
+ var events_textarea = document.getElementById("events_textarea");
+ if (events_textarea != null) {
+ events_textarea.value += "[" + event_id + "] " + str + "\n";
+ event_id++;
+ }
+ }
+
+ function onClipSelection() {
+ var src_textbox = document.getElementById("src_textbox");
+ var clip_selection = document.getElementById("clip_selection");
+
+ for (var i = 0; i < clip_selection.options.length; ++i) {
+ if (clip_selection.options[i].selected) {
+ src_textbox.value = clip_selection.options[i].value;
+ }
+ }
+ }
+
+ function mapResourceType(resourceType) {
+ var strings = ["Manifest",
+ "INIT segment",
+ "MEDIA segment",
+ "Key",
+ "IV"];
+
+ if (resourceType < 0 || resourceType > strings.length) {
+ return "Unknown Resource Type";
+ }
+
+ return strings[resourceType];
+ }
+
+ function mapAdaptiveMediaSourceCreationStatus(status) {
+ var strings = ["Success",
+ "ManifestDownloadFailure",
+ "ManifestParseFailure",
+ "UnsupportedManifestContentType",
+ "UnsupportedManifestVersion",
+ "UnsupportedManifestProfile",
+ "UnknownFailure"];
+
+ if (status < 0 || status > strings.length) {
+ return "Unknown AdaptiveMediaSourceCreationStatus";
+ }
+
+ return strings[status];
+ }
+
+ function attachMediaSource() {
+ try {
+ if (mediaSource != null) {
+ var vid = document.getElementById("video_player4");
+ vid.src = URL.createObjectURL(mediaSource, { oneTimeOnly: true });
+ WinJS.log && WinJS.log("Set media element src to the AdaptiveMediaSource for url: " + url, "sample", "status");
+ }
+ }
+ catch (e) {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function onMediaSourceCreated(result) {
+ if (result.status === AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.success) {
+
+ WinJS.log && WinJS.log("AdaptiveMediaSource.createFromUriAsync completed with status: " + result.status + " - " + mapAdaptiveMediaSourceCreationStatus(result.status), "sample", "status");
+ mediaSource = result.mediaSource;
+ attachMediaSource();
+
+ }
+ else {
+ var errorString = "";
+ var httpResponseMessage = result.httpResponseMessage;
+
+ if (httpResponseMessage != null) {
+ errorString = " (HTTP response: " + httpResponseMessage.statusCode + " - " + httpResponseMessage.reasonPhrase;
+
+ if (httpResponseMessage.isSuccessStatusCode &&
+ result.status == AdaptiveStreaming.AdaptiveMediaSourceCreationStatus.unsupportedManifestContentType &&
+ httpResponseMessage.content != null) {
+ errorString += "; Content-Type: " + httpResponseMessage.content.headers.contentType;
+ }
+
+ errorString += ")";
+
+ }
+ WinJS.log && WinJS.log("Failed to create adaptive media source: " + mapAdaptiveMediaSourceCreationStatus(result.status) + errorString, "sample", "error");
+ }
+ }
+
+
+ function loadMediaSourceFromUri() {
+ try {
+ var vid = document.getElementById("video_player4");
+ var src_textbox = document.getElementById("src_textbox");
+
+ url = new Windows.Foundation.Uri(src_textbox.value);
+
+ mediaSource = null;
+ vid.removeAttribute("src");
+
+ WinJS.log && WinJS.log("Creating AdaptiveMediaSource for url: " + url, "sample", "status");
+ var eme = new PlayReadyManager(vid);
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync
+ AdaptiveStreaming.AdaptiveMediaSource.createFromUriAsync(url).done(
+ function completed(result) {
+ onMediaSourceCreated(result);
+ });
+
+ }
+ catch (e) {
+ WinJS.log && WinJS.log("EXCEPTION: " + e.toString(), "sample", "error");
+ }
+ }
+
+ function setSource() {
+ loadMediaSourceFromUri();
+ }
+
+ //==============================================================================
+ // EME Support
+ //==============================================================================
+
+ function PlayReadyManager(vid) {
+ this.vid = vid;
+
+ var that = this;
+ vid.addEventListener(this.NEEDKEY_EVENT, function (e) {
+ that.needPlayReadyKey(e);
+ }, false);
+ }
+
+ PlayReadyManager.prototype = {
+ NEEDKEY_EVENT: "msneedkey",
+ KEYMESSAGE_EVENT: "mskeymessage",
+ KEYADDED_EVENT: "mskeyadded",
+ KEYERROR_EVENT: "mskeyerror",
+ KEY_SYSTEM: "com.microsoft.playready",
+
+ needPlayReadyKey: function (e) {
+ var that = this;
+ var video = document.getElementById("video_player4");
+ logEvent("Received needkey message");
+
+ if (!video.msKeys) {
+ logEvent("Creating a new MediaKeys(\"" + this.KEY_SYSTEM + "\")");
+ try {
+ video.msSetMediaKeys(new MSMediaKeys(this.KEY_SYSTEM));
+ } catch (e) {
+ throw "Unable to create MediaKeys(\"" + this.KEY_SYSTEM + "\"). Verify the components are installed and functional. Original error: " + e.message;
+ }
+ } else {
+ return;
+ }
+
+ var session = video.msKeys.createSession("video/mp4", e.initData);
+ if (!session) {
+ throw "Could not create key session";
+ }
+
+ session.addEventListener(this.KEYMESSAGE_EVENT, function (e) {
+ logEvent("Processing key message");
+ that.downloadPlayReadyKey(e.destinationURL, String.fromCharCode.apply(null, new Uint16Array(e.message.buffer)), function (data) {
+ session.update(data);
+ });
+ });
+
+ session.addEventListener(this.KEYADDED_EVENT, function () {
+ logEvent("Key successfully added");
+ });
+
+ session.addEventListener(this.KEYERROR_EVENT, function () {
+ throw "Unexpected 'keyerror' event from key session. Code: " + session.error.code + ", systemCode: " + session.error.systemCode;
+ });
+ },
+
+ downloadPlayReadyKey: function (url, keyMessage, callback) {
+ logEvent("Parsing key message XML");
+ var keyMessageXML = new DOMParser().parseFromString(keyMessage, "application/xml");
+
+ var challenge;
+ if (keyMessageXML.getElementsByTagName("Challenge")[0]) {
+ challenge = atob(keyMessageXML.getElementsByTagName("Challenge")[0].childNodes[0].nodeValue);
+ } else {
+ throw "Can not find in key message";
+ }
+
+ var headerNames = keyMessageXML.getElementsByTagName("name");
+ var headerValues = keyMessageXML.getElementsByTagName("value");
+ if (headerNames.length !== headerValues.length) {
+ throw "Mismatched header / pair in key message";
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", url);
+ xhr.responseType = "arraybuffer";
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ callback(new Uint8Array(xhr.response));
+ } else {
+ throw "XHR failed (" + url + "). Status: " + xhr.status + " (" + xhr.statusText + ")";
+ }
+ }
+ }
+ for (var i = 0; i < headerNames.length; i++) {
+ xhr.setRequestHeader(headerNames[i].childNodes[0].nodeValue, headerValues[i].childNodes[0].nodeValue);
+ }
+
+ logEvent("Loading PlayReady key from: " + url);
+ xhr.send(challenge);
+ }
+ }
+
+
+})();
diff --git a/Samples/AdaptiveStreaming/js/package.appxmanifest b/Samples/AdaptiveStreaming/js/package.appxmanifest
new file mode 100644
index 0000000000..5ae7f6fced
--- /dev/null
+++ b/Samples/AdaptiveStreaming/js/package.appxmanifest
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+ AdaptiveStreaing JS Sample
+ Microsoft Corporation
+ images\storelogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdaptiveStreaming/js/sample-utils/placeholder.txt b/Samples/AdaptiveStreaming/js/sample-utils/placeholder.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/Samples/AdvancedCasting/README.md b/Samples/AdvancedCasting/README.md
new file mode 100644
index 0000000000..251400ce8c
--- /dev/null
+++ b/Samples/AdvancedCasting/README.md
@@ -0,0 +1,65 @@
+
+Advanced Casting Sample
+-----------
+
+This sample shows how to use the APIs in the **Windows.Media.Casting** and **Windows.Media.DialProtocol** namespaces. It also illustrates how to use the **Windows.UI.ViewManagement.ProjectionManager** and **Windows.Devices.Enumeration.DevicePicker** APIs to render media on a remote device. It covers sending media to various devices- Miracast, DLNA, DIAL, and Bluetooth. For an intro to casting, see the *Basic Media Casting Sample*.
+
+**Scenario 1: Media Element Casting 101:**
+Press the *Cast* button next to the progress bar in the video element. Select the device you'd like to cast to.
+
+This is an example of the built in casting that comes with the media element transport controls. This will enable casting to Miracast, DLNA, and Bluetooth devices.
+
+**Scenario 2: Casting APIs and a Custom Cast Button:**
+Press the *Cast* button next to the progress bar in the video element. Select the device you'd like to cast to.
+
+This is very similar to the first scenario, however, in this case, the **Windows.Media.Casting** APIs are used manually to create a custom cast button that's then included in the media transport controls.
+
+**Scenario 3: DIAL Sender Universal Windows App**
+For this scenario you'll need a device that supports Dial. You can set the application name and arguments in the fields provided and then use the cast button in the transport controls to launch the app on the remote device.
+
+In this scenario, the **Windows.Media.DialProtocol** APIs are illustrated.
+
+**Scenario 4: DIAL Receiver Windows Universal App**
+This scenario is used to illustrate how a developer would write a universal app that supports being launched by DIAL. This app can be launched with the APIs used in Scenario 3. Currently this scenario is only valid for select Xbox configurations.
+
+**Scenario 5: Multi-View Media Application**
+Again, the cast button is used here to send a video to a second screen. In this case, however the **Windows.UI.ViewManagement.ProjectionManager** API is used. This allows the developer to customize their second screen experience. This API works with wired monitors and Miracast devices.
+
+**Scenario 6: Combine Casting Methods**
+This scenario brings all the prior scenarios together and shows how to use them all at the same time in order to reach the widest set of devices. **Windows.Devices.Enumeration.DevicePicker** is used to build a picker to show all the different devices in one place.
+
+Related topics
+--------------
+
+[Windows.Media.Casting namespace](https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.casting.aspx)
+[Windows.Media.DialProtocol namespace](https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.dialprotocol.aspx)
+[Windows.UI.ViewManagement.ProjectionManager API](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.viewmanagement.projectionmanager.aspx)
+[Windows.Devices.Enumeration.DevicePicker API](https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.enumeration.devicepicker.aspx)
+
+System requirements
+-----------------------------
+
+Client:
+Windows 10
+Windows Phone 10
+
+Build the sample
+----------------
+
+1. Start Visual Studio 2015 and select **File** \> **Open** \> **Project/Solution**.
+2. Go to the directory to which you unzipped the sample. Then go to the subdirectory containing the sample in the language you desire - either C++, C\#, or JavaScript. Double-click the Visual Studio 2015 Solution (.sln) file.
+3. Press Ctrl+Shift+B, or select **Build** \> **Build Solution**.
+
+Run the sample
+--------------
+
+The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
+
+**Deploying the sample**
+1. Select **Build** \> **Deploy Solution**.
+
+**Deploying and running the sample**
+1. To debug the sample and then run it, press F5 or select **Debug** \> **Start Debugging**. To run the sample without debugging, press Ctrl+F5 or select**Debug** \> **Start Without Debugging**.
+
diff --git a/Samples/AdvancedCasting/cs/01_MediaElement.xaml b/Samples/AdvancedCasting/cs/01_MediaElement.xaml
new file mode 100644
index 0000000000..9522486ebb
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/01_MediaElement.xaml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/01_MediaElement.xaml.cs b/Samples/AdvancedCasting/cs/01_MediaElement.xaml.cs
new file mode 100644
index 0000000000..a453b92d27
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/01_MediaElement.xaml.cs
@@ -0,0 +1,71 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario01 : Page
+ {
+ private MainPage rootPage;
+ private VideoMetaData video;
+ public Scenario01()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+
+ // Get a video
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ video = dataProvider.GetRandomVideo();
+ this.player.Source = video.VideoLink;
+ this.LicenseText.Text = "License: " + video.License;
+
+ //Set the source on the MediaElement
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+
+ // Use the compat version of the transport controls
+ this.player.TransportControls.IsCompact = true;
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ #region Media Element Methods
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ if (this.player.CurrentState != Windows.UI.Xaml.Media.MediaElementState.Closed)
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Failed to load '{0}', {1}", video.Title, e.ErrorMessage), NotifyType.ErrorMessage);
+ }
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Openend '{0}'", video.Title), NotifyType.StatusMessage);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml b/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml
new file mode 100644
index 0000000000..52d8135bf9
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml.cs b/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml.cs
new file mode 100644
index 0000000000..34fc458f02
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/02_Casting_API_CastButton.xaml.cs
@@ -0,0 +1,201 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Controls;
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using System;
+using Windows.Devices.Enumeration;
+using Windows.Foundation;
+using Windows.Media.Casting;
+using Windows.UI;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario02 : Page
+ {
+ private MainPage rootPage;
+ private CastingDevicePicker picker = null;
+ private VideoMetaData video = null;
+ private CastingConnection connection;
+ public Scenario02()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+
+ // Get an Azure hosted video
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ video = dataProvider.GetRandomVideo();
+
+ //Set the source on the player
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+ player.Source = video.VideoLink;
+ this.LicenseText.Text = "License: " + video.License;
+
+ //Subscribe for the clicked event on the custom cast button
+ ((MediaTransportControlsWithCustomCastButton)this.player.TransportControls).CastButtonClicked += TransportControls_CastButtonClicked;
+
+ // Instantiate the Device Picker
+ picker = new CastingDevicePicker();
+
+ // Generate the filter based on the content in the MediaElement
+ picker.Filter.SupportedCastingSources.Add(player.GetAsCastingSource());
+
+ //Hook up device selected event
+ picker.CastingDeviceSelected += Picker_CastingDeviceSelected;
+
+ //Hook up device disconnected event
+ picker.CastingDevicePickerDismissed += Picker_CastingDevicePickerDismissed;
+
+ //Set the Appearence of the picker
+ picker.Appearance.BackgroundColor = Colors.Black;
+ picker.Appearance.ForegroundColor = Colors.White;
+ picker.Appearance.AccentColor = Colors.Gray;
+
+ picker.Appearance.SelectedAccentColor = Colors.Gray;
+
+ picker.Appearance.SelectedForegroundColor = Colors.White;
+ picker.Appearance.SelectedBackgroundColor = Colors.Black;
+ }
+
+ private void TransportControls_CastButtonClicked(object sender, EventArgs e)
+ {
+ rootPage.NotifyUser("Custom Cast Button Clicked", NotifyType.StatusMessage);
+
+ //Pause Current Playback
+ player.Pause();
+
+ //Get the custom transport controls
+ MediaTransportControlsWithCustomCastButton mtc = (MediaTransportControlsWithCustomCastButton)this.player.TransportControls;
+
+ //Retrieve the location of the casting button
+ GeneralTransform transform = mtc.CastButton.TransformToVisual(Window.Current.Content as UIElement);
+ Point pt = transform.TransformPoint(new Point(0, 0));
+
+ //Show the picker above our custom cast button
+ picker.Show(new Rect(pt.X, pt.Y, mtc.CastButton.ActualWidth, mtc.CastButton.ActualHeight), Windows.UI.Popups.Placement.Above);
+ }
+
+ private async void Picker_CastingDevicePickerDismissed(CastingDevicePicker sender, object args)
+ {
+ // This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ player.Play();
+ });
+ }
+ private async void Picker_CastingDeviceSelected(CastingDevicePicker sender, CastingDeviceSelectedEventArgs args)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ try
+ {
+ rootPage.NotifyUser(string.Format("Picker DeviceSelected event fired for device '{0}'", args.SelectedCastingDevice.FriendlyName), NotifyType.StatusMessage);
+
+ //DateTime t1 = DateTime.Now;
+ //DeviceInformation mydevice = await DeviceInformation.CreateFromIdAsync(args.SelectedCastingDevice.Id);
+ //DateTime t2 = DateTime.Now;
+
+ //TimeSpan ts = new TimeSpan(t2.Ticks - t1.Ticks);
+
+ //System.Diagnostics.Debug.WriteLine(string.Format("DeviceInformation.CreateFromIdAsync took '{0} seconds'", ts.TotalSeconds));
+
+ //Create a casting conneciton from our selected casting device
+ rootPage.NotifyUser(string.Format("Creating connection for '{0}'", args.SelectedCastingDevice.FriendlyName), NotifyType.StatusMessage);
+ connection = args.SelectedCastingDevice.CreateCastingConnection();
+
+ //Hook up the casting events
+ connection.ErrorOccurred += Connection_ErrorOccurred;
+ connection.StateChanged += Connection_StateChanged;
+
+ // Get the casting source from the MediaElement
+ CastingSource source = null;
+
+ try
+ {
+ // Get the casting source from the Media Element
+ source = player.GetAsCastingSource();
+
+ // Start Casting
+ rootPage.NotifyUser(string.Format("Starting casting to '{0}'", args.SelectedCastingDevice.FriendlyName), NotifyType.StatusMessage);
+ CastingConnectionErrorStatus status = await connection.RequestStartCastingAsync(source);
+
+ if (status == CastingConnectionErrorStatus.Succeeded)
+ {
+ player.Play();
+ rootPage.NotifyUser(string.Format("Starting casting to '{0}'", args.SelectedCastingDevice.FriendlyName), NotifyType.StatusMessage);
+ }
+
+ }
+ catch
+ {
+ rootPage.NotifyUser(string.Format("Failed to get casting source for video '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+ });
+ }
+
+ #region Casting Connection Status Methods
+ private async void Connection_StateChanged(CastingConnection sender, object args)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Casting Connection State Changed: " + sender.State, NotifyType.StatusMessage);
+ });
+ }
+ private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Connection Error Occured: " + args.Message, NotifyType.ErrorMessage);
+ });
+ }
+
+ #endregion
+
+
+ #region Media Element Status Methods
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Failed to load '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Openend '{0}'", video.Title), NotifyType.StatusMessage);
+ }
+
+
+ #endregion
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml b/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml
new file mode 100644
index 0000000000..03e9d01c49
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml.cs b/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml.cs
new file mode 100644
index 0000000000..68c5a37ff7
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/03_DIAL_Sender_API.xaml.cs
@@ -0,0 +1,275 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Controls;
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using System;
+using Windows.Devices.Enumeration;
+using Windows.Foundation;
+using Windows.Media.DialProtocol;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario03 : Page
+ {
+ private MainPage rootPage;
+ private DialDevicePicker picker = null;
+ private VideoMetaData video = null;
+ private DialDevice activeDialDevice = null;
+ private DeviceInformation activeDeviceInformation = null;
+
+
+ public Scenario03()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+
+ // Get an Azure hosted video
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ video = dataProvider.GetRandomVideo();
+
+ //Set the source on the player
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+ this.player.Source = video.VideoLink;
+
+ //Subscribe for the clicked event on the custom cast button
+ ((MediaTransportControlsWithCustomCastButton)this.player.TransportControls).CastButtonClicked += TransportControls_CastButtonClicked;
+
+ //Configure the DIAL launch arguments for the current video
+ this.dial_launch_args_textbox.Text = string.Format("v={0}&t=0&pairingCode=E4A8136D-BCD3-45F4-8E49-AE01E9A46B5F", video.Id);
+
+ //Subscribe for the clicked event on the custom cast button
+ ((MediaTransportControlsWithCustomCastButton)this.player.TransportControls).CastButtonClicked += TransportControls_CastButtonClicked;
+
+ // Instantiate the Device Picker
+ picker = new DialDevicePicker();
+
+ //Add the DIAL Filter, so that the application only shows DIAL devices that have
+ // the application installed or advertise that they can install them.
+ picker.Filter.SupportedAppNames.Add(this.dial_appname_textbox.Text);
+
+ //Hook up device selected event
+ picker.DialDeviceSelected += Picker_DeviceSelected;
+
+ //Hook up the picker disconnected event
+ picker.DisconnectButtonClicked += Picker_DisconnectButtonClicked;
+
+ //Hook up the picker dismissed event
+ picker.DialDevicePickerDismissed += Picker_DevicePickerDismissed;
+ }
+ private void TransportControls_CastButtonClicked(object sender, EventArgs e)
+ {
+ rootPage.NotifyUser("Show Device Picker Button Clicked", NotifyType.StatusMessage);
+
+ //Pause Current Playback
+ player.Pause();
+
+ //Get the custom transport controls
+ MediaTransportControlsWithCustomCastButton mtc = (MediaTransportControlsWithCustomCastButton)this.player.TransportControls;
+ //Retrieve the location of the casting button
+ GeneralTransform transform = mtc.CastButton.TransformToVisual(Window.Current.Content as UIElement);
+ Point pt = transform.TransformPoint(new Point(0, 0));
+
+ //Show the picker above our Show Device Picker button
+ picker.Show(new Rect(pt.X, pt.Y, mtc.CastButton.ActualWidth, mtc.CastButton.ActualHeight), Windows.UI.Popups.Placement.Above);
+
+ try
+ {
+ if (activeDialDevice != null)
+ picker.SetDisplayStatus(activeDialDevice, DialDeviceDisplayStatus.Connected);
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+ }
+
+ #region Device Picker Methods
+
+ private async void Picker_DevicePickerDismissed(DialDevicePicker sender, object args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ try
+ {
+ rootPage.NotifyUser(string.Format("Picker DevicePickerDismissed event fired for device"), NotifyType.StatusMessage);
+
+ if (activeDialDevice != null)
+ {
+ // Resume video playback
+ this.player.Play();
+ }
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+ });
+ }
+
+ private async void Picker_DisconnectButtonClicked(DialDevicePicker sender, DialDisconnectButtonClickedEventArgs args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ try
+ {
+ rootPage.NotifyUser(string.Format("Picker DisconnectButtonClicked event fired for device '{0}'", activeDeviceInformation.Name), NotifyType.StatusMessage);
+
+ // Get the DialDevice instance for the selected device
+ DialDevice selectedDialDevice = await DialDevice.FromIdAsync(args.Device.Id);
+ // Update the picker status
+ picker.SetDisplayStatus(selectedDialDevice, DialDeviceDisplayStatus.Connecting);
+
+ DialApp app = selectedDialDevice.GetDialApp(this.dial_appname_textbox.Text);
+
+ //Get the current application state
+ //DialAppStateDetails stateDetails = await app.GetAppStateAsync();
+
+ DialAppStopResult result = await app.StopAsync();
+
+ if (result == DialAppStopResult.Stopped)
+ {
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser("Application stopped successfully.", NotifyType.StatusMessage);
+ picker.SetDisplayStatus(args.Device, DialDeviceDisplayStatus.Disconnected);
+ activeDialDevice = null;
+ activeDeviceInformation = null;
+ picker.Hide();
+ }
+ else
+ {
+ if (result == DialAppStopResult.StopFailed || result == DialAppStopResult.NetworkFailure)
+ {
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser(string.Format("Error occured trying to stop application. Status: '{0}'", result.ToString()), NotifyType.StatusMessage);
+ picker.SetDisplayStatus(args.Device, DialDeviceDisplayStatus.Error);
+ }
+ else //in case of DialAppStopResult.OperationNotSupported, there is not much more you can do. You could implement your own
+ // mechanism to stop the application on that device.
+ {
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser(string.Format("Stop is not supported by device: '{0}'", activeDeviceInformation.Name), NotifyType.ErrorMessage);
+ activeDialDevice = null;
+ activeDeviceInformation = null;
+
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+
+ });
+ }
+
+ private async void Picker_DeviceSelected(DialDevicePicker sender, DialDeviceSelectedEventArgs args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ try {
+ rootPage.NotifyUser(string.Format("Picker DeviceSelected event fired"), NotifyType.StatusMessage);
+
+ // Set the status to connecting
+ picker.SetDisplayStatus(args.SelectedDialDevice, DialDeviceDisplayStatus.Connecting);
+
+ rootPage.NotifyUser(string.Format("Resolving DialDevice'"), NotifyType.StatusMessage);
+
+ //Get the DialApp object for the specific application on the selected device
+ DialApp app = args.SelectedDialDevice.GetDialApp(this.dial_appname_textbox.Text);
+
+ if (app == null)
+ {
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ //rootPage.NotifyUser(string.Format("'{0}' cannot find app with ID '{1}'", selectedDeviceInformation.Name, this.dial_appname_textbox.Text), NotifyType.StatusMessage);
+ picker.SetDisplayStatus(args.SelectedDialDevice, DialDeviceDisplayStatus.Error);
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Attempting to launch '{0}'", app.AppName), NotifyType.StatusMessage);
+ //Launch the application on the 1st screen device
+ DialAppLaunchResult result = await app.RequestLaunchAsync(this.dial_launch_args_textbox.Text);
+
+ //Verify to see whether the application was launched
+ if (result == DialAppLaunchResult.Launched)
+ {
+ rootPage.NotifyUser(string.Format("Launched '{0}'", app.AppName), NotifyType.StatusMessage);
+ activeDialDevice = args.SelectedDialDevice;
+ DeviceInformation selectedDeviceInformation = await DeviceInformation.CreateFromIdAsync(args.SelectedDialDevice.Id);
+
+ activeDeviceInformation = selectedDeviceInformation;
+
+ //This is where you will need to add you application specific communication between your 1st and 2nd screen applications
+ //...
+ //...
+ //...
+
+ picker.SetDisplayStatus(activeDialDevice, DialDeviceDisplayStatus.Connected);
+ picker.Hide();
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Attempting to launch '{0}'", app.AppName), NotifyType.StatusMessage);
+ picker.SetDisplayStatus(args.SelectedDialDevice, DialDeviceDisplayStatus.Error);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+ });
+ }
+
+ #endregion
+
+ #region Media Element Status Methods
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ // Update status
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ // Update status
+ rootPage.NotifyUser(string.Format("Failed to load '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ // Update status
+ rootPage.NotifyUser(string.Format("Openend '{0}'", video.Title), NotifyType.StatusMessage);
+ // Start playback
+ player.Play();
+ }
+
+ #endregion
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml b/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml
new file mode 100644
index 0000000000..dd3eb15857
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml.cs b/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml.cs
new file mode 100644
index 0000000000..7f634e809a
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/04_DIAL_Receiver_App.xaml.cs
@@ -0,0 +1,117 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using ScreenCasting.Util;
+using System;
+using Windows.ApplicationModel.Activation;
+using Windows.Storage;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario04 : Page
+ {
+ private MainPage rootPage;
+ private VideoMetaData video = null;
+ private TimeSpan originalPosition = new TimeSpan(0);
+ public Scenario04()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+ rootPage.SizeChanged += RootPage_SizeChanged;
+ }
+
+ protected async override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+ player.MediaEnded += Player_MediaEnded;
+
+ if (e.Parameter is DialReceiverActivatedEventArgs)
+ {
+ DialReceiverActivatedEventArgs activationArgs = (DialReceiverActivatedEventArgs)e.Parameter;
+
+ //Parse the DIAL arguments from the activation arguments
+ DialLaunchArguments dialArgs = DialLaunchArguments.Parse(activationArgs.Arguments);
+
+ // Get the list of available Azure videos.
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ // Get the vide that is playing
+ video = dataProvider.GetFromID(dialArgs.VideoId);
+ //Set the source on the player
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+ this.player.Source = video.VideoLink;
+ this.LicenseText.Text = "License: " + video.License;
+
+ player.Position = dialArgs.Position;
+ }
+ else
+ {
+ StorageFile localVideo = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/casting.mp4"));
+ var stream = await localVideo.OpenAsync(FileAccessMode.Read);
+ this.player.SetSource(stream, localVideo.FileType);
+ }
+ }
+
+ private void Player_MediaEnded(object sender, RoutedEventArgs e)
+ {
+ if (video == null)
+ {
+ this.player.Position = new TimeSpan(0);
+ this.player.Play();
+ }
+ }
+
+ private void RootPage_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ this.player.Height = this.Height;
+ this.player.Width = this.Width;
+ }
+
+ #region MediaElement Status Changes
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ if (video == null)
+ rootPage.NotifyUser(string.Format("{0}", this.player.CurrentState), NotifyType.StatusMessage);
+ else
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ if (video == null)
+ rootPage.NotifyUser(string.Format("Failed to load"), NotifyType.ErrorMessage);
+ else
+ rootPage.NotifyUser(string.Format("Failed to load '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ if (video == null)
+ rootPage.NotifyUser(string.Format("Openend"), NotifyType.StatusMessage);
+ else
+ rootPage.NotifyUser(string.Format("Openend '{0}'", "Title"), NotifyType.StatusMessage);
+
+ player.Play();
+ }
+
+ #endregion
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml b/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml
new file mode 100644
index 0000000000..a53776d853
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml.cs b/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml.cs
new file mode 100644
index 0000000000..555614d393
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/05_Multi_View_Media_Application.xaml.cs
@@ -0,0 +1,263 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Controls;
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using ScreenCasting.Util;
+using System;
+using Windows.ApplicationModel.Core;
+using Windows.Devices.Enumeration;
+using Windows.Foundation;
+using Windows.UI.Core;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Media.Imaging;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario05 : Page
+ {
+ private MainPage rootPage;
+ private DevicePicker picker;
+ private VideoMetaData video = null;
+ ProjectionViewBroker pvb = new ProjectionViewBroker();
+ DeviceInformation activeDevice = null;
+
+ int thisViewId;
+
+ public Scenario05()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+
+ // Get an Azure hosted video
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ video = dataProvider.GetRandomVideo();
+
+ //Set the source on the player
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+ this.player.Source = video.VideoLink;
+ this.LicenseText.Text = "License: " + video.License;
+
+ //Subscribe for the clicked event on the custom cast button
+ ((MediaTransportControlsWithCustomCastButton)this.player.TransportControls).CastButtonClicked += TransportControls_CastButtonClicked;
+
+ // Instantiate the Device Picker
+ picker = new DevicePicker ();
+
+ // Get the device selecter for Miracast devices
+ picker.Filter.SupportedDeviceSelectors.Add(ProjectionManager.GetDeviceSelector());
+
+ //Hook up device selected event
+ picker.DeviceSelected += Picker_DeviceSelected;
+
+ //Hook up device disconnected event
+ picker.DisconnectButtonClicked += Picker_DisconnectButtonClicked;
+
+ //Hook up picker dismissed event
+ picker.DevicePickerDismissed += Picker_DevicePickerDismissed;
+
+ // Hook up the events that are received when projection is stoppped
+ pvb.ProjectionStopping += Pvb_ProjectionStopping;
+ }
+
+ private void TransportControls_CastButtonClicked(object sender, EventArgs e)
+ {
+ rootPage.NotifyUser("Custom Cast Button Clicked", NotifyType.StatusMessage);
+
+ //Pause Current Playback
+ player.Pause();
+
+ //Get the custom transport controls
+ MediaTransportControlsWithCustomCastButton mtc = (MediaTransportControlsWithCustomCastButton)this.player.TransportControls;
+
+ //Retrieve the location of the casting button
+ GeneralTransform transform = mtc.CastButton.TransformToVisual(Window.Current.Content as UIElement);
+ Point pt = transform.TransformPoint(new Point(0, 0));
+
+ //Show the picker above our custom cast button
+ picker.Show(new Rect(pt.X, pt.Y, mtc.CastButton.ActualWidth, mtc.CastButton.ActualHeight), Windows.UI.Popups.Placement.Above);
+ }
+ private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ try
+ {
+ // Set status to Connecting
+ picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress);
+
+ // Getting the selected device improves debugging
+ DeviceInformation selectedDevice = args.SelectedDevice;
+
+ thisViewId = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().Id;
+
+ // If projection is already in progress, then it could be shown on the monitor again
+ // Otherwise, we need to create a new view to show the presentation
+ if (rootPage.ProjectionViewPageControl == null)
+ {
+ // First, create a new, blank view
+ var thisDispatcher = Window.Current.Dispatcher;
+ await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ // ViewLifetimeControl is a wrapper to make sure the view is closed only
+ // when the app is done with it
+ rootPage.ProjectionViewPageControl = ViewLifetimeControl.CreateForCurrentView();
+
+ // Assemble some data necessary for the new page
+ pvb.MainPageDispatcher = thisDispatcher;
+ pvb.ProjectionViewPageControl = rootPage.ProjectionViewPageControl;
+ pvb.MainViewId = thisViewId;
+
+ // Display the page in the view. Note that the view will not become visible
+ // until "StartProjectingAsync" is called
+ var rootFrame = new Frame();
+ rootFrame.Navigate(typeof(ProjectionViewPage), pvb);
+ Window.Current.Content = rootFrame;
+
+ Window.Current.Activate();
+ });
+ }
+
+ try
+ {
+ // Start/StopViewInUse are used to signal that the app is interacting with the
+ // view, so it shouldn't be closed yet, even if the user loses access to it
+ rootPage.ProjectionViewPageControl.StartViewInUse();
+
+ try
+ {
+ await ProjectionManager.StartProjectingAsync(rootPage.ProjectionViewPageControl.Id, thisViewId, selectedDevice);
+
+ }
+ catch (Exception ex)
+ {
+ if (!ProjectionManager.ProjectionDisplayAvailable || pvb.ProjectedPage == null)
+ throw ex;
+ }
+
+ // ProjectionManager currently can throw an exception even when projection has started.\
+ // Re-throw the exception when projection has not been started after calling StartProjectingAsync
+ if (ProjectionManager.ProjectionDisplayAvailable && pvb.ProjectedPage != null)
+ {
+ this.player.Pause();
+ await pvb.ProjectedPage.SetMediaSource(this.player.Source, this.player.Position);
+ activeDevice = selectedDevice;
+ // Set status to Connected
+ picker.SetDisplayStatus(args.SelectedDevice, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
+ picker.Hide();
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Projection has failed to '{0}'", selectedDevice.Name), NotifyType.ErrorMessage);
+ // Set status to Failed
+ picker.SetDisplayStatus(args.SelectedDevice, "Connection Failed", DevicePickerDisplayStatusOptions.ShowRetryButton);
+ }
+ }
+ catch (Exception)
+ {
+ rootPage.NotifyUser(string.Format("Projection has failed to '{0}'", selectedDevice.Name), NotifyType.ErrorMessage);
+ // Set status to Failed
+ try { picker.SetDisplayStatus(args.SelectedDevice, "Connection Failed", DevicePickerDisplayStatusOptions.ShowRetryButton); } catch { }
+ }
+ }
+ catch (Exception ex)
+ {
+ UnhandledExceptionPage.ShowUnhandledException(ex);
+ }
+ });
+ }
+ private async void Picker_DevicePickerDismissed(DevicePicker sender, object args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ if (activeDevice == null)
+ {
+ player.Play();
+ }
+ });
+ }
+ private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);
+ //Update the display status for the selected device.
+ sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);
+
+ if (this.pvb.ProjectedPage != null)
+ this.pvb.ProjectedPage.StopProjecting();
+
+ //Update the display status for the selected device.
+ sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None);
+ rootPage.NotifyUser("Disconnected", NotifyType.StatusMessage);
+
+ // Set the active device variables to null
+ activeDevice = null;
+ });
+ }
+
+ private async void Pvb_ProjectionStopping(object sender, EventArgs e)
+ {
+ ProjectionViewBroker broker = sender as ProjectionViewBroker;
+
+ TimeSpan position = broker.ProjectedPage.Player.Position;
+ Uri source = broker.ProjectedPage.Player.Source;
+
+ await rootPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Resuming playback on the first screen", NotifyType.StatusMessage);
+ this.player.Source = source;
+
+ this.player.Position = position;
+ this.player.Play();
+ rootPage.ProjectionViewPageControl = null;
+ });
+ }
+
+ #region MediaElement Status Methods
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ // Update status
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Failed to load '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Openend '{0}'", video.Title), NotifyType.StatusMessage);
+
+ player.Play();
+ }
+
+ #endregion
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml b/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml
new file mode 100644
index 0000000000..eaebb49a1a
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml.cs b/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml.cs
new file mode 100644
index 0000000000..82df56d4a8
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/06_Combine_Casting_Tech.xaml.cs
@@ -0,0 +1,575 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+using Windows.UI.Xaml.Media;
+using Windows.Media.DialProtocol;
+using ScreenCasting.Data.Azure;
+using ScreenCasting.Data.Common;
+using Windows.Devices.Enumeration;
+using System.Threading.Tasks;
+using Windows.Media.Casting;
+using ScreenCasting.Controls;
+using ScreenCasting.Util;
+using Windows.UI.ViewManagement;
+using Windows.ApplicationModel.Core;
+using Windows.UI.Core;
+using Windows.Storage;
+
+namespace ScreenCasting
+{
+ public sealed partial class Scenario06 : Page
+ {
+ private const int MAX_RESULTS = 10;
+
+ private MainPage rootPage;
+ private DevicePicker picker = null;
+ private DeviceInformation activeDevice = null;
+ private object activeCastConnectionHandler = null;
+ private VideoMetaData video = null;
+ int thisViewId;
+
+ public Scenario06()
+ {
+ this.InitializeComponent();
+
+ rootPage = MainPage.Current;
+
+ //Subscribe to player events
+ player.MediaOpened += Player_MediaOpened;
+ player.MediaFailed += Player_MediaFailed;
+ player.CurrentStateChanged += Player_CurrentStateChanged;
+
+ // Get an Azure hosted video
+ AzureDataProvider dataProvider = new AzureDataProvider();
+ video = dataProvider.GetRandomVideo();
+
+ //Set the source on the player
+ rootPage.NotifyUser(string.Format("Opening '{0}'", video.Title), NotifyType.StatusMessage);
+ this.player.Source = video.VideoLink;
+ this.LicenseText.Text = "License: " + video.License;
+
+ //Configure the DIAL launch arguments for the current video
+ this.dial_launch_args_textbox.Text = string.Format("v={0}&t=0&pairingCode=E4A8136D-BCD3-45F4-8E49-AE01E9A46B5F", video.Id);
+
+ //Subscribe for the clicked event on the custom cast button
+ ((MediaTransportControlsWithCustomCastButton)this.player.TransportControls).CastButtonClicked += TransportControls_CastButtonClicked;
+
+ // Instantiate the Device Picker
+ picker = new DevicePicker();
+
+ //Hook up device selected event
+ picker.DeviceSelected += Picker_DeviceSelected;
+
+ //Hook up device disconnected event
+ picker.DisconnectButtonClicked += Picker_DisconnectButtonClicked;
+
+ //Hook up device disconnected event
+ picker.DevicePickerDismissed += Picker_DevicePickerDismissed;
+
+ //Add the DIAL Filter, so that the application only shows DIAL devices that have the application installed or advertise that they can install them.
+ //BUG: picker.Filter.SupportedDeviceSelectors.Add(DialDevice.GetDeviceSelector(this.dial_appname_textbox.Text));
+ picker.Filter.SupportedDeviceSelectors.Add("System.Devices.DevObjectType:=6 AND System.Devices.AepContainer.ProtocolIds:~~{0E261DE4-12F0-46E6-91BA-428607CCEF64} AND System.Devices.AepContainer.Categories:~~Multimedia.ApplicationLauncher.DIAL");
+
+ //Add the CAST API Filter, so that the application only shows Miracast, Bluetooth, DLNA devices that can render the video
+ // BUG: picker.Filter.SupportedDeviceSelectors.Add(await CastingDevice.GetDeviceSelectorFromCastingSourceAsync(player.GetAsCastingSource()));
+ // BUG: picker.Filter.SupportedDeviceSelectors.Add(CastingDevice.GetDeviceSelector(CastingPlaybackTypes.Video));
+ picker.Filter.SupportedDeviceSelectors.Add("System.Devices.InterfaceClassGuid:=\"{D0875FB4-2196-4c7a-A63D-E416ADDD60A1}\"" + " AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True");
+
+ //Add projection manager filter
+ picker.Filter.SupportedDeviceSelectors.Add(ProjectionManager.GetDeviceSelector());
+
+ pvb.ProjectionStopping += Pvb_ProjectionStopping;
+ }
+
+ ProjectionViewBroker pvb = new ProjectionViewBroker();
+
+ private void TransportControls_CastButtonClicked(object sender, EventArgs e)
+ {
+ //Pause Current Playback
+ player.Pause();
+
+ rootPage.NotifyUser("Show Device Picker Button Clicked", NotifyType.StatusMessage);
+
+ //Get the custom transport controls
+ MediaTransportControlsWithCustomCastButton mtc = (MediaTransportControlsWithCustomCastButton)this.player.TransportControls;
+ //Retrieve the location of the casting button
+ GeneralTransform transform = mtc.CastButton.TransformToVisual(Window.Current.Content as UIElement);
+ Point pt = transform.TransformPoint(new Point(0, 0));
+
+ //Show the picker above our Show Device Picker button
+ picker.Show(new Rect(pt.X, pt.Y, mtc.CastButton.ActualWidth, mtc.CastButton.ActualHeight), Windows.UI.Popups.Placement.Above);
+ }
+
+ #region Windows.Devices.Enumeration.DevicePicker Methods
+ private async void Picker_DeviceSelected(DevicePicker sender, DeviceSelectedEventArgs args)
+ {
+ string deviceId = args.SelectedDevice.Id;
+
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ //Update the display status for the selected device to connecting.
+ try { picker.SetDisplayStatus(args.SelectedDevice, "Connecting", DevicePickerDisplayStatusOptions.ShowProgress); } catch { }
+
+ //The selectedDeviceInfo instance is needed to be able to update the picker.
+ DeviceInformation selectedDeviceInfo = args.SelectedDevice;
+#if DEBUG
+ // The args.SelectedCastingDevice is proxied from the picker process. The picker process is
+ // dismissmed as soon as you break into the debugger. Creating a non-proxied version
+ // allows debugging since the proxied version stops working once the picker is dismissed.
+ selectedDeviceInfo = await DeviceInformation.CreateFromIdAsync(args.SelectedDevice.Id);
+#endif
+
+ bool castSucceeded = false;
+
+ // If the ProjectionManager API did not work and the device id will have 'dial' in it.
+ castSucceeded = await TryLaunchDialAppAsync(selectedDeviceInfo);
+
+ // If it doesn't try the ProjectionManager API.
+ if (!castSucceeded)
+ castSucceeded = await TryProjectionManagerCastAsync(selectedDeviceInfo);
+
+ //If DIAL and ProjectionManager did not work for the selected device, try the CAST API
+ if (!castSucceeded)
+ castSucceeded = await TryCastMediaElementAsync(selectedDeviceInfo);
+
+ if (castSucceeded)
+ {
+ //Update the display status for the selected device. Try Catch in case the picker is not visible anymore.
+ try { picker.SetDisplayStatus(selectedDeviceInfo, "Connected", DevicePickerDisplayStatusOptions.ShowDisconnectButton); } catch { }
+
+ // Hide the picker now that all the work is completed. Try Catch in case the picker is not visible anymore.
+ try { picker.Hide(); } catch { }
+ }
+ else
+ {
+ //Show a retry button when connecting to the selected device failed.
+ try { picker.SetDisplayStatus(selectedDeviceInfo, "Connecting failed", DevicePickerDisplayStatusOptions.ShowRetryButton); } catch { }
+ }
+ });
+ }
+ private async void Picker_DevicePickerDismissed(DevicePicker sender, object args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ if (activeDevice == null)
+ {
+ player.Play();
+ }
+ });
+ }
+ private async void Picker_DisconnectButtonClicked(DevicePicker sender, DeviceDisconnectButtonClickedEventArgs args)
+ {
+ //Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ rootPage.NotifyUser("Disconnect Button clicked", NotifyType.StatusMessage);
+
+ //Update the display status for the selected device.
+ sender.SetDisplayStatus(args.Device, "Disconnecting", DevicePickerDisplayStatusOptions.ShowProgress);
+
+ bool disconnected = false;
+ if (this.activeCastConnectionHandler is ProjectionViewBroker)
+ disconnected = TryStopProjectionManagerAsync((ProjectionViewBroker)activeCastConnectionHandler);
+ if (this.activeCastConnectionHandler is DialApp)
+ disconnected = await TryStopDialAppAsync((DialApp)activeCastConnectionHandler);
+ if (this.activeCastConnectionHandler is CastingConnection)
+ disconnected = await TryDisconnectCastingSessionAsync((CastingConnection)activeCastConnectionHandler);
+
+ if (disconnected)
+ {
+ //Update the display status for the selected device.
+ try { sender.SetDisplayStatus(args.Device, "Disconnected", DevicePickerDisplayStatusOptions.None); } catch { }
+ // Set the active device variables to null
+ activeDevice = null;
+ activeCastConnectionHandler = null;
+
+ //Hide the picker
+ sender.Hide();
+ }
+ else
+ {
+ //Update the display status for the selected device.
+ sender.SetDisplayStatus(args.Device, "Disconnect failed", DevicePickerDisplayStatusOptions.ShowDisconnectButton);
+ }
+ });
+ }
+
+ #endregion
+
+ #region ProjectionManager APIs
+ private async Task TryProjectionManagerCastAsync(DeviceInformation device)
+ {
+ bool projectionManagerCastAsyncSucceeded = false;
+
+ if ((activeDevice ==null && ProjectionManager.ProjectionDisplayAvailable && device == null) || device != null)
+ {
+ thisViewId = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().Id;
+
+ // If projection is already in progress, then it could be shown on the monitor again
+ // Otherwise, we need to create a new view to show the presentation
+ if (rootPage.ProjectionViewPageControl == null)
+ {
+ // First, create a new, blank view
+ var thisDispatcher = Window.Current.Dispatcher;
+ await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ // ViewLifetimeControl is a wrapper to make sure the view is closed only
+ // when the app is done with it
+ rootPage.ProjectionViewPageControl = ViewLifetimeControl.CreateForCurrentView();
+
+ // Assemble some data necessary for the new page
+ pvb.MainPageDispatcher = thisDispatcher;
+ pvb.ProjectionViewPageControl = rootPage.ProjectionViewPageControl;
+ pvb.MainViewId = thisViewId;
+
+ // Display the page in the view. Note that the view will not become visible
+ // until "StartProjectingAsync" is called
+ var rootFrame = new Frame();
+ rootFrame.Navigate(typeof(ProjectionViewPage), pvb);
+ Window.Current.Content = rootFrame;
+ Window.Current.Activate();
+ });
+ }
+
+ try
+ {
+ // Start/StopViewInUse are used to signal that the app is interacting with the
+ // view, so it shouldn't be closed yet, even if the user loses access to it
+ rootPage.ProjectionViewPageControl.StartViewInUse();
+
+ try
+ {
+ rootPage.NotifyUser(string.Format("Starting projection of '{0}' on a second view '{1}' using ProjectionManager", video.Title, device.Name), NotifyType.StatusMessage);
+
+ await ProjectionManager.StartProjectingAsync(rootPage.ProjectionViewPageControl.Id, thisViewId, device);
+ }
+ catch (Exception ex)
+ {
+ if (!ProjectionManager.ProjectionDisplayAvailable)
+ throw ex;
+ }
+
+ if (pvb.ProjectedPage != null)
+ {
+ this.player.Pause();
+ await pvb.ProjectedPage.SetMediaSource(this.player.Source, this.player.Position);
+ }
+ if (device != null)
+ {
+ activeDevice = device;
+ activeCastConnectionHandler = pvb;
+ }
+ projectionManagerCastAsyncSucceeded = true;
+
+ rootPage.NotifyUser(string.Format("Displaying '{0}' on a second view '{1}' using ProjectionManager", video.Title, device.Name), NotifyType.StatusMessage);
+ }
+ catch (Exception)
+ {
+ rootPage.NotifyUser("The projection view is being disposed", NotifyType.ErrorMessage);
+ }
+ ApplicationView.GetForCurrentView().ExitFullScreenMode();
+ }
+ return projectionManagerCastAsyncSucceeded;
+ }
+ private bool TryStopProjectionManagerAsync(ProjectionViewBroker broker)
+ {
+ broker.ProjectedPage.StopProjecting();
+ return true;
+ }
+
+
+ private async void Pvb_ProjectionStopping(object sender, EventArgs e)
+ {
+ ProjectionViewBroker broker = sender as ProjectionViewBroker;
+
+ TimeSpan position = broker.ProjectedPage.Player.Position;
+ Uri source = broker.ProjectedPage.Player.Source;
+
+ await rootPage.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Resuming playback on the first screen", NotifyType.StatusMessage);
+ this.player.Source = source;
+ this.player.Position = position;
+ this.player.Play();
+ rootPage.ProjectionViewPageControl = null;
+ });
+ }
+
+ #endregion
+
+ #region Windows.Media.Casting APIs
+
+ private async Task TryCastMediaElementAsync(DeviceInformation device)
+ {
+ bool castMediaElementSucceeded = false;
+
+ //Verify whether the selected device supports DLNA, Bluetooth, or Miracast.
+ rootPage.NotifyUser(string.Format("Checking to see if device {0} supports Miracast, Bluetooth, or DLNA", device.Name), NotifyType.StatusMessage);
+
+ CastingConnection connection = null;
+
+ //Check to see whether we are casting to the same device
+ if (activeDevice != null && device.Id == activeDevice.Id)
+ connection = activeCastConnectionHandler as CastingConnection;
+ else // if not casting to the same device reset the active device related variables.
+ {
+ activeDevice = null;
+ activeCastConnectionHandler = null;
+ }
+
+ // If we can re-use the existing connection
+ if (connection == null || connection.State == CastingConnectionState.Disconnected || connection.State == CastingConnectionState.Disconnecting)
+ {
+ CastingDevice castDevice = null;
+ activeDevice = null;
+
+ //Try to create a CastingDevice instannce. If it doesn't succeed, the selected device does not support playback of the video source.
+ rootPage.NotifyUser(string.Format("Attempting to resolve casting device for '{0}'", device.Name), NotifyType.StatusMessage);
+ try { castDevice = await CastingDevice.FromIdAsync(device.Id); } catch { }
+
+ if (castDevice == null)
+ {
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ rootPage.NotifyUser(string.Format("'{0}' does not support playback of this media", device.Name), NotifyType.StatusMessage);
+ }
+ else
+ {
+ //Create a casting conneciton from our selected casting device
+ rootPage.NotifyUser(string.Format("Creating connection for '{0}'", device.Name), NotifyType.StatusMessage);
+ connection = castDevice.CreateCastingConnection();
+
+ //Hook up the casting events
+ connection.ErrorOccurred += Connection_ErrorOccurred;
+ connection.StateChanged += Connection_StateChanged;
+ }
+
+ //Cast the content loaded in the media element to the selected casting device
+ rootPage.NotifyUser(string.Format("Casting to '{0}'", device.Name), NotifyType.StatusMessage);
+
+ CastingSource source = null;
+ // Get the casting source
+ try { source = player.GetAsCastingSource(); } catch { }
+
+ if (source == null)
+ {
+ rootPage.NotifyUser(string.Format("Failed to get casting source for video '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ else
+ {
+ CastingConnectionErrorStatus status = await connection.RequestStartCastingAsync(source);
+
+ if (status == CastingConnectionErrorStatus.Succeeded)
+ {
+ //Remember the device to which casting succeeded
+ activeDevice = device;
+ //Remember the current active connection.
+ activeCastConnectionHandler = connection;
+ castMediaElementSucceeded = true;
+ player.Play();
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Failed to cast to '{0}'", device.Name), NotifyType.ErrorMessage);
+ }
+ }
+ }
+ return castMediaElementSucceeded;
+ }
+ private async void Connection_StateChanged(CastingConnection sender, object args)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Casting Connection State Changed: " + sender.State, NotifyType.StatusMessage);
+ });
+ }
+ private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
+ {
+ await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ rootPage.NotifyUser("Casting Error Occured: " + args.Message, NotifyType.ErrorMessage);
+ activeDevice = null;
+ activeCastConnectionHandler = null;
+ });
+ }
+ private async Task TryDisconnectCastingSessionAsync(CastingConnection connection)
+ {
+ bool disconnected = false;
+
+ //Disconnect the casting session
+ CastingConnectionErrorStatus status = await connection.DisconnectAsync();
+
+ if (status == CastingConnectionErrorStatus.Succeeded)
+ {
+ rootPage.NotifyUser("Connection disconnected successfully.", NotifyType.StatusMessage);
+ disconnected = true;
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Failed to disconnect connection with reason {0}.", status.ToString()), NotifyType.ErrorMessage);
+ }
+
+ return disconnected;
+ }
+
+ #endregion
+
+ #region Windows.Media.DialProtocol APIs
+ private async Task TryLaunchDialAppAsync(DeviceInformation device)
+ {
+ bool dialAppLaunchSucceeded = false;
+
+ //Update the launch arguments to include the Position
+ this.dial_launch_args_textbox.Text = string.Format("v={0}&t={1}&pairingCode=E4A8136D-BCD3-45F4-8E49-AE01E9A46B5F", video.Id, player.Position.Ticks);
+
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ rootPage.NotifyUser(string.Format("Checking to see if device {0} supports DIAL", device.Name), NotifyType.StatusMessage);
+
+ DialDevice dialDevice = null;
+
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ rootPage.NotifyUser(string.Format("Attempting to resolve DIAL device for '{0}'", device.Name), NotifyType.StatusMessage);
+
+ string[] newIds = (string[])device.Properties["{0BBA1EDE-7566-4F47-90EC-25FC567CED2A} 2"];
+
+ if (newIds.Length > 0)
+ {
+ string deviceId = newIds[0];
+ try { dialDevice = await DialDevice.FromIdAsync(deviceId); } catch { }
+ }
+
+ if (dialDevice == null)
+ {
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ rootPage.NotifyUser(string.Format("'{0}' does not support DIAL", device.Name), NotifyType.StatusMessage);
+ }
+ else
+ {
+ //Get the DialApp object for the specific application on the selected device
+ DialApp app = dialDevice.GetDialApp(this.dial_appname_textbox.Text);
+
+ if (app == null)
+ {
+ //Try to create a DIAL device. If it doesn't succeed, the selected device does not support DIAL.
+ rootPage.NotifyUser(string.Format("'{0}' cannot find app with ID '{1}'", device.Name, this.dial_appname_textbox.Text), NotifyType.StatusMessage);
+ }
+ else
+ {
+ rootPage.NotifyUser(string.Format("Attempting to launch '{0}'", app.AppName), NotifyType.StatusMessage);
+ //Launch the application on the 1st screen device
+ DialAppLaunchResult result = await app.RequestLaunchAsync(this.dial_launch_args_textbox.Text);
+
+ //Verify to see whether the application was launched
+ if (result == DialAppLaunchResult.Launched)
+ {
+ //Remember the device to which casting succeeded
+ activeDevice = device;
+ //DIAL is sessionsless but the DIAL app allows us to get the state and "disconnect".
+ //Disconnect in the case of DIAL is equivalenet to stopping the app.
+ activeCastConnectionHandler = app;
+ rootPage.NotifyUser(string.Format("Launched '{0}'", app.AppName), NotifyType.StatusMessage);
+ //This is where you will need to add you application specific communication between your 1st and 2nd screen applications
+ //...
+
+
+ dialAppLaunchSucceeded = true;
+ }
+ }
+ }
+
+ return dialAppLaunchSucceeded;
+ }
+ private async Task TryStopDialAppAsync(DialApp app)
+ {
+ bool stopped = false;
+
+ //Get the current application state
+ DialAppStateDetails stateDetails = await app.GetAppStateAsync();
+
+ switch (stateDetails.State)
+ {
+ case DialAppState.NetworkFailure:
+ {
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser("Network Failure while getting application state", NotifyType.ErrorMessage);
+ break;
+ }
+ case DialAppState.Stopped:
+ {
+ stopped = true;
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser("Application was already stopped.", NotifyType.StatusMessage);
+ break;
+ }
+ default:
+ {
+ DialAppStopResult result = await app.StopAsync();
+
+ if (result == DialAppStopResult.Stopped)
+ {
+ stopped = true;
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser("Application stopped successfully.", NotifyType.StatusMessage);
+ }
+ else
+ {
+ if (result == DialAppStopResult.StopFailed || result == DialAppStopResult.NetworkFailure)
+ {
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser(string.Format("Error occured trying to stop application. Status: '{0}'", result.ToString()), NotifyType.StatusMessage);
+ }
+ else //in case of DialAppStopResult.OperationNotSupported, there is not much more you can do. You could implement your own
+ // mechanism to stop the application on that device.
+ {
+ stopped = true;
+ // In case getting the application state failed because of a network failure, you could add retry logic
+ rootPage.NotifyUser(string.Format("Stop is not supported by device: '{0}'", activeDevice.Name), NotifyType.ErrorMessage);
+ }
+ }
+ break;
+ }
+ }
+ return stopped;
+ }
+
+ #endregion
+
+ #region Media Element Status Methods
+ private void Player_CurrentStateChanged(object sender, RoutedEventArgs e)
+ {
+ // Update status
+ rootPage.NotifyUser(string.Format("{0} '{1}'", this.player.CurrentState, video.Title), NotifyType.StatusMessage);
+ }
+ private void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Failed to load '{0}'", video.Title), NotifyType.ErrorMessage);
+ }
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ rootPage.NotifyUser(string.Format("Openend '{0}'", video.Title), NotifyType.StatusMessage);
+
+ player.Play();
+ }
+
+ #endregion
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ rootPage = MainPage.Current;
+ }
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/AdvancedCasting.csproj b/Samples/AdvancedCasting/cs/AdvancedCasting.csproj
new file mode 100644
index 0000000000..3e1a571ecd
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/AdvancedCasting.csproj
@@ -0,0 +1,232 @@
+
+
+
+
+ Debug
+ x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}
+ AppContainerExe
+ Properties
+ ScreenCasting
+ ScreenCasting
+ en-US
+ UAP
+ 10.0.10240.0
+ 10.0.10240.0
+ 14
+ true
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UAP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+ 02_Casting_API_CastButton.xaml
+
+
+ 03_DIAL_Sender_API.xaml
+
+
+ 05_Multi_View_Media_Application.xaml
+
+
+ 06_Combine_Casting_Tech.xaml
+
+
+
+ UnhandledExceptionPage.xaml
+
+
+ App.xaml
+
+
+
+
+
+
+
+
+ MainPage.xaml
+
+
+ ProjectionViewPage.xaml
+
+
+
+
+ 01_MediaElement.xaml
+
+
+ 04_DIAL_Receiver_App.xaml
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Styles\Styles.xaml
+ MSBuild:Compile
+ Designer
+
+
+
+
+ Properties\Default.rd.xml
+
+
+ Assets\casting.mp4
+
+
+ Assets\smallTile-sdk.png
+
+
+ Assets\splash-sdk.png
+
+
+ Assets\squareTile-sdk.png
+
+
+ Assets\storeLogo-sdk.png
+
+
+ Assets\tile-sdk.png
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdvancedCasting/cs/AdvancedCasting.sln b/Samples/AdvancedCasting/cs/AdvancedCasting.sln
new file mode 100644
index 0000000000..b3a186300f
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/AdvancedCasting.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedCasting", "AdvancedCasting.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
+ {DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Samples/AdvancedCasting/cs/App.xaml b/Samples/AdvancedCasting/cs/App.xaml
new file mode 100644
index 0000000000..3546dae999
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/App.xaml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/App.xaml.cs b/Samples/AdvancedCasting/cs/App.xaml.cs
new file mode 100644
index 0000000000..cb79a52d21
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/App.xaml.cs
@@ -0,0 +1,166 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
+
+namespace ScreenCasting
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ sealed partial class App : Application
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += OnSuspending;
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ this.DebugSettings.EnableFrameRateCounter = false;
+
+ }
+
+#endif
+ Application.Current.UnhandledException += Current_UnhandledException;
+
+ Window.Current.Activate();
+
+ 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();
+ // Set the default language
+ rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+ {
+ //TODO: Load state from previously suspended application
+ }
+
+ // Place the frame in the current Window
+ Window.Current.Content = rootFrame;
+ Window.Current.Activate();
+ }
+
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ try
+ {
+ rootFrame.Navigate(typeof(MainPage), e);
+ }
+ catch (Exception ex)
+ {
+ Window.Current.Content = new Frame();
+ Window.Current.Activate();
+ rootFrame.Navigate(typeof(UnhandledExceptionPage), e.Arguments);
+ ((UnhandledExceptionPage)rootFrame.Content).StatusMessage = ex.Message + ex.StackTrace;
+ }
+
+ }
+
+
+ // Ensure the current window is active
+ Window.Current.Activate();
+ }
+
+ private void Current_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ Window.Current.Content = new Frame();
+ Frame rootFrame = Window.Current.Content as Frame;
+ Window.Current.Activate();
+ rootFrame.Navigate(typeof(UnhandledExceptionPage));
+ ((UnhandledExceptionPage)rootFrame.Content).StatusMessage = e.Exception.Message + e.Exception.StackTrace;
+ }
+
+ protected override void OnActivated(IActivatedEventArgs args)
+ {
+ try
+ {
+ Window.Current.Content = new Frame();
+ Frame rootFrame = Window.Current.Content as Frame;
+ Window.Current.Activate();
+
+
+ if (args.Kind == ActivationKind.DialReceiver)
+ {
+ rootFrame.Navigate(typeof(MainPage), args);
+ }
+ else
+ {
+ rootFrame.Navigate(typeof(MainPage));
+ }
+ base.OnActivated(args);
+ }
+ catch (Exception ex)
+ {
+ Window.Current.Content = new Frame();
+ Frame rootFrame = Window.Current.Content as Frame;
+ Window.Current.Activate();
+ rootFrame.Navigate(typeof(UnhandledExceptionPage));
+ ((UnhandledExceptionPage)rootFrame.Content).StatusMessage = ex.Message + ex.StackTrace;
+ }
+ }
+
+ ///
+ /// Invoked when Navigation to a certain page fails
+ ///
+ /// The Frame which failed navigation
+ /// Details about the navigation failure
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+
+ ///
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ ///
+ /// The source of the suspend request.
+ /// Details about the suspend request.
+ private void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+ //TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Controls/MediaTransportControlsWithCustomCastButton.cs b/Samples/AdvancedCasting/cs/Controls/MediaTransportControlsWithCustomCastButton.cs
new file mode 100644
index 0000000000..8a66777aab
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Controls/MediaTransportControlsWithCustomCastButton.cs
@@ -0,0 +1,55 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Documents;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+namespace ScreenCasting.Controls
+{
+ public sealed class MediaTransportControlsWithCustomCastButton : MediaTransportControls
+ {
+
+ public MediaTransportControlsWithCustomCastButton()
+ {
+ this.DefaultStyleKey = typeof(MediaTransportControlsWithCustomCastButton);
+ }
+
+ public event EventHandler CastButtonClicked;
+ private void CastButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (CastButtonClicked != null)
+ CastButtonClicked(this, EventArgs.Empty);
+ }
+
+ public Button CastButton
+ {
+ get { return this.GetTemplateChild("CustomCastButton") as Button; }
+ }
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ this.IsCompact = true;
+
+ CastButton.Click += CastButton_Click;
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Controls/ProjectedMediaTransportControls.cs b/Samples/AdvancedCasting/cs/Controls/ProjectedMediaTransportControls.cs
new file mode 100644
index 0000000000..803042b4e5
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Controls/ProjectedMediaTransportControls.cs
@@ -0,0 +1,65 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Documents;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+
+namespace ScreenCasting.Controls
+{
+ public sealed class ProjectedMediaTransportControls : MediaTransportControls
+ {
+
+ public ProjectedMediaTransportControls()
+ {
+ this.DefaultStyleKey = typeof(ProjectedMediaTransportControls);
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ //Find the Swap Views button and subscribe to the clicked event.
+ Button swapViewsButton = GetTemplateChild("SwapViewsButton") as Button;
+ swapViewsButton.Click += SwapViewsButton_Click;
+
+ //Find the Stop Projecting button and subscribe to the clicked event.
+ Button stopProjectingButton = GetTemplateChild("StopProjectingButton") as Button;
+ stopProjectingButton.Click += StopProjectingButton_Click;
+
+ this.IsCompact = true;
+ }
+
+ public event EventHandler StopProjectingButtonClick;
+ public event EventHandler SwapViewsButtonClick;
+
+ private void StopProjectingButton_Click (object sender, RoutedEventArgs e)
+ {
+ if (StopProjectingButtonClick != null)
+ StopProjectingButtonClick(this, EventArgs.Empty);
+ }
+
+ private void SwapViewsButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (SwapViewsButtonClick != null)
+ SwapViewsButtonClick(this, EventArgs.Empty);
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Controls/ProjectionViewBroker.cs b/Samples/AdvancedCasting/cs/Controls/ProjectionViewBroker.cs
new file mode 100644
index 0000000000..f4a39c81f4
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Controls/ProjectionViewBroker.cs
@@ -0,0 +1,43 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Controls;
+using ScreenCasting.Util;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+using Windows.UI.Xaml.Controls;
+
+namespace ScreenCasting
+{
+ // This is a simple container for a set of data used to comminicate between the main and the projection view
+ internal class ProjectionViewBroker
+ {
+ public CoreDispatcher MainPageDispatcher;
+ public ViewLifetimeControl ProjectionViewPageControl;
+ public int MainViewId;
+ public event EventHandler ProjectionStopping;
+ public ProjectionViewPage ProjectedPage;
+ public void NotifyProjectionStopping()
+ {
+ try
+ {
+ if (ProjectionStopping != null)
+ ProjectionStopping(this, EventArgs.Empty);
+ }
+ catch { }
+ }
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Data/Azure/AzureDataProvider.cs b/Samples/AdvancedCasting/cs/Data/Azure/AzureDataProvider.cs
new file mode 100644
index 0000000000..c669944b0d
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Data/Azure/AzureDataProvider.cs
@@ -0,0 +1,106 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Web.Syndication;
+using ScreenCasting.Data.Common;
+
+namespace ScreenCasting.Data.Azure
+{
+ public class AzureDataProvider : ItemsDataProvider
+ {
+ private static Dictionary s_metaDataList = null;
+ private const int MAX_RESULTS = 10;
+ public override VideoMetaData GetRandomVideo ()
+ {
+ List videos = GetAll(MAX_RESULTS);
+ Random indexRandomizer = new Random();
+
+ // Pick a random video
+ return videos[indexRandomizer.Next(0, videos.Count - 1)];
+ }
+ public override List GetAll(int max_results)
+ {
+ if (s_metaDataList == null)
+ {
+ Dictionary l = new Dictionary();
+
+ VideoMetaData video1 = new VideoMetaData();
+ video1.Id = "AzureMediaServicesOverview";
+ video1.PubDate = DateTime.Now;
+ video1.VideoLink = new Uri("http://amssamples.streaming.mediaservices.windows.net/91492735-c523-432b-ba01-faba6c2206a2/AzureMediaServicesPromo.ism/manifest(format=m3u8-aapl)");
+ video1.Title = "Azure Media Services Overview";
+ video1.WebPageLink = new Uri("http://amsplayer.azurewebsites.net/amssamples.html");
+ video1.License = "(C) Microsoft Coorporation | All Rights Reserved";
+ video1.Thumbnail = new Uri("http://t3.gstatic.com/images?q=tbn:ANd9GcRoTu81vs8GuQtJBGUZ0pLEiNHVVx3dFwHsu7JCkvGop8Z-98EsPg");
+ l.Add(video1.Id, video1);
+
+ VideoMetaData video2 = new VideoMetaData();
+ video2.Id = "BigBuckBunnyTrailer";
+ video2.PubDate = DateTime.Now;
+ video2.VideoLink = new Uri("http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_480p_surround-fix.avi");
+ video2.Title = "Big Buck Bunny";
+ video2.WebPageLink = new Uri("https://peach.blender.org/");
+ video2.License = "(CC) Blender Foundation | peach.blender.org";
+ video2.Thumbnail = new Uri("http://t0.gstatic.com/images?q=tbn:ANd9GcQT54UKh0zX5OUDNLRyXOOwt3pqj0lpaLCJebucva2LSV49aGjRfg");
+ l.Add(video2.Id, video2);
+
+ VideoMetaData video3 = new VideoMetaData();
+ video3.Id = "bc57e088-27ec-44e0-ac20-a85ccbcd50da";
+ video3.PubDate = DateTime.Now;
+ video3.VideoLink = new Uri("http://amssamples.streaming.mediaservices.windows.net/bc57e088-27ec-44e0-ac20-a85ccbcd50da/TearsOfSteel.ism/manifest(format=mpd-time-csf)");
+ video3.Title = "Tears of Steel";
+ video3.WebPageLink = new Uri("https://mango.blender.org/");
+ video3.License = "(CC) Blender Foundation | durian.blender.org/";
+ video3.Thumbnail = new Uri("http://t3.gstatic.com/images?q=tbn:ANd9GcQO0MMO_vXf8Q1zjZWLHa1_566Mf_jty6vJKRi9R-C_0W-gXnNOog");
+ l.Add(video3.Id, video3);
+
+ //VideoMetaData video4 = new VideoMetaData();
+ //video4.Id = "b6822ec8-5c2b-4ae0-a851-fd46a78294e9";
+ //video4.PubDate = DateTime.Now;
+ //video4.VideoLink = new Uri("http://amssamples.streaming.mediaservices.windows.net/b6822ec8-5c2b-4ae0-a851-fd46a78294e9/ElephantsDream.ism/manifest(filtername=FirstFilter,format=mpd-time-csf)");
+ //video4.Title = "Elephants Dream";
+ //video4.WebPageLink = new Uri("https://orange.blender.org/");
+ //video4.License = "(c) copyright 2006, Blender Foundation / Netherlands Media Art Institute / www.elephantsdream.org";
+ //video4.Thumbnail = new Uri("https://orange.blender.org/wp-content/uploads/2006/05/edscore_cover_l.jpg");
+ //l.Add(video4.Id, video4);
+
+
+ VideoMetaData video5 = new VideoMetaData();
+ video5.Id = "49b57c87-f5f3-48b3-ba22-c55cfdffa9cb";
+ video5.PubDate = DateTime.Now;
+ video5.VideoLink = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
+ video5.Title = "Sintel";
+ video5.WebPageLink = new Uri("https://durian.blender.org/");
+ video5.License = "© copyright Blender Foundation | www.sintel.org";
+ video5.Thumbnail = new Uri("https://durian.blender.org/wp-content/uploads/2010/05/sintel_trailer_1080.jpg");
+ l.Add(video5.Id, video5);
+ s_metaDataList = l;
+ }
+ return s_metaDataList.Values.ToList();
+ }
+
+ public override VideoMetaData GetFromID(string id)
+ {
+ if (s_metaDataList == null)
+ GetAll(20);
+
+ VideoMetaData video = s_metaDataList[id];
+
+ return video;
+ }
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Data/Common/ItemsDataProvider.cs b/Samples/AdvancedCasting/cs/Data/Common/ItemsDataProvider.cs
new file mode 100644
index 0000000000..e26313b534
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Data/Common/ItemsDataProvider.cs
@@ -0,0 +1,28 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ScreenCasting.Data.Common
+{
+ public abstract class ItemsDataProvider
+ {
+ public abstract List GetAll(int max_results);
+
+ public abstract VideoMetaData GetRandomVideo();
+ public abstract VideoMetaData GetFromID(string ID);
+
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Data/Common/VideoMetaData.cs b/Samples/AdvancedCasting/cs/Data/Common/VideoMetaData.cs
new file mode 100644
index 0000000000..ae2629d0a6
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Data/Common/VideoMetaData.cs
@@ -0,0 +1,30 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ScreenCasting.Data.Common
+{
+ public class VideoMetaData
+ {
+ public string Id { get; set; }
+ public string Title { get; set; }
+ public DateTime PubDate { get; set; }
+ public string License { get; set; }
+ public Uri WebPageLink { get; set; }
+ public Uri VideoLink { get; set; }
+ public Uri Thumbnail { get; set; }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/MainPage.xaml b/Samples/AdvancedCasting/cs/MainPage.xaml
new file mode 100644
index 0000000000..6de6a0fa33
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/MainPage.xaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Status:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/MainPage.xaml.cs b/Samples/AdvancedCasting/cs/MainPage.xaml.cs
new file mode 100644
index 0000000000..b3ae3f494a
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/MainPage.xaml.cs
@@ -0,0 +1,218 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Util;
+using System;
+using System.Collections.Generic;
+using Windows.ApplicationModel.Activation;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
+
+namespace ScreenCasting
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class MainPage : Page
+ {
+ public static MainPage Current;
+ public ViewLifetimeControl ProjectionViewPageControl;
+ public MainPage()
+ {
+ LoadScenarios();
+
+ this.DataContext = this;
+
+ this.InitializeComponent();
+
+ // This is a static public property that allows downstream pages to get a handle to the MainPage instance
+ // in order to call methods that are in this class.
+ Current = this;
+ SampleTitle.Text = FEATURE_NAME;
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ ApplicationView.GetForCurrentView().ExitFullScreenMode();
+ this.ScenarioControl.SelectionChanged += ScenarioControl_SelectionChanged;
+
+ try
+ {
+ // Populate the scenario list from the SampleConfiguration.cs file
+ ScenarioControl.ItemsSource = Scenarios;
+
+ if (e.Parameter is DialReceiverActivatedEventArgs)
+ {
+ NavigateToScenario(typeof(Scenario04), e.Parameter);
+ }
+ else
+ {
+ ScenarioControl.SelectedIndex = 0;
+ }
+
+ }
+ catch (Exception ex)
+ {
+ Window.Current.Content = new Frame();
+ Frame rootFrame = Window.Current.Content as Frame;
+ rootFrame.Navigate(typeof(UnhandledExceptionPage), null);
+ ((UnhandledExceptionPage)rootFrame.Content).StatusMessage = ex.Message + ex.StackTrace;
+ }
+ }
+
+ ///
+ /// Called whenever the user changes selection in the scenarios list. This method will navigate to the respective
+ /// sample scenario page.
+ ///
+ ///
+ ///
+ private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // Clear the status block when navigating scenarios.
+ NotifyUser(String.Empty, NotifyType.StatusMessage);
+
+ ListBox scenarioListBox = sender as ListBox;
+ Scenario s = Scenarios[scenarioListBox.SelectedIndex];
+ if (s != null)
+ {
+ ScenarioFrame.Navigate(s.ClassType);
+ if (Window.Current.Bounds.Width < 640)
+ {
+ Splitter.IsPaneOpen = false;
+ StatusBorder.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ Splitter.IsPaneOpen = true;
+ StatusBorder.Visibility = Visibility.Visible;
+ }
+ }
+ }
+
+
+
+ internal void NavigateToScenario(Type scenarioType, object args)
+ {
+ try
+ {
+ // Clear the status block when navigating scenarios.
+ NotifyUser(String.Empty, NotifyType.StatusMessage);
+
+ ListBox scenarioListBox = this.ScenarioControl;
+
+ int selectedIndex = -1;
+
+ this.ScenarioControl.SelectionChanged -= ScenarioControl_SelectionChanged;
+ for (int idx = 0; idx < scenarioListBox.Items.Count; idx++)
+ {
+ if (((Scenario)scenarioListBox.Items[idx]).ClassType == scenarioType)
+ {
+ selectedIndex = idx;
+ break;
+ }
+ }
+
+ if (selectedIndex > -1)
+ scenarioListBox.SelectedIndex = selectedIndex;
+
+ Scenario s = scenarioListBox.SelectedItem as Scenario;
+
+ if (s != null)
+ {
+ ScenarioFrame.Navigate(s.ClassType, args);
+ if (Window.Current.Bounds.Width < 640)
+ {
+ Splitter.IsPaneOpen = false;
+ StatusBorder.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ Splitter.IsPaneOpen = true;
+ StatusBorder.Visibility = Visibility.Visible;
+ }
+ }
+ this.ScenarioControl.SelectionChanged += ScenarioControl_SelectionChanged;
+ }
+ catch(Exception ex)
+ {
+ Frame rootFrame = Window.Current.Content as Frame;
+
+ Window.Current.Content = new Frame();
+ rootFrame.Navigate(typeof(UnhandledExceptionPage), ex.Message);
+ ((UnhandledExceptionPage)rootFrame.Content).StatusMessage = ex.Message + ex.StackTrace;
+ }
+ }
+
+
+ public List Scenarios
+ {
+ get { return this.scenarios; }
+ }
+
+ ///
+ /// Used to display messages to the user
+ ///
+ ///
+ ///
+ public void NotifyUser(string strMessage, NotifyType type)
+ {
+ switch (type)
+ {
+ case NotifyType.StatusMessage:
+ StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
+ break;
+ case NotifyType.ErrorMessage:
+ StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
+ break;
+ }
+ StatusBlock.Text = strMessage;
+
+ // Collapse the StatusBlock if it has no text to conserve real estate.
+ StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ async void Footer_Click(object sender, RoutedEventArgs e)
+ {
+ await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString()));
+ }
+
+ private void Button_Click(object sender, RoutedEventArgs e)
+ {
+ Splitter.IsPaneOpen = (Splitter.IsPaneOpen == true) ? false : true;
+ StatusBorder.Visibility = Visibility.Collapsed;
+ }
+ }
+ public enum NotifyType
+ {
+ StatusMessage,
+ ErrorMessage
+ };
+
+ //public class ScenarioBindingConverter : IValueConverter
+ //{
+ // public object Convert(object value, Type targetType, object parameter, string language)
+ // {
+ // Scenario s = value as Scenario;
+ // return (MainPage.Current.Scenarios.IndexOf(s) + 1) + ") " + s.Title;
+ // }
+
+ // public object ConvertBack(object value, Type targetType, object parameter, string language)
+ // {
+ // return true;
+ // }
+ //}
+}
diff --git a/Samples/AdvancedCasting/cs/Package.appxmanifest b/Samples/AdvancedCasting/cs/Package.appxmanifest
new file mode 100644
index 0000000000..57f90fd121
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Package.appxmanifest
@@ -0,0 +1,37 @@
+
+
+
+
+
+ ScreenCasting C# Sample
+ Microsoft Corporation
+ Assets\StoreLogo-sdk.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml b/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml
new file mode 100644
index 0000000000..a8c8848000
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml.cs b/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml.cs
new file mode 100644
index 0000000000..d5aaef8cd9
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/ProjectionViewPage.xaml.cs
@@ -0,0 +1,142 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using ScreenCasting.Controls;
+using System;
+using System.Threading.Tasks;
+using Windows.UI.Core;
+using Windows.UI.ViewManagement;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace ScreenCasting
+{
+ public sealed partial class ProjectionViewPage : Page
+ {
+ public ProjectionViewPage()
+ {
+ this.InitializeComponent();
+
+ ProjectedMediaTransportControls pmtcs = this.player.TransportControls as ProjectedMediaTransportControls;
+ if (pmtcs != null)
+ pmtcs.StopProjectingButtonClick += ProjectionViewPage_StopProjectingButtonClick;
+
+ this.player.MediaOpened += Player_MediaOpened;
+ }
+
+ private void Player_MediaOpened(object sender, RoutedEventArgs e)
+ {
+ this.player.IsFullWindow = true;
+ this.player.AreTransportControlsEnabled = true;
+ }
+
+ private void ProjectionViewPage_StopProjectingButtonClick(object sender, EventArgs e)
+ {
+ this.StopProjecting();
+ }
+
+
+
+ public async Task SetMediaSource (Uri source, TimeSpan position)
+ {
+ await this.player.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
+ {
+ this.player.Source = source;
+ this.player.Position = position;
+ this.player.Play();
+ });
+ return true;
+ }
+
+ public MediaElement Player
+ {
+ get { return this.player; }
+ }
+
+ ProjectionViewBroker broker = null;
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ broker = (ProjectionViewBroker)e.Parameter;
+ broker.ProjectedPage = this;
+
+ // Listen for when it's time to close this view
+ broker.ProjectionViewPageControl.Released += thisViewControl_Released;
+ }
+
+ private async void thisViewControl_Released(object sender, EventArgs e)
+ {
+ // There are two major cases where this event will get invoked:
+ // 1. The view goes unused for some time, and the system cleans it up
+ // 2. The app calls "StopProjectingAsync"
+ broker.ProjectionViewPageControl.Released -= thisViewControl_Released;
+ await broker.ProjectionViewPageControl.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
+ {
+ this.broker.NotifyProjectionStopping();
+ MainPage.Current.ProjectionViewPageControl = null;
+ });
+
+ this.player.Stop();
+ this.player.Source = null;
+
+ Window.Current.Close();
+ }
+
+ public async void SwapViews()
+ {
+ // The view might arrive on the wrong display. The user can
+ // easily swap the display on which the view appears
+ broker.ProjectionViewPageControl.StartViewInUse();
+ await ProjectionManager.SwapDisplaysForViewsAsync(
+ ApplicationView.GetForCurrentView().Id,
+ broker.MainViewId
+ );
+ broker.ProjectionViewPageControl.StopViewInUse();
+ }
+ private void SwapViews_Click(object sender, RoutedEventArgs e)
+ {
+ SwapViews();
+ }
+
+ public async void StopProjecting()
+ {
+ broker.NotifyProjectionStopping();
+
+ // There may be cases to end the projection from the projected view
+ // (e.g. the presentation hosted in that view concludes)
+ // broker.ProjectionViewPageControl.StartViewInUse();
+ await this.player.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
+ {
+ this.player.Stop();
+ this.player.Source = null;
+
+ broker.ProjectionViewPageControl.StartViewInUse();
+
+ try
+ {
+ await ProjectionManager.StopProjectingAsync(
+ broker.ProjectionViewPageControl.Id,
+ broker.MainViewId
+ );
+ }
+ catch { }
+ Window.Current.Close();
+
+ });
+
+ broker.ProjectionViewPageControl.StopViewInUse();
+ }
+ private void StopProjecting_Click(object sender, RoutedEventArgs e)
+ {
+ StopProjecting();
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Properties/AssemblyInfo.cs b/Samples/AdvancedCasting/cs/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..8deb85e22b
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ScreenCasting")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ScreenCasting")]
+[assembly: AssemblyCopyright("Copyright 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
diff --git a/Samples/AdvancedCasting/cs/SampleConfiguration.cs b/Samples/AdvancedCasting/cs/SampleConfiguration.cs
new file mode 100644
index 0000000000..ed2b290844
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/SampleConfiguration.cs
@@ -0,0 +1,55 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using Windows.UI.Xaml.Controls;
+using ScreenCasting;
+using System.Reflection;
+using ScreenCasting.Util;
+
+namespace ScreenCasting
+{
+ public partial class MainPage : Page
+ {
+ public const string FEATURE_NAME = "ScreenCasting";
+ private List scenarios;
+
+ private void LoadScenarios()
+ {
+ if (ApiInformation.IsTypePresent("Windows.Devices.Enumeration.DevicePicker"))
+ {
+ scenarios = new List
+ {
+ new Scenario() { Title="1 - Media Element Casting 101", ClassType=Type.GetType("ScreenCasting.Scenario01",false)}
+ ,new Scenario() { Title="2 - Casting APIs and a Custom Cast Button", ClassType=Type.GetType("ScreenCasting.Scenario02",false)}
+ ,new Scenario() { Title="3 - DIAL Sender Universal Windows app", ClassType=Type.GetType("ScreenCasting.Scenario03",false)}
+ ,new Scenario() { Title="4 - DIAL Receiver Windows Universal app", ClassType=Type.GetType("ScreenCasting.Scenario04")}
+ ,new Scenario() { Title="5 - Multi-View Media Application", ClassType=Type.GetType("ScreenCasting.Scenario05")}
+ ,new Scenario() { Title="6 - Combine Casting Methods", ClassType=Type.GetType("ScreenCasting.Scenario06")}
+
+ };
+ }
+ else
+ {
+ scenarios = new List {
+ new Scenario() { Title="DIAL Receiver Windows Universal Application", ClassType=typeof(Scenario04)}
+ };
+ }
+ }
+ }
+
+ public class Scenario
+ {
+ public string Title { get; set; }
+ public Type ClassType { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Samples/AdvancedCasting/cs/Styles/MediaTransportControlWithCustomCastButtonStyles.xaml b/Samples/AdvancedCasting/cs/Styles/MediaTransportControlWithCustomCastButtonStyles.xaml
new file mode 100644
index 0000000000..ba78b25875
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Styles/MediaTransportControlWithCustomCastButtonStyles.xaml
@@ -0,0 +1,706 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Collapsed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/Styles/ProjectedMediaTransportControlsStyles.xaml b/Samples/AdvancedCasting/cs/Styles/ProjectedMediaTransportControlsStyles.xaml
new file mode 100644
index 0000000000..854db0833a
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Styles/ProjectedMediaTransportControlsStyles.xaml
@@ -0,0 +1,715 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visible
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Collapsed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml b/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml
new file mode 100644
index 0000000000..ed4c4c39e2
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml.cs b/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml.cs
new file mode 100644
index 0000000000..4a3f80c847
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/UnhandledExceptionPage.xaml.cs
@@ -0,0 +1,72 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
+
+namespace ScreenCasting
+{
+
+
+
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class UnhandledExceptionPage : Page
+ {
+ public static void ShowUnhandledException(Exception ex)
+ {
+ Frame rootFrame = Window.Current.Content as Frame;
+ if (rootFrame == null)
+ {
+ rootFrame = new Frame();
+ Window.Current.Content = rootFrame;
+ Window.Current.Activate();
+ }
+
+ rootFrame.Navigate(typeof(UnhandledExceptionPage), ex.ToString());
+ }
+
+ protected override void OnNavigatedTo(NavigationEventArgs e)
+ {
+ base.OnNavigatedTo(e);
+
+ if(e.Parameter is string)
+ {
+ this.StatusMessage = (string)e.Parameter;
+ }
+ }
+ public UnhandledExceptionPage()
+ {
+ InitializeComponent();
+ }
+
+ public string StatusMessage
+ {
+ get { return this.Status.Text; }
+ set { this.Status.Text = value; }
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Util/ApiInformation.cs b/Samples/AdvancedCasting/cs/Util/ApiInformation.cs
new file mode 100644
index 0000000000..391fda7ed5
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Util/ApiInformation.cs
@@ -0,0 +1,35 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ScreenCasting.Util
+{
+ class ApiInformation
+ {
+ public static bool IsTypePresent(string typeName)
+ {
+ try
+ {
+ Windows.Media.Casting.CastingDevicePicker picker = new Windows.Media.Casting.CastingDevicePicker();
+
+ return true;
+ }
+ catch {
+ return false;
+ }
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Util/CustomDevicePickerFilter.cs b/Samples/AdvancedCasting/cs/Util/CustomDevicePickerFilter.cs
new file mode 100644
index 0000000000..c39acad575
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Util/CustomDevicePickerFilter.cs
@@ -0,0 +1,45 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Devices.Enumeration;
+
+namespace ScreenCasting.Util
+{
+ public class CustomDevicePickerFilter
+ {
+ private IList supportedDeviceSelectors = new List();
+
+ public IList SupportedDeviceSelectors
+ {
+ get { return supportedDeviceSelectors; }
+ }
+ public override string ToString()
+ {
+ string retval = string.Empty;
+
+ if (supportedDeviceSelectors.Count > 0)
+ retval = supportedDeviceSelectors[0];
+
+ if (supportedDeviceSelectors.Count > 1)
+ retval = "(" + retval + ")";
+
+ for (int idx = 1; idx < supportedDeviceSelectors.Count; idx++)
+ retval = retval + " OR (" + supportedDeviceSelectors[idx] + ")";
+
+ return retval;
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Util/DialLaunchArguments.cs b/Samples/AdvancedCasting/cs/Util/DialLaunchArguments.cs
new file mode 100644
index 0000000000..38dfb4cb8f
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Util/DialLaunchArguments.cs
@@ -0,0 +1,58 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ScreenCasting.Util
+{
+ class DialLaunchArguments
+ {
+ public string VideoId { get; private set; }
+ public string PairingCode { get; private set; }
+ public TimeSpan Position { get; private set; }
+
+ private DialLaunchArguments() { }
+
+ public static DialLaunchArguments Parse(string arguments)
+ {
+ try
+ {
+ DialLaunchArguments dialLaunchArgs = new DialLaunchArguments();
+
+ string[] argswithkeys = arguments.Split('&');
+
+ foreach (string currentArgWithKey in argswithkeys)
+ {
+ string key = currentArgWithKey.Split('=')[0];
+ string val = currentArgWithKey.Split('=')[1];
+ switch (key)
+ {
+ case "v": { dialLaunchArgs.VideoId = val; break; }
+ case "t": { dialLaunchArgs.Position = TimeSpan.FromTicks(long.Parse(val)); break; }
+ case "pairingCode": { dialLaunchArgs.PairingCode = val; break; }
+ }
+ }
+ return dialLaunchArgs;
+ }
+ catch (Exception ex){
+ throw new ArgumentOutOfRangeException(string.Format("Failed to parse DIAL launch arguments: '{0}'", arguments), ex);
+ }
+ }
+
+
+ }
+
+
+}
diff --git a/Samples/AdvancedCasting/cs/Util/RequiredDeviceProperties.cs b/Samples/AdvancedCasting/cs/Util/RequiredDeviceProperties.cs
new file mode 100644
index 0000000000..9314804d33
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Util/RequiredDeviceProperties.cs
@@ -0,0 +1,60 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ScreenCasting.Util
+{
+ public class RequiredDeviceProperties
+ {
+ public static readonly string DEVPKEY_AepContainer_FriendlyName = "{0bba1ede-7566-4f47-90ec-25fc567ced2a}, 5";
+ public static readonly string DEVPKEY_AepContainer_SupportsAudio = "{6af55d45-38db-4495-acb0-d4728a3b8314}, 2";
+ public static readonly string DEVPKEY_AepContainer_SupportsVideo = "{6af55d45-38db-4495-acb0-d4728a3b8314}, 3";
+ public static readonly string DEVPKEY_AepContainer_SupportsImages = "{6af55d45-38db-4495-acb0-d4728a3b8314}, 4";
+ public static readonly string DEVPKEY_AepContainer_SupportedUriSchemes = "{6af55d45-38db-4495-acb0-d4728a3b8314}, 5";
+ public static readonly string DEVPKEY_AepContainer_Categories = "System.Devices.AepContainer.Categories";
+ public static readonly string DEVPKEY_DeviceContainer_Manufacturer = "System.Devices.Manufacturer";
+ public static readonly string DEVPKEY_DeviceContainer_ModelName = "System.Devices.ModelName";
+ public static readonly string DEVPKEY_Device_ContainerId = "System.Devices.ContainerId";
+ public static readonly string DEVPKEY_Device_InstanceId = "System.Devices.DeviceInstanceId";
+
+ private RequiredDeviceProperties() { }
+
+ public static void AddProps(IList list)
+ {
+ foreach (string s in Props)
+ list.Add(s);
+ }
+ public static List Props
+ {
+ get
+ {
+ List properties = new List();
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_FriendlyName);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_SupportsAudio);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_SupportsVideo);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_SupportsImages);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_SupportedUriSchemes);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_AepContainer_Categories);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_DeviceContainer_Manufacturer);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_DeviceContainer_ModelName);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_Device_ContainerId);
+ properties.Add(RequiredDeviceProperties.DEVPKEY_Device_InstanceId);
+
+ return properties;
+ }
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/Util/ViewLifetimeControl.cs b/Samples/AdvancedCasting/cs/Util/ViewLifetimeControl.cs
new file mode 100644
index 0000000000..e3ecc73d2d
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/Util/ViewLifetimeControl.cs
@@ -0,0 +1,325 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+// The objects defined here demonstrate how to make sure each of the views created remains alive as long as
+// the app needs them, but only when they're being used by the app or the user. Many of the scenarios contained in this
+// sample use these functions to keep track of the views available and ensure that the view is not closed while
+// the scenario is attempting to show it.
+//
+// As you can see in scenario 1, the ApplicationViewSwitcher.TryShowAsStandaloneAsync and
+// ProjectionManager.StartProjectingAsync methods let you show one view next to another. The Consolidated event
+// is fired when a view stops being visible separately from other views. Common cases where this will occur
+// is when the view falls out of the list of recently used apps, or when the user performs the close gesture on the view.
+// This is a good time to close the view, provided the app isn't trying to show the view at the same time. This event
+// is fired on the thread of the view that becomes consolidated.
+//
+// Each view lives on its own thread, so concurrency control is necessary. Also, as you'll see in the sample,
+// certain objects may be bound to UI on given threads. Properties of those objects should only be updated
+// on that UI thread.
+
+using System;
+using System.ComponentModel;
+using Windows.UI.Core;
+using Windows.UI.ViewManagement;
+
+namespace ScreenCasting.Util
+{
+ // A custom event that fires whenever the secondary view is ready to be closed. You should
+ // clean up any state (including deregistering for events) then close the window in this handler
+ public delegate void ViewReleasedHandler(Object sender, EventArgs e);
+
+ // A ViewLifetimeControl is instantiated for every secondary view. ViewLifetimeControl's reference count
+ // keeps track of when the secondary view thinks it's in usem and when the main view is interacting with the secondary view (about to show
+ // it to the user, etc.) When the reference count drops to zero, the secondary view is closed.
+ public sealed class ViewLifetimeControl : INotifyPropertyChanged
+ {
+ // Dispatcher for this view. Kept here for sending messages between this view and the main view.
+ CoreDispatcher dispatcher;
+
+ // Window for this particular view. Used to register and unregister for events
+ CoreWindow window;
+
+ // The title for the view shown in the list of recently used apps (by setting the title on
+ // ApplicationView)
+ string title;
+
+ // This class uses references counts to make sure the secondary views isn't closed prematurely.
+ // Whenever the main view is about to interact with the secondary view, it should take a reference
+ // by calling "StartViewInUse" on this object. When finished interacting, it should release the reference
+ // by calling "StopViewInUse". You can see examples of this throughout the sample, especially in
+ // scenario 1.
+ int refCount = 0;
+
+ // Each view has a unique Id, found using the ApplicationView.Id property or
+ // ApplicationView.GetApplicationViewIdForCoreWindow method. This id is used in all of the ApplicationViewSwitcher
+ // and ProjectionManager APIs.
+ int viewId;
+
+ // Tracks if this ViewLifetimeControl object is still valid. If this is true, then the view is in the process
+ // of closing itself down
+ bool released = false;
+
+ // Keeps track of if the consolidated event has fired yet. A view is consolidated with other views
+ // when there's no way for the user to get to it (it's not in the list of recently used apps, cannot be
+ // launched from Start, etc.) A view stops being consolidated when it's visible--at that point
+ // the user can interact with it, move it on or off screen, etc.
+ bool consolidated = true;
+
+ // Used to store pubicly registered events under the protection of a lock
+ event ViewReleasedHandler InternalReleased;
+
+ // Instantiate views using "CreateForCurrentView"
+ private ViewLifetimeControl(CoreWindow newWindow)
+ {
+ dispatcher = newWindow.Dispatcher;
+ window = newWindow;
+ viewId = ApplicationView.GetApplicationViewIdForWindow(window);
+
+ // This class will automatically tell the view when its time to close
+ // or stay alive in a few cases
+ RegisterForEvents();
+ }
+
+ // Register for events on the current view
+ private void RegisterForEvents()
+ {
+ // A view is consolidated with other views hen there's no way for the user to get to it (it's not in the list of recently used apps, cannot be
+ // launched from Start, etc.) A view stops being consolidated when it's visible--at that point the user can interact with it, move it on or off screen, etc.
+ // It's generally a good idea to close a view after it has been consolidated, but keep it open while it's visible.
+ ApplicationView.GetForCurrentView().Consolidated += ViewConsolidated;
+ window.VisibilityChanged += VisibilityChanged;
+ }
+
+ // Unregister for events. Call this method before closing the view to prevent leaks.
+ private void UnregisterForEvents()
+ {
+ ApplicationView.GetForCurrentView().Consolidated -= ViewConsolidated;
+ window.VisibilityChanged -= VisibilityChanged;
+ }
+
+ private void VisibilityChanged(object sender, VisibilityChangedEventArgs e)
+ {
+
+ if (e.Visible)
+ {
+ // A view is consolidated with other views hen there's no way for the user to get to it (it's not in the list of recently used apps, cannot be
+ // launched from Start, etc.) A view stops being consolidated when it's visible--at that point the user can interact with it, move it on or off screen, etc.
+ // It's generally a good idea to close a view after it has been consolidated, but keep it open while it's visible.
+ Consolidated = false;
+ }
+ }
+
+ // A view is consolidated with other views hen there's no way for the user to get to it (it's not in the list of recently used apps, cannot be
+ // launched from Start, etc.) A view stops being consolidated when it's visible--at that point the user can interact with it, move it on or off screen, etc.
+ // It's generally a good idea to close a view after it has been consolidated, but keep it open while it's visible.
+ private void ViewConsolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs e)
+ {
+ Consolidated = true;
+ }
+
+ // Called when a view has been "consolidated" (no longer accessible to the user)
+ // and no other view is trying to interact with it. This should only be closed after the reference
+ // count goes to 0 (including being consolidated). At the end of this, the view is closed.
+ private void FinalizeRelease()
+ {
+ bool justReleased = false;
+ lock (this)
+ {
+ if (refCount == 0)
+ {
+ justReleased = true;
+ released = true;
+ }
+ }
+
+ // This assumes that released will never be made false after it
+ // it has been set to true
+ if (justReleased)
+ {
+ UnregisterForEvents();
+ InternalReleased(this, null);
+ }
+ }
+
+ // Creates ViewLifetimeControl for the particular view.
+ // Only do this once per view.
+ public static ViewLifetimeControl CreateForCurrentView()
+ {
+ return new ViewLifetimeControl(CoreWindow.GetForCurrentThread());
+ }
+
+ // For purposes of this sample, the collection of views
+ // is bound to a UI collection. This property is available for binding
+ public string Title
+ {
+ get
+ {
+ return title;
+ }
+ set
+ {
+ if (title != value)
+ {
+ title = value;
+ if (PropertyChanged != null)
+ {
+ PropertyChanged(this, new PropertyChangedEventArgs("Title"));
+ }
+ }
+ }
+ }
+
+ // Necessary to communicate with the window
+ public CoreDispatcher Dispatcher
+ {
+ get
+ {
+ // This property never changes, so there's no need to lock
+ return dispatcher;
+ }
+ }
+
+ // Each view has a unique Id, found using the ApplicationView.Id property or
+ // ApplicationView.GetApplicationViewIdForCoreWindow method. This id is used in all of the ApplicationViewSwitcher
+ // and ProjectionManager APIs.
+ public int Id
+ {
+ get
+ {
+ // This property never changes, so there's no need to lock
+ return viewId;
+ }
+ }
+
+ // Keeps track of if the consolidated event has fired yet. A view is consolidated with other views
+ // when there's no way for the user to get to it (it's not in the list of recently used apps, cannot be
+ // launched from Start, etc.) A view stops being consolidated when it's visible--at that point
+ // the user can interact with it, move it on or off screen, etc.
+ public bool Consolidated
+ {
+ get
+ {
+ // This property should only be accessed by the thread on which the view lives, so there's no need to lock
+ return consolidated;
+ }
+ set
+ {
+ if (consolidated != value)
+ {
+ consolidated = value;
+ if (consolidated)
+ {
+ // The view isn't accessible to the user, so it's OK to close it.
+ StopViewInUse();
+ }
+ else
+ {
+ // The view has become visible, so do not close it until it's consolidated
+ StartViewInUse();
+ }
+ }
+ }
+ }
+
+ // Signals that the view is being interacted with by another view,
+ // so it shouldn't be closed even if it becomes "consolidated"
+ public int StartViewInUse()
+ {
+ bool releasedCopy = false;
+ int refCountCopy = 0;
+
+ // This method is called from several different threads
+ // (each view lives on its own thread)
+ lock (this)
+ {
+ releasedCopy = this.released;
+ if (!released)
+ {
+ refCountCopy = ++refCount;
+ }
+ }
+
+ if (releasedCopy)
+ {
+ throw new InvalidOperationException("This view is being disposed");
+ }
+
+ return refCountCopy;
+ }
+
+ // Should come after any call to StartViewInUse
+ // Signals that the another view has finished interacting with the view tracked
+ // by this object
+ public int StopViewInUse()
+ {
+ int refCountCopy = 0;
+ bool releasedCopy = false;
+
+ lock (this)
+ {
+ releasedCopy = this.released;
+ if (!released)
+ {
+ refCountCopy = --refCount;
+ if (refCountCopy == 0)
+ {
+ // If no other view is interacting with this view, and
+ // the view isn't accessible to the user, it's appropriate
+ // to close it
+ //
+ // Before actually closing the view, make sure there are no
+ // other important events waiting in the queue (this low-priority item
+ // will run after other events)
+ dispatcher.RunAsync(CoreDispatcherPriority.Low, FinalizeRelease);
+ }
+ }
+ }
+
+ if (releasedCopy)
+ {
+ throw new InvalidOperationException("This view is being disposed");
+ }
+ return refCountCopy;
+ }
+
+ // Signals to consumers that its time to close the view so that
+ // they can clean up (including calling Window.Close() when finished)
+ public event PropertyChangedEventHandler PropertyChanged;
+ public event ViewReleasedHandler Released
+ {
+ add
+ {
+ bool releasedCopy = false;
+ lock (this)
+ {
+ releasedCopy = released;
+ if (!released)
+ {
+ InternalReleased += value;
+ }
+ }
+
+ if (releasedCopy)
+ {
+ throw new InvalidOperationException("This view is being disposed");
+ }
+ }
+
+ remove
+ {
+ lock (this)
+ {
+ InternalReleased -= value;
+ }
+ }
+ }
+ }
+}
diff --git a/Samples/AdvancedCasting/cs/project.json b/Samples/AdvancedCasting/cs/project.json
new file mode 100644
index 0000000000..c594939270
--- /dev/null
+++ b/Samples/AdvancedCasting/cs/project.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
+ },
+ "frameworks": {
+ "uap10.0": {}
+ },
+ "runtimes": {
+ "win10-arm": {},
+ "win10-arm-aot": {},
+ "win10-x86": {},
+ "win10-x86-aot": {},
+ "win10-x64": {},
+ "win10-x64-aot": {}
+ }
+}
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/ISecureInterfaceService.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/ISecureInterfaceService.h
new file mode 100644
index 0000000000..45fa60fccb
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/ISecureInterfaceService.h
@@ -0,0 +1,54 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+public interface class ISecureInterfaceService
+{
+public:
+ // Implement this function to handle calls to the Concatenate method.
+ Windows::Foundation::IAsyncOperation^ ConcatenateAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info , _In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2);
+
+ // Implement this function to handle requests for the value of the IsUpperCaseEnabled property.
+ //
+ // Currently, info will always be null, because no information is available about the requestor.
+ Windows::Foundation::IAsyncOperation^ GetIsUpperCaseEnabledAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+ // Implement this function to handle requests to set the IsUpperCaseEnabled property.
+ //
+ // Currently, info will always be null, because no information is available about the requestor.
+ Windows::Foundation::IAsyncOperation^ SetIsUpperCaseEnabledAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info, bool value);
+
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1IntrospectionXml.xml b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1IntrospectionXml.xml
new file mode 100644
index 0000000000..366ad9383e
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1IntrospectionXml.xml
@@ -0,0 +1,20 @@
+
+
+ A secure AllJoyn sample
+
+
+ Concatenate two input strings and returns the concatenated string as output
+
+
+
+
+
+ Determine if the output of the Concatenate method is returned as upper case string or not
+
+
+
+ This signal is emitted when producer sends a text message to consumer
+
+
+
+
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj
new file mode 100644
index 0000000000..49551a4d07
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj
@@ -0,0 +1,260 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {0a9e8245-5676-4b45-b34b-756927d85b3c}
+ WindowsRuntimeComponent
+ Scenario1WinRTComponent
+ com.microsoft.Samples.SecureInterface
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.10240.0
+ 10.0.10240.0
+ true
+
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ true
+ v140
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+ DynamicLibrary
+ false
+ true
+ v140
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ $(VC_IncludePath);$(UniversalCRT_IncludePath);$(WindowsSDK_IncludePath);..\..\shared
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions);QCC_OS_GROUP_WINDOWS
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj -Zm210 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+ WindowsApp.lib;%(AdditionalDependencies);msajapi.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj.filters b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj.filters
new file mode 100644
index 0000000000..3288c2691e
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/Scenario1WinRTComponent.vcxproj.filters
@@ -0,0 +1,37 @@
+
+
+
+
+ aa05969e-0ba6-407c-9c26-91ed00b63b8b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.cpp
new file mode 100644
index 0000000000..8b79c09f40
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.cpp
@@ -0,0 +1,408 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace concurrency;
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::AllJoyn;
+using namespace com::microsoft::Samples::SecureInterface;
+
+std::map SecureInterfaceConsumer::SourceInterfaces;
+
+SecureInterfaceConsumer::SecureInterfaceConsumer(AllJoynBusAttachment^ busAttachment)
+ : m_busAttachment(busAttachment),
+ m_proxyBusObject(nullptr),
+ m_busObject(nullptr),
+ m_sessionListener(nullptr),
+ m_sessionId(0)
+{
+ m_weak = new WeakReference(this);
+ m_signals = ref new SecureInterfaceSignals();
+ m_nativeBusAttachment = AllJoynHelpers::GetInternalBusAttachment(m_busAttachment);
+}
+
+SecureInterfaceConsumer::~SecureInterfaceConsumer()
+{
+ AllJoynBusObjectManager::ReleaseBusObject(m_nativeBusAttachment, AllJoynHelpers::PlatformToMultibyteString(ServiceObjectPath).data());
+ if (SessionListener != nullptr)
+ {
+ alljoyn_busattachment_setsessionlistener(m_nativeBusAttachment, m_sessionId, nullptr);
+ alljoyn_sessionlistener_destroy(SessionListener);
+ }
+ if (nullptr != ProxyBusObject)
+ {
+ alljoyn_proxybusobject_destroy(ProxyBusObject);
+ }
+ delete m_weak;
+}
+
+void SecureInterfaceConsumer::OnSessionLost(_In_ alljoyn_sessionid sessionId, _In_ alljoyn_sessionlostreason reason)
+{
+ if (sessionId == m_sessionId)
+ {
+ AllJoynSessionLostEventArgs^ args = ref new AllJoynSessionLostEventArgs(static_cast(reason));
+ SessionLost(this, args);
+ }
+}
+
+void SecureInterfaceConsumer::OnSessionMemberAdded(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberAddedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ SessionMemberAdded(this, args);
+ }
+}
+
+void SecureInterfaceConsumer::OnSessionMemberRemoved(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberRemovedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ SessionMemberRemoved(this, args);
+ }
+}
+
+QStatus SecureInterfaceConsumer::AddSignalHandler(_In_ alljoyn_busattachment busAttachment, _In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_signalhandler_ptr handler)
+{
+ alljoyn_interfacedescription_member member;
+ if (!alljoyn_interfacedescription_getmember(interfaceDescription, methodName, &member))
+ {
+ return ER_BUS_INTERFACE_NO_SUCH_MEMBER;
+ }
+
+ return alljoyn_busattachment_registersignalhandler(busAttachment, handler, member, NULL);
+}
+
+IAsyncOperation^ SecureInterfaceConsumer::JoinSessionAsync(
+ _In_ AllJoynServiceInfo^ serviceInfo, _Inout_ SecureInterfaceWatcher^ watcher)
+{
+ return create_async([serviceInfo, watcher]() -> SecureInterfaceJoinSessionResult^
+ {
+ auto result = ref new SecureInterfaceJoinSessionResult();
+ result->Status = AllJoynStatus::Ok;
+ result->Consumer = nullptr;
+
+ result->Consumer = ref new SecureInterfaceConsumer(watcher->BusAttachment);
+ result->Status = result->Consumer->JoinSession(serviceInfo);
+
+ return result;
+ });
+}
+
+IAsyncOperation^ SecureInterfaceConsumer::ConcatenateAsync(_In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2)
+{
+ return create_async([this, interfaceMemberInStr1, interfaceMemberInStr2]() -> SecureInterfaceConcatenateResult^
+ {
+ auto result = ref new SecureInterfaceConcatenateResult();
+
+ alljoyn_message message = alljoyn_message_create(m_nativeBusAttachment);
+ size_t argCount = 2;
+ alljoyn_msgarg inputs = alljoyn_msgarg_array_create(argCount);
+
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(inputs, 0), "s", interfaceMemberInStr1);
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(inputs, 1), "s", interfaceMemberInStr2);
+
+ QStatus status = alljoyn_proxybusobject_methodcall(
+ ProxyBusObject,
+ "com.microsoft.Samples.SecureInterface",
+ "Concatenate",
+ inputs,
+ argCount,
+ message,
+ c_MessageTimeoutInMilliseconds,
+ 0);
+ result->Status = static_cast(status);
+ if (ER_OK == status)
+ {
+ result->Status = AllJoynStatus::Ok;
+ Platform::String^ argument0;
+ status = static_cast(TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 0), "s", &argument0));
+ result->OutStr = argument0;
+
+ if (status != ER_OK)
+ {
+ result->Status = static_cast(status);
+ }
+ }
+ else if (ER_BUS_REPLY_IS_ERROR_MESSAGE == status)
+ {
+ alljoyn_msgarg errorArg = alljoyn_message_getarg(message, 1);
+ if (nullptr != errorArg)
+ {
+ uint16 errorStatus;
+ status = alljoyn_msgarg_get_uint16(errorArg, &errorStatus);
+ if (ER_OK == status)
+ {
+ status = static_cast(errorStatus);
+ }
+ }
+ result->Status = static_cast(status);
+ }
+
+ alljoyn_message_destroy(message);
+ alljoyn_msgarg_destroy(inputs);
+
+ return result;
+ });
+}
+
+IAsyncOperation^ SecureInterfaceConsumer::SetIsUpperCaseEnabledAsync(_In_ bool value)
+{
+ return create_async([this, value]() -> SecureInterfaceSetIsUpperCaseEnabledResult^
+ {
+ PropertySetContext setContext;
+
+ alljoyn_msgarg inputArgument = alljoyn_msgarg_create();
+ TypeConversionHelpers::SetAllJoynMessageArg(inputArgument, "b", value);
+
+ alljoyn_proxybusobject_setpropertyasync(
+ ProxyBusObject,
+ "com.microsoft.Samples.SecureInterface",
+ "IsUpperCaseEnabled",
+ inputArgument,
+ [](QStatus status, alljoyn_proxybusobject obj, void* context)
+ {
+ UNREFERENCED_PARAMETER(obj);
+ auto propertyContext = static_cast(context);
+ propertyContext->SetStatus(status);
+ propertyContext->SetEvent();
+ },
+ c_MessageTimeoutInMilliseconds,
+ &setContext);
+
+ alljoyn_msgarg_destroy(inputArgument);
+
+ setContext.Wait();
+
+ auto result = ref new SecureInterfaceSetIsUpperCaseEnabledResult();
+ result->Status = setContext.GetStatus();
+ return result;
+ });
+}
+
+IAsyncOperation^ SecureInterfaceConsumer::GetIsUpperCaseEnabledAsync()
+{
+ return create_async([this]() -> SecureInterfaceGetIsUpperCaseEnabledResult^
+ {
+ PropertyGetContext getContext;
+
+ alljoyn_proxybusobject_getpropertyasync(
+ ProxyBusObject,
+ "com.microsoft.Samples.SecureInterface",
+ "IsUpperCaseEnabled",
+ [](QStatus status, alljoyn_proxybusobject obj, const alljoyn_msgarg value, void* context)
+ {
+ UNREFERENCED_PARAMETER(obj);
+ auto propertyContext = static_cast*>(context);
+
+ if (ER_OK == status)
+ {
+ bool argument;
+ TypeConversionHelpers::GetAllJoynMessageArg(value, "b", &argument);
+
+ propertyContext->SetValue(argument);
+ }
+ propertyContext->SetStatus(status);
+ propertyContext->SetEvent();
+ },
+ c_MessageTimeoutInMilliseconds,
+ &getContext);
+
+ getContext.Wait();
+
+ auto result = ref new SecureInterfaceGetIsUpperCaseEnabledResult();
+ result->Status = getContext.GetStatus();
+ result->IsUpperCaseEnabled = getContext.GetValue();
+ return result;
+ });
+}
+
+void SecureInterfaceConsumer::OnPropertyChanged(_In_ alljoyn_proxybusobject obj, _In_ PCSTR interfaceName, _In_ const alljoyn_msgarg changed, _In_ const alljoyn_msgarg invalidated)
+{
+ UNREFERENCED_PARAMETER(obj);
+ UNREFERENCED_PARAMETER(interfaceName);
+ UNREFERENCED_PARAMETER(invalidated);
+
+ alljoyn_msgarg changedProperties;
+ size_t changedPropertyCount;
+ if (ER_OK != alljoyn_msgarg_get(changed, "a{sv}", &changedPropertyCount, &changedProperties))
+ {
+ return;
+ }
+
+ for (size_t i = 0; i < changedPropertyCount; i++)
+ {
+ char* propertyName;
+ alljoyn_msgarg propertyValue;
+ if (ER_OK != alljoyn_msgarg_get(alljoyn_msgarg_array_element(changedProperties, i), "{sv}", &propertyName, &propertyValue))
+ {
+ return;
+ }
+
+ if (strcmp("IsUpperCaseEnabled", propertyName) == 0)
+ {
+ IsUpperCaseEnabledChanged(this, nullptr);
+ }
+ }
+}
+
+void SecureInterfaceConsumer::CallTextSentSignalHandler(_In_ const alljoyn_interfacedescription_member* member, _In_ alljoyn_message message)
+{
+ auto source = SourceInterfaces.find(member->iface);
+ if (source == SourceInterfaces.end())
+ {
+ return;
+ }
+
+ auto consumer = source->second->Resolve();
+ if (consumer->Signals != nullptr)
+ {
+ auto callInfo = ref new AllJoynMessageInfo(AllJoynHelpers::MultibyteToPlatformString(alljoyn_message_getsender(message)));
+ auto eventArgs = ref new SecureInterfaceTextSentReceivedEventArgs();
+ eventArgs->MessageInfo = callInfo;
+
+ Platform::String^ argument0;
+ TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 0), "s", &argument0);
+
+ eventArgs->Message = argument0;
+
+ consumer->Signals->CallTextSentReceived(consumer->Signals, eventArgs);
+ }
+}
+
+int32 SecureInterfaceConsumer::JoinSession(_In_ AllJoynServiceInfo^ serviceInfo)
+{
+ alljoyn_sessionlistener_callbacks callbacks =
+ {
+ AllJoynHelpers::SessionLostHandler,
+ AllJoynHelpers::SessionMemberAddedHandler,
+ AllJoynHelpers::SessionMemberRemovedHandler
+ };
+
+ alljoyn_busattachment_enableconcurrentcallbacks(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment));
+
+ SessionListener = alljoyn_sessionlistener_create(&callbacks, m_weak);
+ alljoyn_sessionopts sessionOpts = alljoyn_sessionopts_create(ALLJOYN_TRAFFIC_TYPE_MESSAGES, true, ALLJOYN_PROXIMITY_ANY, ALLJOYN_TRANSPORT_ANY);
+
+ std::vector sessionNameUtf8 = AllJoynHelpers::PlatformToMultibyteString(serviceInfo->UniqueName);
+ RETURN_IF_QSTATUS_ERROR(alljoyn_busattachment_joinsession(
+ m_nativeBusAttachment,
+ &sessionNameUtf8[0],
+ serviceInfo->SessionPort,
+ SessionListener,
+ &m_sessionId,
+ sessionOpts));
+ alljoyn_sessionopts_destroy(sessionOpts);
+
+ ServiceObjectPath = serviceInfo->ObjectPath;
+ std::vector objectPath = AllJoynHelpers::PlatformToMultibyteString(ServiceObjectPath);
+
+ if (objectPath.empty())
+ {
+ return AllJoynStatus::Fail;
+ }
+
+ ProxyBusObject = alljoyn_proxybusobject_create(m_nativeBusAttachment, &sessionNameUtf8[0], &objectPath[0], m_sessionId);
+ if (nullptr == ProxyBusObject)
+ {
+ return AllJoynStatus::Fail;
+ }
+
+ PCSTR propertyNames[] = { "IsUpperCaseEnabled" };
+
+ RETURN_IF_QSTATUS_ERROR(alljoyn_proxybusobject_registerpropertieschangedlistener(
+ ProxyBusObject,
+ "com.microsoft.Samples.SecureInterface",
+ propertyNames,
+ _countof(propertyNames),
+ AllJoynHelpers::PropertyChangedHandler,
+ m_weak));
+
+
+ alljoyn_interfacedescription description = alljoyn_busattachment_getinterface(m_nativeBusAttachment, "com.microsoft.Samples.SecureInterface");
+ if (nullptr == description)
+ {
+ return AllJoynStatus::Fail;
+ }
+
+ unsigned int noneMechanismIndex = 0;
+ bool authenticationMechanismsContainsNone = m_busAttachment->AuthenticationMechanisms->IndexOf(AllJoynAuthenticationMechanism::None, &noneMechanismIndex);
+ QCC_BOOL interfaceIsSecure = alljoyn_interfacedescription_issecure(description);
+
+ // If the current set of AuthenticationMechanisms supports authentication,
+ // determine whether to secure the connection.
+ if (AllJoynHelpers::CanSecure(m_busAttachment->AuthenticationMechanisms))
+ {
+ // Secure the connection if the org.alljoyn.Bus.Secure XML annotation
+ // is specified, or if None is not present in AuthenticationMechanisms.
+ if (!authenticationMechanismsContainsNone || interfaceIsSecure)
+ {
+ alljoyn_proxybusobject_secureconnection(ProxyBusObject, QCC_FALSE);
+ }
+ }
+ else
+ {
+ // If the current set of AuthenticationMechanisms does not support authentication
+ // but the interface requires security, report an error.
+ if (interfaceIsSecure)
+ {
+ return static_cast(ER_BUS_NO_AUTHENTICATION_MECHANISM);
+ }
+ }
+
+ RETURN_IF_QSTATUS_ERROR(AllJoynBusObjectManager::GetBusObject(m_nativeBusAttachment, AllJoynHelpers::PlatformToMultibyteString(ServiceObjectPath).data(), &m_busObject));
+ RETURN_IF_QSTATUS_ERROR(alljoyn_proxybusobject_addinterface(ProxyBusObject, description));
+
+ if (!AllJoynBusObjectManager::BusObjectIsRegistered(m_nativeBusAttachment, m_busObject))
+ {
+ RETURN_IF_QSTATUS_ERROR(alljoyn_busobject_addinterface(BusObject, description));
+ }
+
+ QStatus result = AddSignalHandler(
+ m_nativeBusAttachment,
+ description,
+ "TextSent",
+ [](const alljoyn_interfacedescription_member* member, PCSTR srcPath, alljoyn_message message) { UNREFERENCED_PARAMETER(srcPath); CallTextSentSignalHandler(member, message); });
+ if (result != ER_OK)
+ {
+ return static_cast(result);
+ }
+
+ SourceInterfaces[description] = m_weak;
+ RETURN_IF_QSTATUS_ERROR(AllJoynBusObjectManager::TryRegisterBusObject(m_nativeBusAttachment, BusObject, true));
+ m_signals->Initialize(BusObject, m_sessionId);
+
+ return AllJoynStatus::Ok;
+}
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.h
new file mode 100644
index 0000000000..a6458b085f
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceConsumer.h
@@ -0,0 +1,159 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+public interface class ISecureInterfaceConsumer
+{
+ event Windows::Foundation::TypedEventHandler^ SessionLost;
+ event Windows::Foundation::TypedEventHandler^ SessionMemberAdded;
+ event Windows::Foundation::TypedEventHandler^ SessionMemberRemoved;
+ event Windows::Foundation::TypedEventHandler^ IsUpperCaseEnabledChanged;
+};
+
+public ref class SecureInterfaceConsumer sealed : [Windows::Foundation::Metadata::Default] ISecureInterfaceConsumer
+{
+public:
+ SecureInterfaceConsumer(Windows::Devices::AllJoyn::AllJoynBusAttachment^ busAttachment);
+ virtual ~SecureInterfaceConsumer();
+
+ // Join the AllJoyn session specified by sessionName.
+ //
+ // This will usually be called after the unique name of a producer has been reported
+ // in the Added callback on the Watcher.
+ static Windows::Foundation::IAsyncOperation^ JoinSessionAsync(_In_ Windows::Devices::AllJoyn::AllJoynServiceInfo^ serviceInfo, _Inout_ SecureInterfaceWatcher^ watcher);
+
+ // Call the Concatenate method
+ Windows::Foundation::IAsyncOperation^ ConcatenateAsync(_In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2);
+ // This event fires whenever the value of IsUpperCaseEnabled changes.
+ virtual event Windows::Foundation::TypedEventHandler^ IsUpperCaseEnabledChanged;
+
+ // Get the value of the IsUpperCaseEnabled property.
+ Windows::Foundation::IAsyncOperation^ GetIsUpperCaseEnabledAsync();
+
+ // Set the value of the IsUpperCaseEnabled property.
+ Windows::Foundation::IAsyncOperation^ SetIsUpperCaseEnabledAsync(_In_ bool value);
+
+ // Used to send signals or register functions to handle received signals.
+ property SecureInterfaceSignals^ Signals
+ {
+ SecureInterfaceSignals^ get() { return m_signals; }
+ }
+
+ // This event will fire whenever the consumer loses the session that it is a member of.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionLost;
+
+ // This event will fire whenever a member joins the session.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionMemberAdded;
+
+ // This event will fire whenever a member leaves the session.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionMemberRemoved;
+
+internal:
+ // Consumers do not support property get.
+ QStatus OnPropertyGet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _Inout_ alljoyn_msgarg val)
+ {
+ UNREFERENCED_PARAMETER(interfaceName); UNREFERENCED_PARAMETER(propertyName); UNREFERENCED_PARAMETER(val);
+ return ER_NOT_IMPLEMENTED;
+ }
+
+ // Consumers do not support property set.
+ QStatus OnPropertySet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _In_ alljoyn_msgarg val)
+ {
+ UNREFERENCED_PARAMETER(interfaceName); UNREFERENCED_PARAMETER(propertyName); UNREFERENCED_PARAMETER(val);
+ return ER_NOT_IMPLEMENTED;
+ }
+
+ void OnSessionLost(_In_ alljoyn_sessionid sessionId, _In_ alljoyn_sessionlostreason reason);
+ void OnSessionMemberAdded(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName);
+ void OnSessionMemberRemoved(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName);
+
+ void OnPropertyChanged(_In_ alljoyn_proxybusobject obj, _In_ PCSTR interfaceName, _In_ const alljoyn_msgarg changed, _In_ const alljoyn_msgarg invalidated);
+
+ property Platform::String^ ServiceObjectPath
+ {
+ Platform::String^ get() { return m_ServiceObjectPath; }
+ void set(Platform::String^ value) { m_ServiceObjectPath = value; }
+ }
+
+ property alljoyn_proxybusobject ProxyBusObject
+ {
+ alljoyn_proxybusobject get() { return m_proxyBusObject; }
+ void set(alljoyn_proxybusobject value) { m_proxyBusObject = value; }
+ }
+
+ property alljoyn_busobject BusObject
+ {
+ alljoyn_busobject get() { return m_busObject; }
+ void set(alljoyn_busobject value) { m_busObject = value; }
+ }
+
+ property alljoyn_sessionlistener SessionListener
+ {
+ alljoyn_sessionlistener get() { return m_sessionListener; }
+ void set(alljoyn_sessionlistener value) { m_sessionListener = value; }
+ }
+
+ property alljoyn_sessionid SessionId
+ {
+ alljoyn_sessionid get() { return m_sessionId; }
+ }
+
+private:
+ int32 JoinSession(_In_ Windows::Devices::AllJoyn::AllJoynServiceInfo^ serviceInfo);
+
+ // Register a callback function to handle incoming signals.
+ QStatus AddSignalHandler(_In_ alljoyn_busattachment busAttachment, _In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_signalhandler_ptr handler);
+
+ static void CallTextSentSignalHandler(_In_ const alljoyn_interfacedescription_member* member, _In_ alljoyn_message message);
+
+ Windows::Devices::AllJoyn::AllJoynBusAttachment^ m_busAttachment;
+ SecureInterfaceSignals^ m_signals;
+ Platform::String^ m_ServiceObjectPath;
+
+ alljoyn_proxybusobject m_proxyBusObject;
+ alljoyn_busobject m_busObject;
+ alljoyn_sessionlistener m_sessionListener;
+ alljoyn_sessionid m_sessionId;
+ alljoyn_busattachment m_nativeBusAttachment;
+
+ // Used to pass a pointer to this class to callbacks
+ Platform::WeakReference* m_weak;
+
+ // This map is required because we need a way to pass the consumer to the signal
+ // handlers, but the current AllJoyn C API does not allow passing a context to these
+ // callbacks.
+ static std::map SourceInterfaces;
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceEventArgs.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceEventArgs.h
new file mode 100644
index 0000000000..bf3f9a7268
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceEventArgs.h
@@ -0,0 +1,60 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+// Signals
+public ref class SecureInterfaceTextSentReceivedEventArgs sealed
+{
+public:
+ property Windows::Devices::AllJoyn::AllJoynMessageInfo^ MessageInfo
+ {
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ get() { return m_messageInfo; }
+ void set(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ value) { m_messageInfo = value; }
+ }
+
+ property Platform::String^ Message
+ {
+ Platform::String^ get() { return m_interfaceMemberMessage; }
+ internal:
+ void set(_In_ Platform::String^ value) { m_interfaceMemberMessage = value; }
+ }
+
+private:
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ m_messageInfo;
+
+ Platform::String^ m_interfaceMemberMessage;
+};
+
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceMethodResults.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceMethodResults.h
new file mode 100644
index 0000000000..309f856e8b
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceMethodResults.h
@@ -0,0 +1,162 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+ref class SecureInterfaceConsumer;
+
+public ref class SecureInterfaceConcatenateResult sealed
+{
+public:
+ property int32 Status
+ {
+ int32 get() { return m_status; }
+ internal:
+ void set(_In_ int32 value) { m_status = value; }
+ }
+
+ property Platform::String^ OutStr
+ {
+ Platform::String^ get() { return m_interfaceMemberOutStr; }
+ internal:
+ void set(_In_ Platform::String^ value) { m_interfaceMemberOutStr = value; }
+ }
+
+ static SecureInterfaceConcatenateResult^ CreateSuccessResult(_In_ Platform::String^ interfaceMemberOutStr)
+ {
+ auto result = ref new SecureInterfaceConcatenateResult();
+ result->Status = Windows::Devices::AllJoyn::AllJoynStatus::Ok;
+ result->OutStr = interfaceMemberOutStr;
+ return result;
+ }
+
+ static SecureInterfaceConcatenateResult^ CreateFailureResult(_In_ int32 status)
+ {
+ auto result = ref new SecureInterfaceConcatenateResult();
+ result->Status = status;
+ return result;
+ }
+
+private:
+ int32 m_status;
+ Platform::String^ m_interfaceMemberOutStr;
+};
+
+public ref class SecureInterfaceJoinSessionResult sealed
+{
+public:
+ property int32 Status
+ {
+ int32 get() { return m_status; }
+ internal:
+ void set(_In_ int32 value) { m_status = value; }
+ }
+
+ property SecureInterfaceConsumer^ Consumer
+ {
+ SecureInterfaceConsumer^ get() { return m_consumer; }
+ internal:
+ void set(_In_ SecureInterfaceConsumer^ value) { m_consumer = value; }
+ };
+
+private:
+ int32 m_status;
+ SecureInterfaceConsumer^ m_consumer;
+};
+
+public ref class SecureInterfaceGetIsUpperCaseEnabledResult sealed
+{
+public:
+ property int32 Status
+ {
+ int32 get() { return m_status; }
+ internal:
+ void set(_In_ int32 value) { m_status = value; }
+ }
+
+ property bool IsUpperCaseEnabled
+ {
+ bool get() { return m_value; }
+ internal:
+ void set(_In_ bool value) { m_value = value; }
+ }
+
+ static SecureInterfaceGetIsUpperCaseEnabledResult^ CreateSuccessResult(_In_ bool value)
+ {
+ auto result = ref new SecureInterfaceGetIsUpperCaseEnabledResult();
+ result->Status = Windows::Devices::AllJoyn::AllJoynStatus::Ok;
+ result->IsUpperCaseEnabled = value;
+ return result;
+ }
+
+ static SecureInterfaceGetIsUpperCaseEnabledResult^ CreateFailureResult(_In_ int32 status)
+ {
+ auto result = ref new SecureInterfaceGetIsUpperCaseEnabledResult();
+ result->Status = status;
+ return result;
+ }
+
+private:
+ int32 m_status;
+ bool m_value;
+};
+
+public ref class SecureInterfaceSetIsUpperCaseEnabledResult sealed
+{
+public:
+ property int32 Status
+ {
+ int32 get() { return m_status; }
+ internal:
+ void set(_In_ int32 value) { m_status = value; }
+ }
+
+ static SecureInterfaceSetIsUpperCaseEnabledResult^ CreateSuccessResult()
+ {
+ auto result = ref new SecureInterfaceSetIsUpperCaseEnabledResult();
+ result->Status = Windows::Devices::AllJoyn::AllJoynStatus::Ok;
+ return result;
+ }
+
+ static SecureInterfaceSetIsUpperCaseEnabledResult^ CreateFailureResult(_In_ int32 status)
+ {
+ auto result = ref new SecureInterfaceSetIsUpperCaseEnabledResult();
+ result->Status = status;
+ return result;
+ }
+
+private:
+ int32 m_status;
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.cpp
new file mode 100644
index 0000000000..ca583b5871
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.cpp
@@ -0,0 +1,457 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace concurrency;
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::AllJoyn;
+using namespace com::microsoft::Samples::SecureInterface;
+
+std::map SecureInterfaceProducer::SourceObjects;
+std::map SecureInterfaceProducer::SourceInterfaces;
+
+SecureInterfaceProducer::SecureInterfaceProducer(AllJoynBusAttachment^ busAttachment)
+ : m_busAttachment(busAttachment),
+ m_sessionListener(nullptr),
+ m_busObject(nullptr),
+ m_sessionPort(0),
+ m_sessionId(0)
+{
+ m_weak = new WeakReference(this);
+ ServiceObjectPath = ref new String(L"/Service");
+ m_signals = ref new SecureInterfaceSignals();
+ m_busAttachmentStateChangedToken.Value = 0;
+}
+
+SecureInterfaceProducer::~SecureInterfaceProducer()
+{
+ UnregisterFromBus();
+ delete m_weak;
+}
+
+void SecureInterfaceProducer::UnregisterFromBus()
+{
+ if ((nullptr != m_busAttachment) && (0 != m_busAttachmentStateChangedToken.Value))
+ {
+ m_busAttachment->StateChanged -= m_busAttachmentStateChangedToken;
+ m_busAttachmentStateChangedToken.Value = 0;
+ }
+ if (nullptr != SessionPortListener)
+ {
+ alljoyn_busattachment_unbindsessionport(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), m_sessionPort);
+ alljoyn_sessionportlistener_destroy(SessionPortListener);
+ SessionPortListener = nullptr;
+ }
+ if (nullptr != BusObject)
+ {
+ alljoyn_busattachment_unregisterbusobject(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), BusObject);
+ alljoyn_busobject_destroy(BusObject);
+ BusObject = nullptr;
+ }
+ if (nullptr != SessionListener)
+ {
+ alljoyn_sessionlistener_destroy(SessionListener);
+ SessionListener = nullptr;
+ }
+}
+
+bool SecureInterfaceProducer::OnAcceptSessionJoiner(_In_ alljoyn_sessionport sessionPort, _In_ PCSTR joiner, _In_ const alljoyn_sessionopts opts)
+{
+ UNREFERENCED_PARAMETER(sessionPort); UNREFERENCED_PARAMETER(joiner); UNREFERENCED_PARAMETER(opts);
+
+ return true;
+}
+
+void SecureInterfaceProducer::OnSessionJoined(_In_ alljoyn_sessionport sessionPort, _In_ alljoyn_sessionid id, _In_ PCSTR joiner)
+{
+ UNREFERENCED_PARAMETER(joiner);
+
+ // We initialize the Signals object after the session has been joined, because it needs
+ // the session id.
+ m_signals->Initialize(BusObject, id);
+ m_sessionPort = sessionPort;
+ m_sessionId = id;
+
+ alljoyn_sessionlistener_callbacks callbacks =
+ {
+ AllJoynHelpers::SessionLostHandler,
+ AllJoynHelpers::SessionMemberAddedHandler,
+ AllJoynHelpers::SessionMemberRemovedHandler
+ };
+
+ SessionListener = alljoyn_sessionlistener_create(&callbacks, m_weak);
+ alljoyn_busattachment_setsessionlistener(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), id, SessionListener);
+}
+
+void SecureInterfaceProducer::OnSessionLost(_In_ alljoyn_sessionid sessionId, _In_ alljoyn_sessionlostreason reason)
+{
+ if (sessionId == m_sessionId)
+ {
+ AllJoynSessionLostEventArgs^ args = ref new AllJoynSessionLostEventArgs(static_cast(reason));
+ AllJoynHelpers::DispatchEvent([=]() {
+ SessionLost(this, args);
+ });
+ }
+}
+
+void SecureInterfaceProducer::OnSessionMemberAdded(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberAddedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ AllJoynHelpers::DispatchEvent([=]() {
+ SessionMemberAdded(this, args);
+ });
+ }
+}
+
+void SecureInterfaceProducer::OnSessionMemberRemoved(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberRemovedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ AllJoynHelpers::DispatchEvent([=]() {
+ SessionMemberRemoved(this, args);
+ });
+ }
+}
+
+void SecureInterfaceProducer::BusAttachmentStateChanged(_In_ AllJoynBusAttachment^ sender, _In_ AllJoynBusAttachmentStateChangedEventArgs^ args)
+{
+ if (args->State == AllJoynBusAttachmentState::Connected)
+ {
+ QStatus result = AllJoynHelpers::CreateProducerSession(m_busAttachment, m_weak);
+ if (ER_OK != result)
+ {
+ StopInternal(result);
+ return;
+ }
+ }
+ else if (args->State == AllJoynBusAttachmentState::Disconnected)
+ {
+ StopInternal(ER_BUS_STOPPING);
+ }
+}
+
+void SecureInterfaceProducer::CallConcatenateHandler(_Inout_ alljoyn_busobject busObject, _In_ alljoyn_message message)
+{
+ auto source = SourceObjects.find(busObject);
+ if (source == SourceObjects.end())
+ {
+ return;
+ }
+
+ SecureInterfaceProducer^ producer = source->second->Resolve();
+ if (producer->Service != nullptr)
+ {
+ AllJoynMessageInfo^ callInfo = ref new AllJoynMessageInfo(AllJoynHelpers::MultibyteToPlatformString(alljoyn_message_getsender(message)));
+
+ Platform::String^ inputArg0;
+ TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 0), "s", &inputArg0);
+ Platform::String^ inputArg1;
+ TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 1), "s", &inputArg1);
+
+ create_task(producer->Service->ConcatenateAsync(callInfo, inputArg0, inputArg1)).then([busObject, message](SecureInterfaceConcatenateResult^ result)
+ {
+ int32 status;
+
+ if (nullptr == result)
+ {
+ alljoyn_busobject_methodreply_status(busObject, message, ER_BUS_NO_LISTENER);
+ return;
+ }
+
+ status = result->Status;
+ if (AllJoynStatus::Ok != status)
+ {
+ alljoyn_busobject_methodreply_status(busObject, message, static_cast(status));
+ return;
+ }
+
+ size_t argCount = 1;
+ alljoyn_msgarg outputs = alljoyn_msgarg_array_create(argCount);
+
+ status = TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(outputs, 0), "s", result->OutStr);
+ if (AllJoynStatus::Ok != status)
+ {
+ alljoyn_busobject_methodreply_status(busObject, message, static_cast(status));
+ alljoyn_msgarg_destroy(outputs);
+ return;
+ }
+
+ alljoyn_busobject_methodreply_args(busObject, message, outputs, argCount);
+ alljoyn_msgarg_destroy(outputs);
+ }).wait();
+ }
+}
+
+void SecureInterfaceProducer::CallTextSentSignalHandler(_In_ const alljoyn_interfacedescription_member* member, _In_ alljoyn_message message)
+{
+ auto source = SourceInterfaces.find(member->iface);
+ if (source == SourceInterfaces.end())
+ {
+ return;
+ }
+
+ auto producer = source->second->Resolve();
+ if (producer->Signals != nullptr)
+ {
+ auto callInfo = ref new AllJoynMessageInfo(AllJoynHelpers::MultibyteToPlatformString(alljoyn_message_getsender(message)));
+ auto eventArgs = ref new SecureInterfaceTextSentReceivedEventArgs();
+ eventArgs->MessageInfo = callInfo;
+
+ Platform::String^ argument0;
+ TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 0), "s", &argument0);
+ eventArgs->Message = argument0;
+
+ producer->Signals->CallTextSentReceived(producer->Signals, eventArgs);
+ }
+}
+
+QStatus SecureInterfaceProducer::AddMethodHandler(_In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_methodhandler_ptr handler)
+{
+ alljoyn_interfacedescription_member member;
+ if (!alljoyn_interfacedescription_getmember(interfaceDescription, methodName, &member))
+ {
+ return ER_BUS_INTERFACE_NO_SUCH_MEMBER;
+ }
+
+ return alljoyn_busobject_addmethodhandler(
+ m_busObject,
+ member,
+ handler,
+ m_weak);
+}
+
+QStatus SecureInterfaceProducer::AddSignalHandler(_In_ alljoyn_busattachment busAttachment, _In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_signalhandler_ptr handler)
+{
+ alljoyn_interfacedescription_member member;
+ if (!alljoyn_interfacedescription_getmember(interfaceDescription, methodName, &member))
+ {
+ return ER_BUS_INTERFACE_NO_SUCH_MEMBER;
+ }
+
+ return alljoyn_busattachment_registersignalhandler(busAttachment, handler, member, NULL);
+}
+
+QStatus SecureInterfaceProducer::OnPropertyGet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _Inout_ alljoyn_msgarg value)
+{
+ UNREFERENCED_PARAMETER(interfaceName);
+
+ if (0 == strcmp(propertyName, "IsUpperCaseEnabled"))
+ {
+ auto task = create_task(Service->GetIsUpperCaseEnabledAsync(nullptr));
+ auto result = task.get();
+
+ if (AllJoynStatus::Ok != result->Status)
+ {
+ return static_cast(result->Status);
+ }
+
+ return static_cast(TypeConversionHelpers::SetAllJoynMessageArg(value, "b", result->IsUpperCaseEnabled));
+ }
+
+ return ER_BUS_NO_SUCH_PROPERTY;
+}
+
+QStatus SecureInterfaceProducer::OnPropertySet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _In_ alljoyn_msgarg value)
+{
+ UNREFERENCED_PARAMETER(interfaceName);
+
+ if (0 == strcmp(propertyName, "IsUpperCaseEnabled"))
+ {
+ bool argument;
+ TypeConversionHelpers::GetAllJoynMessageArg(value, "b", &argument);
+
+ auto task = create_task(Service->SetIsUpperCaseEnabledAsync(nullptr, argument));
+ auto result = task.get();
+
+ return static_cast(result->Status);
+ }
+ return ER_BUS_NO_SUCH_PROPERTY;
+}
+
+void SecureInterfaceProducer::EmitIsUpperCaseEnabledChanged()
+{
+ create_task([&]
+ {
+ alljoyn_msgarg value = alljoyn_msgarg_create();
+ OnPropertyGet("com.microsoft.Samples.SecureInterface", "IsUpperCaseEnabled", value);
+
+ alljoyn_busobject_emitpropertychanged(
+ m_busObject,
+ "com.microsoft.Samples.SecureInterface",
+ "IsUpperCaseEnabled",
+ value,
+ m_sessionId);
+
+ alljoyn_msgarg_destroy(value);
+ });
+}
+
+void SecureInterfaceProducer::Start()
+{
+ if (nullptr == m_busAttachment)
+ {
+ StopInternal(ER_FAIL);
+ return;
+ }
+
+ QStatus result = AllJoynHelpers::CreateInterfaces(m_busAttachment, c_SecureInterfaceIntrospectionXml);
+ if (result != ER_OK)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ result = AllJoynHelpers::CreateBusObject(m_weak);
+ if (result != ER_OK)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ alljoyn_interfacedescription interfaceDescription = alljoyn_busattachment_getinterface(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), "com.microsoft.Samples.SecureInterface");
+ if (interfaceDescription == nullptr)
+ {
+ StopInternal(ER_FAIL);
+ return;
+ }
+ alljoyn_busobject_addinterface_announced(BusObject, interfaceDescription);
+
+ result = AddMethodHandler(
+ interfaceDescription,
+ "Concatenate",
+ [](alljoyn_busobject busObject, const alljoyn_interfacedescription_member* member, alljoyn_message message) { UNREFERENCED_PARAMETER(member); CallConcatenateHandler(busObject, message); });
+ if (result != ER_OK)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ result = AddSignalHandler(
+ AllJoynHelpers::GetInternalBusAttachment(m_busAttachment),
+ interfaceDescription,
+ "TextSent",
+ [](const alljoyn_interfacedescription_member* member, PCSTR srcPath, alljoyn_message message) { UNREFERENCED_PARAMETER(srcPath); CallTextSentSignalHandler(member, message); });
+ if (result != ER_OK)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ SourceObjects[m_busObject] = m_weak;
+ SourceInterfaces[interfaceDescription] = m_weak;
+
+ unsigned int noneMechanismIndex = 0;
+ bool authenticationMechanismsContainsNone = m_busAttachment->AuthenticationMechanisms->IndexOf(AllJoynAuthenticationMechanism::None, &noneMechanismIndex);
+ QCC_BOOL interfaceIsSecure = alljoyn_interfacedescription_issecure(interfaceDescription);
+
+ // If the current set of AuthenticationMechanisms supports authentication,
+ // determine whether a secure BusObject is required.
+ if (AllJoynHelpers::CanSecure(m_busAttachment->AuthenticationMechanisms))
+ {
+ // Register the BusObject as "secure" if the org.alljoyn.Bus.Secure XML annotation
+ // is specified, or if None is not present in AuthenticationMechanisms.
+ if (!authenticationMechanismsContainsNone || interfaceIsSecure)
+ {
+ result = alljoyn_busattachment_registerbusobject_secure(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), BusObject);
+ }
+ else
+ {
+ result = alljoyn_busattachment_registerbusobject(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), BusObject);
+ }
+ }
+ else
+ {
+ // If the current set of AuthenticationMechanisms does not support authentication
+ // but the interface requires security, report an error.
+ if (interfaceIsSecure)
+ {
+ result = ER_BUS_NO_AUTHENTICATION_MECHANISM;
+ }
+ else
+ {
+ result = alljoyn_busattachment_registerbusobject(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), BusObject);
+ }
+ }
+
+ if (result != ER_OK)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ m_busAttachmentStateChangedToken = m_busAttachment->StateChanged += ref new TypedEventHandler(this, &SecureInterfaceProducer::BusAttachmentStateChanged);
+ m_busAttachment->Connect();
+}
+
+void SecureInterfaceProducer::Stop()
+{
+ StopInternal(AllJoynStatus::Ok);
+}
+
+void SecureInterfaceProducer::StopInternal(int32 status)
+{
+ UnregisterFromBus();
+ Stopped(this, ref new AllJoynProducerStoppedEventArgs(status));
+}
+
+int32 SecureInterfaceProducer::RemoveMemberFromSession(_In_ String^ uniqueName)
+{
+ return alljoyn_busattachment_removesessionmember(
+ AllJoynHelpers::GetInternalBusAttachment(m_busAttachment),
+ m_sessionId,
+ AllJoynHelpers::PlatformToMultibyteString(uniqueName).data());
+}
+
+PCSTR com::microsoft::Samples::SecureInterface::c_SecureInterfaceIntrospectionXml = ""
+" A secure AllJoyn sample "
+" "
+" "
+" Method that concatenates two input strings and returns the concatenated string as output "
+" "
+" "
+" "
+" "
+" "
+" Property to determine if the output of the Concatenate method is returned as upper case string or not "
+" "
+" "
+" "
+" Signal to send a text message "
+" "
+" "
+" "
+;
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.h
new file mode 100644
index 0000000000..c16af8d209
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceProducer.h
@@ -0,0 +1,174 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+extern PCSTR c_SecureInterfaceIntrospectionXml;
+
+ref class SecureInterfaceProducer;
+
+public interface class ISecureInterfaceProducer
+{
+ event Windows::Foundation::TypedEventHandler^ Stopped;
+ event Windows::Foundation::TypedEventHandler^ SessionLost;
+ event Windows::Foundation::TypedEventHandler^ SessionMemberAdded;
+ event Windows::Foundation::TypedEventHandler^ SessionMemberRemoved;
+};
+
+public ref class SecureInterfaceProducer sealed : [Windows::Foundation::Metadata::Default] ISecureInterfaceProducer
+{
+public:
+ SecureInterfaceProducer(Windows::Devices::AllJoyn::AllJoynBusAttachment^ busAttachment);
+ virtual ~SecureInterfaceProducer();
+
+ // The implementation of ISecureInterfaceService that will handle method calls and property requests.
+ property ISecureInterfaceService^ Service
+ {
+ ISecureInterfaceService^ get() { return m_serviceInterface; }
+ void set(ISecureInterfaceService^ value) { m_serviceInterface = value; }
+ }
+
+ // Used to send signals or register functions to handle received signals.
+ property SecureInterfaceSignals^ Signals
+ {
+ SecureInterfaceSignals^ get() { return m_signals; }
+ }
+
+ // This event will fire whenever this producer is stopped.
+ virtual event Windows::Foundation::TypedEventHandler^ Stopped;
+
+ // This event will fire whenever the producer loses the session that it created.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionLost;
+
+ // This event will fire whenever a member joins the session.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionMemberAdded;
+
+ // This event will fire whenever a member leaves the session.
+ virtual event Windows::Foundation::TypedEventHandler^ SessionMemberRemoved;
+
+ // Send a signal to all members of the session to notify them that the value of IsUpperCaseEnabled has changed.
+ void EmitIsUpperCaseEnabledChanged();
+
+ // Start advertising the service.
+ void Start();
+
+ // Stop advertising the service.
+ void Stop();
+
+ // Remove a member that has joined this session.
+ int32 RemoveMemberFromSession(_In_ Platform::String^ uniqueName);
+
+internal:
+ bool OnAcceptSessionJoiner(_In_ alljoyn_sessionport sessionPort, _In_ PCSTR joiner, _In_ const alljoyn_sessionopts opts);
+ void OnSessionJoined(_In_ alljoyn_sessionport sessionPort, _In_ alljoyn_sessionid id, _In_ PCSTR joiner);
+ QStatus OnPropertyGet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _Inout_ alljoyn_msgarg val);
+ QStatus OnPropertySet(_In_ PCSTR interfaceName, _In_ PCSTR propertyName, _In_ alljoyn_msgarg val);
+ void OnSessionLost(_In_ alljoyn_sessionid sessionId, _In_ alljoyn_sessionlostreason reason);
+ void OnSessionMemberAdded(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName);
+ void OnSessionMemberRemoved(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName);
+
+ property Platform::String^ ServiceObjectPath
+ {
+ Platform::String^ get() { return m_ServiceObjectPath; }
+ void set(Platform::String^ value) { m_ServiceObjectPath = value; }
+ }
+
+ property alljoyn_busobject BusObject
+ {
+ alljoyn_busobject get() { return m_busObject; }
+ void set(alljoyn_busobject value) { m_busObject = value; }
+ }
+
+ property alljoyn_sessionportlistener SessionPortListener
+ {
+ alljoyn_sessionportlistener get() { return m_sessionPortListener; }
+ void set(alljoyn_sessionportlistener value) { m_sessionPortListener = value; }
+ }
+
+ property alljoyn_sessionlistener SessionListener
+ {
+ alljoyn_sessionlistener get() { return m_sessionListener; }
+ void set(alljoyn_sessionlistener value) { m_sessionListener = value; }
+ }
+
+ property alljoyn_sessionport SessionPort
+ {
+ alljoyn_sessionport get() { return m_sessionPort; }
+ internal:
+ void set(alljoyn_sessionport value) { m_sessionPort = value; }
+ }
+
+ property alljoyn_sessionid SessionId
+ {
+ alljoyn_sessionid get() { return m_sessionId; }
+ }
+
+ // Stop advertising the service and pass status to anyone listening for the Stopped event.
+ void StopInternal(int32 status);
+
+ void BusAttachmentStateChanged(_In_ Windows::Devices::AllJoyn::AllJoynBusAttachment^ sender, _In_ Windows::Devices::AllJoyn::AllJoynBusAttachmentStateChangedEventArgs^ args);
+
+private:
+ static void CallConcatenateHandler(_Inout_ alljoyn_busobject busObject, _In_ alljoyn_message message);
+ static void CallTextSentSignalHandler(_In_ const alljoyn_interfacedescription_member* member, _In_ alljoyn_message message);
+
+ // Register a callback function to handle methods.
+ QStatus AddMethodHandler(_In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_methodhandler_ptr handler);
+ // Register a callback function to handle incoming signals.
+ QStatus AddSignalHandler(_In_ alljoyn_busattachment busAttachment, _In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_signalhandler_ptr handler);
+
+ void UnregisterFromBus();
+
+ Windows::Devices::AllJoyn::AllJoynBusAttachment^ m_busAttachment;
+ Windows::Foundation::EventRegistrationToken m_busAttachmentStateChangedToken;
+ SecureInterfaceSignals^ m_signals;
+ ISecureInterfaceService^ m_serviceInterface;
+ Platform::String^ m_ServiceObjectPath;
+
+ alljoyn_busobject m_busObject;
+ alljoyn_sessionportlistener m_sessionPortListener;
+ alljoyn_sessionlistener m_sessionListener;
+ alljoyn_sessionport m_sessionPort;
+ alljoyn_sessionid m_sessionId;
+
+ // Used to pass a pointer to this class to callbacks
+ Platform::WeakReference* m_weak;
+
+ // These maps are required because we need a way to pass the producer to the method
+ // and signal handlers, but the current AllJoyn C API does not allow passing a context to these
+ // callbacks.
+ static std::map SourceObjects;
+ static std::map SourceInterfaces;
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.cpp
new file mode 100644
index 0000000000..e784c0ed05
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.cpp
@@ -0,0 +1,75 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Devices::AllJoyn;
+using namespace com::microsoft::Samples::SecureInterface;
+
+// Note: Unlike an Interface implementation, which provides a single handler for each member, the event
+// model allows for 0 or more listeners to be registered. The EventAdapter implementation deals with this
+// difference by implementing a last-writer-wins policy. The lack of any return value (i.e., 0 listeners)
+// is handled by returning a null result.
+
+// Methods
+IAsyncOperation^ SecureInterfaceServiceEventAdapter::ConcatenateAsync(_In_ AllJoynMessageInfo^ info, _In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2)
+{
+ auto args = ref new SecureInterfaceConcatenateCalledEventArgs(info, interfaceMemberInStr1, interfaceMemberInStr2);
+ AllJoynHelpers::DispatchEvent([=]() {
+ ConcatenateCalled(this, args);
+ });
+ return SecureInterfaceConcatenateCalledEventArgs::GetResultAsync(args);
+}
+
+// Property Reads
+IAsyncOperation^ SecureInterfaceServiceEventAdapter::GetIsUpperCaseEnabledAsync(_In_ AllJoynMessageInfo^ info)
+{
+ auto args = ref new SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs(info);
+ AllJoynHelpers::DispatchEvent([=]() {
+ GetIsUpperCaseEnabledRequested(this, args);
+ });
+ return SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::GetResultAsync(args);
+}
+
+// Property Writes
+IAsyncOperation^ SecureInterfaceServiceEventAdapter::SetIsUpperCaseEnabledAsync(_In_ AllJoynMessageInfo^ info, _In_ bool value)
+{
+ auto args = ref new SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs(info, value);
+ AllJoynHelpers::DispatchEvent([=]() {
+ SetIsUpperCaseEnabledRequested(this, args);
+ });
+ return SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::GetResultAsync(args);
+}
+
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.h
new file mode 100644
index 0000000000..f7ea8ccf46
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventAdapter.h
@@ -0,0 +1,59 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+// This class, and the associated EventArgs classes, exist for the benefit of JavaScript developers who
+// do not have the ability to implement ISecureInterfaceService. Instead, SecureInterfaceServiceEventAdapter
+// provides the Interface implementation and exposes a set of compatible events to the developer.
+public ref class SecureInterfaceServiceEventAdapter sealed : [Windows::Foundation::Metadata::Default] ISecureInterfaceService
+{
+public:
+ // Method Invocation Events
+ event Windows::Foundation::TypedEventHandler^ ConcatenateCalled;
+
+ // Property Read Events
+ event Windows::Foundation::TypedEventHandler^ GetIsUpperCaseEnabledRequested;
+
+ // Property Write Events
+ event Windows::Foundation::TypedEventHandler^ SetIsUpperCaseEnabledRequested;
+
+ // ISecureInterfaceService Implementation
+ virtual Windows::Foundation::IAsyncOperation^ ConcatenateAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info, _In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2);
+
+ virtual Windows::Foundation::IAsyncOperation^ GetIsUpperCaseEnabledAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+ virtual Windows::Foundation::IAsyncOperation^ SetIsUpperCaseEnabledAsync(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info, _In_ bool value);
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.cpp
new file mode 100644
index 0000000000..5f09fe837f
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.cpp
@@ -0,0 +1,277 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace concurrency;
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Devices::AllJoyn;
+using namespace com::microsoft::Samples::SecureInterface;
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+// Methods
+SecureInterfaceConcatenateCalledEventArgs::SecureInterfaceConcatenateCalledEventArgs(
+ _In_ AllJoynMessageInfo^ info,
+ _In_ Platform::String^ interfaceMemberInStr1,
+ _In_ Platform::String^ interfaceMemberInStr2)
+ : m_raised(false),
+ m_completionsRequired(0),
+ m_messageInfo(info),
+ m_interfaceMemberInStr1(interfaceMemberInStr1),
+ m_interfaceMemberInStr2(interfaceMemberInStr2)
+{
+ m_result = SecureInterfaceConcatenateResult::CreateFailureResult(ER_NOT_IMPLEMENTED);
+}
+
+Deferral^ SecureInterfaceConcatenateCalledEventArgs::GetDeferral()
+{
+ std::lock_guard lockGuard(m_lock);
+ if (m_raised)
+ {
+ // Cannot ask for a deferral after the event handler has returned.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+
+ m_completionsRequired++;
+ auto handler = ref new DeferralCompletedHandler(this, &SecureInterfaceConcatenateCalledEventArgs::Complete);
+ return ref new Deferral(handler);
+}
+
+void SecureInterfaceConcatenateCalledEventArgs::InvokeAllFinished()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ m_raised = true;
+ invokeNeeded = (m_completionsRequired == 0);
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceConcatenateCalledEventArgs::Complete()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ if (m_completionsRequired == 0)
+ {
+ // This should never happen since Complete() should only be called by Windows.Foundation.Deferral
+ // which will only invoke our completion handler once.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+ m_completionsRequired--;
+ invokeNeeded = (m_raised && (m_completionsRequired == 0));
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceConcatenateCalledEventArgs::InvokeCompleteHandler()
+{
+ if (m_result->Status == ER_NOT_IMPLEMENTED)
+ {
+ throw Exception::CreateException(E_NOTIMPL, "No handlers are registered for ConcatenateCalled.");
+ }
+ else
+ {
+ m_tce.set(m_result);
+ }
+}
+
+// Readable Properties
+SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs(
+ _In_ AllJoynMessageInfo^ info)
+ : m_raised(false),
+ m_completionsRequired(0),
+ m_messageInfo(info)
+{
+ m_result = SecureInterfaceGetIsUpperCaseEnabledResult::CreateFailureResult(ER_NOT_IMPLEMENTED);
+}
+
+Deferral^ SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::GetDeferral()
+{
+ std::lock_guard lockGuard(m_lock);
+ if (m_raised)
+ {
+ // Cannot ask for a deferral after the event handler has returned.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+
+ m_completionsRequired++;
+ auto handler = ref new DeferralCompletedHandler(this, &SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::Complete);
+ return ref new Deferral(handler);
+}
+
+void SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::InvokeAllFinished()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ m_raised = true;
+ invokeNeeded = (m_completionsRequired == 0);
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::Complete()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ if (m_completionsRequired == 0)
+ {
+ // This should never happen since Complete() should only be called by Windows.Foundation.Deferral
+ // which will only invoke our completion handler once.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+ m_completionsRequired--;
+ invokeNeeded = (m_raised && (m_completionsRequired == 0));
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs::InvokeCompleteHandler()
+{
+ if (m_result->Status == ER_NOT_IMPLEMENTED)
+ {
+ throw Exception::CreateException(E_NOTIMPL, "No handlers are registered for GetIsUpperCaseEnabledRequested.");
+ }
+ else
+ {
+ m_tce.set(m_result);
+ }
+}
+
+// Writable Properties
+SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs(
+ _In_ AllJoynMessageInfo^ info,
+ _In_ bool value)
+ : m_raised(false),
+ m_completionsRequired(0),
+ m_messageInfo(info),
+ m_value(value)
+{
+ m_result = SecureInterfaceSetIsUpperCaseEnabledResult::CreateFailureResult(ER_NOT_IMPLEMENTED);
+}
+
+Deferral^ SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::GetDeferral()
+{
+ std::lock_guard lockGuard(m_lock);
+ if (m_raised)
+ {
+ // Cannot ask for a deferral after the event handler has returned.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+
+ m_completionsRequired++;
+ auto handler = ref new DeferralCompletedHandler(this, &SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::Complete);
+ return ref new Deferral(handler);
+}
+
+void SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::InvokeAllFinished()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ m_raised = true;
+ invokeNeeded = (m_completionsRequired == 0);
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::Complete()
+{
+ bool invokeNeeded;
+
+ // We need to hold a lock while modifying private state, but release it before invoking a completion handler.
+ {
+ std::lock_guard lockGuard(m_lock);
+ if (m_completionsRequired == 0)
+ {
+ // This should never happen since Complete() should only be called by Windows.Foundation.Deferral
+ // which will only invoke our completion handler once.
+ throw Exception::CreateException(E_ILLEGAL_METHOD_CALL);
+ }
+ m_completionsRequired--;
+ invokeNeeded = (m_raised && (m_completionsRequired == 0));
+ }
+
+ if (invokeNeeded)
+ {
+ InvokeCompleteHandler();
+ }
+}
+
+void SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs::InvokeCompleteHandler()
+{
+ if (m_result->Status == ER_NOT_IMPLEMENTED)
+ {
+ throw Exception::CreateException(E_NOTIMPL, "No handlers are registered for SetIsUpperCaseEnabledRequested.");
+ }
+ else
+ {
+ m_tce.set(m_result);
+ }
+}
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.h
new file mode 100644
index 0000000000..82476f6f47
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceServiceEventArgs.h
@@ -0,0 +1,180 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+// Methods
+public ref class SecureInterfaceConcatenateCalledEventArgs sealed
+{
+public:
+ SecureInterfaceConcatenateCalledEventArgs(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info, _In_ Platform::String^ interfaceMemberInStr1, _In_ Platform::String^ interfaceMemberInStr2);
+
+ property Windows::Devices::AllJoyn::AllJoynMessageInfo^ MessageInfo
+ {
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ get() { return m_messageInfo; }
+ }
+
+ property SecureInterfaceConcatenateResult^ Result
+ {
+ SecureInterfaceConcatenateResult^ get() { return m_result; }
+ void set(_In_ SecureInterfaceConcatenateResult^ value) { m_result = value; }
+ }
+
+ property Platform::String^ InStr1
+ {
+ Platform::String^ get() { return m_interfaceMemberInStr1; }
+ }
+
+ property Platform::String^ InStr2
+ {
+ Platform::String^ get() { return m_interfaceMemberInStr2; }
+ }
+
+ Windows::Foundation::Deferral^ GetDeferral();
+
+ static Windows::Foundation::IAsyncOperation^ GetResultAsync(SecureInterfaceConcatenateCalledEventArgs^ args)
+ {
+ args->InvokeAllFinished();
+ auto t = concurrency::create_task(args->m_tce);
+ return concurrency::create_async([t]() -> concurrency::task
+ {
+ return t;
+ });
+ }
+
+private:
+ void Complete();
+ void InvokeAllFinished();
+ void InvokeCompleteHandler();
+
+ bool m_raised;
+ int m_completionsRequired;
+ concurrency::task_completion_event m_tce;
+ std::mutex m_lock;
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ m_messageInfo;
+ SecureInterfaceConcatenateResult^ m_result;
+ Platform::String^ m_interfaceMemberInStr1;
+ Platform::String^ m_interfaceMemberInStr2;
+};
+
+// Readable Properties
+public ref class SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs sealed
+{
+public:
+ SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+ property Windows::Devices::AllJoyn::AllJoynMessageInfo^ MessageInfo
+ {
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ get() { return m_messageInfo; }
+ }
+
+ property SecureInterfaceGetIsUpperCaseEnabledResult^ Result
+ {
+ SecureInterfaceGetIsUpperCaseEnabledResult^ get() { return m_result; }
+ void set(_In_ SecureInterfaceGetIsUpperCaseEnabledResult^ value) { m_result = value; }
+ }
+
+ Windows::Foundation::Deferral^ GetDeferral();
+
+ static Windows::Foundation::IAsyncOperation^ GetResultAsync(SecureInterfaceGetIsUpperCaseEnabledRequestedEventArgs^ args)
+ {
+ args->InvokeAllFinished();
+ auto t = concurrency::create_task(args->m_tce);
+ return concurrency::create_async([t]() -> concurrency::task
+ {
+ return t;
+ });
+ }
+
+private:
+ void Complete();
+ void InvokeAllFinished();
+ void InvokeCompleteHandler();
+
+ bool m_raised;
+ int m_completionsRequired;
+ concurrency::task_completion_event m_tce;
+ std::mutex m_lock;
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ m_messageInfo;
+ SecureInterfaceGetIsUpperCaseEnabledResult^ m_result;
+};
+
+// Writable Properties
+public ref class SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs sealed
+{
+public:
+ SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs(_In_ Windows::Devices::AllJoyn::AllJoynMessageInfo^ info, _In_ bool value);
+
+ property Windows::Devices::AllJoyn::AllJoynMessageInfo^ MessageInfo
+ {
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ get() { return m_messageInfo; }
+ }
+
+ property bool Value
+ {
+ bool get() { return m_value; }
+ }
+
+ property SecureInterfaceSetIsUpperCaseEnabledResult^ Result
+ {
+ SecureInterfaceSetIsUpperCaseEnabledResult^ get() { return m_result; }
+ void set(_In_ SecureInterfaceSetIsUpperCaseEnabledResult^ value) { m_result = value; }
+ }
+
+ static Windows::Foundation::IAsyncOperation^ GetResultAsync(SecureInterfaceSetIsUpperCaseEnabledRequestedEventArgs^ args)
+ {
+ args->InvokeAllFinished();
+ auto t = concurrency::create_task(args->m_tce);
+ return concurrency::create_async([t]() -> concurrency::task
+ {
+ return t;
+ });
+ }
+
+ Windows::Foundation::Deferral^ GetDeferral();
+
+private:
+ void Complete();
+ void InvokeAllFinished();
+ void InvokeCompleteHandler();
+
+ bool m_raised;
+ int m_completionsRequired;
+ concurrency::task_completion_event m_tce;
+ std::mutex m_lock;
+ Windows::Devices::AllJoyn::AllJoynMessageInfo^ m_messageInfo;
+ bool m_value;
+ SecureInterfaceSetIsUpperCaseEnabledResult^ m_result;
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.cpp
new file mode 100644
index 0000000000..d21b092fde
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.cpp
@@ -0,0 +1,80 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Devices::AllJoyn;
+using namespace Windows::Foundation;
+using namespace com::microsoft::Samples::SecureInterface;
+
+void SecureInterfaceSignals::Initialize(_In_ alljoyn_busobject busObject, _In_ alljoyn_sessionid sessionId)
+{
+ m_busObject = busObject;
+ m_sessionId = sessionId;
+
+ auto interfaceDefinition = alljoyn_busattachment_getinterface(alljoyn_busobject_getbusattachment(busObject), "com.microsoft.Samples.SecureInterface");
+ alljoyn_interfacedescription_getmember(interfaceDefinition, "TextSent", &m_memberTextSent);
+}
+
+void SecureInterfaceSignals::TextSent(_In_ Platform::String^ interfaceMemberMessage)
+{
+ if (nullptr == m_busObject)
+ {
+ return;
+ }
+
+ size_t argCount = 1;
+ alljoyn_msgarg arguments = alljoyn_msgarg_array_create(argCount);
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(arguments, 0), "s", interfaceMemberMessage);
+
+ alljoyn_busobject_signal(
+ m_busObject,
+ NULL, // Generated code only supports broadcast signals.
+ m_sessionId,
+ m_memberTextSent,
+ arguments,
+ argCount,
+ 0, // A signal with a TTL of 0 will be sent to every member of the session, regardless of how long it takes to deliver the message
+ ALLJOYN_MESSAGE_FLAG_GLOBAL_BROADCAST, // Broadcast to everyone in the session.
+ NULL); // The generated code does not need the generated signal message
+
+ alljoyn_msgarg_destroy(arguments);
+}
+
+void SecureInterfaceSignals::CallTextSentReceived(_In_ SecureInterfaceSignals^ sender, _In_ SecureInterfaceTextSentReceivedEventArgs^ args)
+{
+ AllJoynHelpers::DispatchEvent([=]() {
+ TextSentReceived(sender, args);
+ });
+}
+
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.h
new file mode 100644
index 0000000000..71abc5428e
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceSignals.h
@@ -0,0 +1,63 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+ref class SecureInterfaceSignals;
+
+public interface class ISecureInterfaceSignals
+{
+ event Windows::Foundation::TypedEventHandler^ TextSentReceived;
+};
+
+public ref class SecureInterfaceSignals sealed : [Windows::Foundation::Metadata::Default] ISecureInterfaceSignals
+{
+public:
+ // Calling this method will send the TextSent signal to every member of the session.
+ void TextSent(_In_ Platform::String^ interfaceMemberMessage);
+
+ // This event fires whenever the TextSent signal is sent by another member of the session.
+ virtual event Windows::Foundation::TypedEventHandler^ TextSentReceived;
+
+internal:
+ void Initialize(_In_ alljoyn_busobject busObject, _In_ alljoyn_sessionid sessionId);
+ void CallTextSentReceived(_In_ SecureInterfaceSignals^ sender, _In_ SecureInterfaceTextSentReceivedEventArgs^ args);
+
+private:
+ alljoyn_busobject m_busObject;
+ alljoyn_sessionid m_sessionId;
+
+ alljoyn_interfacedescription_member m_memberTextSent;
+};
+
+} } } }
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceStructures.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceStructures.h
new file mode 100644
index 0000000000..d988bcbfbf
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceStructures.h
@@ -0,0 +1,119 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+public ref class AllJoynMessageArgStructure sealed : Windows::Foundation::Collections::IVector
+{
+public:
+ AllJoynMessageArgStructure()
+ {
+ m_vector = ref new Platform::Collections::Vector();
+ }
+
+ virtual Windows::Foundation::Collections::IIterator^ First()
+ {
+ return m_vector->First();
+ }
+
+ virtual Platform::Object^ GetAt(unsigned int index)
+ {
+ return m_vector->GetAt(index);
+ }
+
+ virtual property unsigned int Size {
+ virtual unsigned int get()
+ {
+ return m_vector->Size;
+ }
+ }
+
+ virtual bool IndexOf(Platform::Object^ value, unsigned int * index)
+ {
+ return m_vector->IndexOf(value, index);
+ }
+
+ virtual unsigned int GetMany(unsigned int startIndex, Platform::WriteOnlyArray^ items)
+ {
+ return m_vector->GetMany(startIndex, items);
+ }
+
+ virtual Windows::Foundation::Collections::IVectorView^ GetView()
+ {
+ return m_vector->GetView();
+ }
+
+ virtual void SetAt(unsigned int index, Platform::Object^ item)
+ {
+ return m_vector->SetAt(index, item);
+ }
+
+ virtual void InsertAt(unsigned int index, Platform::Object^ item)
+ {
+ return m_vector->InsertAt(index, item);
+ }
+
+ virtual void Append(Platform::Object^ item)
+ {
+ return m_vector->Append(item);
+ }
+
+ virtual void RemoveAt(unsigned int index)
+ {
+ return m_vector->RemoveAt(index);
+ }
+
+ virtual void RemoveAtEnd()
+ {
+ return m_vector->RemoveAtEnd();
+ }
+
+ virtual void Clear()
+ {
+ return m_vector->Clear();
+ }
+
+ virtual void ReplaceAll(const Platform::Array^ arr)
+ {
+ return m_vector->ReplaceAll(arr);
+ }
+
+private:
+ Platform::Collections::Vector^ m_vector;
+};
+} } } }
+
+partial ref class TypeConversionHelpers
+{
+internal:
+};
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.cpp
new file mode 100644
index 0000000000..3261adc15e
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.cpp
@@ -0,0 +1,153 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace concurrency;
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::AllJoyn;
+using namespace com::microsoft::Samples::SecureInterface;
+
+SecureInterfaceWatcher::SecureInterfaceWatcher(AllJoynBusAttachment^ busAttachment) :
+ m_aboutListener(nullptr)
+{
+ m_busAttachment = busAttachment;
+ m_weak = new WeakReference(this);
+ m_busAttachmentStateChangedToken.Value = 0;
+}
+
+SecureInterfaceWatcher::~SecureInterfaceWatcher()
+{
+ UnregisterFromBus();
+}
+
+void SecureInterfaceWatcher::UnregisterFromBus()
+{
+ if (nullptr != m_aboutListener)
+ {
+ PCSTR interfaces[] = { "com.microsoft.Samples.SecureInterface" };
+ alljoyn_busattachment_cancelwhoimplements_interfaces(
+ AllJoynHelpers::GetInternalBusAttachment(m_busAttachment),
+ interfaces,
+ _countof(interfaces));
+
+ alljoyn_busattachment_unregisteraboutlistener(AllJoynHelpers::GetInternalBusAttachment(m_busAttachment), m_aboutListener);
+ alljoyn_aboutlistener_destroy(m_aboutListener);
+ m_aboutListener = nullptr;
+ }
+ if ((nullptr != m_busAttachment) && (0 != m_busAttachmentStateChangedToken.Value))
+ {
+ m_busAttachment->StateChanged -= m_busAttachmentStateChangedToken;
+ }
+}
+
+void SecureInterfaceWatcher::OnAnnounce(
+ _In_ PCSTR name,
+ _In_ uint16_t version,
+ _In_ alljoyn_sessionport port,
+ _In_ alljoyn_msgarg objectDescriptionArg,
+ _In_ const alljoyn_msgarg aboutDataArg)
+{
+ UNREFERENCED_PARAMETER(version);
+ UNREFERENCED_PARAMETER(aboutDataArg);
+
+ alljoyn_aboutobjectdescription objectDescription = alljoyn_aboutobjectdescription_create_full(objectDescriptionArg);
+
+ if (alljoyn_aboutobjectdescription_hasinterface(objectDescription, "com.microsoft.Samples.SecureInterface"))
+ {
+ AllJoynServiceInfo^ args = ref new AllJoynServiceInfo(
+ AllJoynHelpers::MultibyteToPlatformString(name),
+ AllJoynHelpers::GetObjectPath(objectDescription, "com.microsoft.Samples.SecureInterface"),
+ port);
+ Added(this, args);
+ }
+ alljoyn_aboutobjectdescription_destroy(objectDescription);
+}
+
+void SecureInterfaceWatcher::BusAttachmentStateChanged(_In_ AllJoynBusAttachment^ sender, _In_ AllJoynBusAttachmentStateChangedEventArgs^ args)
+{
+ if (args->State == AllJoynBusAttachmentState::Connected)
+ {
+ alljoyn_aboutlistener_callback callbacks =
+ {
+ AllJoynHelpers::AnnounceHandler
+ };
+ m_aboutListener = alljoyn_aboutlistener_create(&callbacks, m_weak);
+
+ alljoyn_busattachment_registeraboutlistener(AllJoynHelpers::GetInternalBusAttachment(sender), m_aboutListener);
+ PCSTR interfaces[] = { "com.microsoft.Samples.SecureInterface" };
+
+ auto status = alljoyn_busattachment_whoimplements_interfaces(
+ AllJoynHelpers::GetInternalBusAttachment(sender),
+ interfaces,
+ _countof(interfaces));
+ if (ER_OK != status)
+ {
+ StopInternal(status);
+ }
+ }
+ else if (args->State == AllJoynBusAttachmentState::Disconnected)
+ {
+ StopInternal(ER_BUS_STOPPING);
+ }
+}
+
+void SecureInterfaceWatcher::Start()
+{
+ if (nullptr == m_busAttachment)
+ {
+ StopInternal(ER_FAIL);
+ return;
+ }
+
+ int32 result = AllJoynHelpers::CreateInterfaces(m_busAttachment, c_SecureInterfaceIntrospectionXml);
+ if (result != AllJoynStatus::Ok)
+ {
+ StopInternal(result);
+ return;
+ }
+
+ m_busAttachmentStateChangedToken = m_busAttachment->StateChanged += ref new TypedEventHandler(this, &SecureInterfaceWatcher::BusAttachmentStateChanged);
+ m_busAttachment->Connect();
+}
+
+void SecureInterfaceWatcher::Stop()
+{
+ StopInternal(AllJoynStatus::Ok);
+}
+
+void SecureInterfaceWatcher::StopInternal(int32 status)
+{
+ UnregisterFromBus();
+ Stopped(this, ref new AllJoynProducerStoppedEventArgs(status));
+}
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.h
new file mode 100644
index 0000000000..80aff081f6
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/SecureInterfaceWatcher.h
@@ -0,0 +1,97 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace com { namespace microsoft { namespace Samples { namespace SecureInterface {
+
+ref class SecureInterfaceWatcher;
+
+public interface class ISecureInterfaceWatcher
+{
+ event Windows::Foundation::TypedEventHandler^ Added;
+ event Windows::Foundation::TypedEventHandler^ Stopped;
+};
+
+public ref class SecureInterfaceWatcher sealed : [Windows::Foundation::Metadata::Default] ISecureInterfaceWatcher
+{
+public:
+ SecureInterfaceWatcher(Windows::Devices::AllJoyn::AllJoynBusAttachment^ busAttachment);
+ virtual ~SecureInterfaceWatcher();
+
+ // This event will fire whenever a producer for this service is found.
+ virtual event Windows::Foundation::TypedEventHandler^ Added;
+
+ // This event will fire whenever the watcher is stopped.
+ virtual event Windows::Foundation::TypedEventHandler^ Stopped;
+
+ // Start watching for producers advertising this service.
+ void Start();
+
+ // Stop watching for producers for this service.
+ void Stop();
+
+internal:
+ void OnAnnounce(
+ _In_ PCSTR name,
+ _In_ uint16_t version,
+ _In_ alljoyn_sessionport port,
+ _In_ alljoyn_msgarg objectDescriptionArg,
+ _In_ const alljoyn_msgarg aboutDataArg);
+
+ void OnPropertyChanged(_In_ PCSTR prop_name, _In_ alljoyn_msgarg prop_value)
+ {
+ UNREFERENCED_PARAMETER(prop_name); UNREFERENCED_PARAMETER(prop_value);
+ }
+
+ property Windows::Devices::AllJoyn::AllJoynBusAttachment^ BusAttachment
+ {
+ Windows::Devices::AllJoyn::AllJoynBusAttachment^ get() { return m_busAttachment; }
+ }
+
+ // Stop watching for producers advertising this service and pass status to anyone listening for the Stopped event.
+ void StopInternal(int32 status);
+
+ void BusAttachmentStateChanged(_In_ Windows::Devices::AllJoyn::AllJoynBusAttachment^ sender, _In_ Windows::Devices::AllJoyn::AllJoynBusAttachmentStateChangedEventArgs^ args);
+
+private:
+ void UnregisterFromBus();
+
+ Windows::Devices::AllJoyn::AllJoynBusAttachment^ m_busAttachment;
+ Windows::Foundation::EventRegistrationToken m_busAttachmentStateChangedToken;
+
+ alljoyn_aboutlistener m_aboutListener;
+
+ // Used to pass a pointer to this class to callbacks.
+ Platform::WeakReference* m_weak;
+};
+
+} } } }
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.cpp b/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.cpp
new file mode 100644
index 0000000000..4b23b663b1
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.cpp
@@ -0,0 +1,32 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
diff --git a/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.h b/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.h
new file mode 100644
index 0000000000..4fbebeac1d
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario1WinRTComponent/pch.h
@@ -0,0 +1,63 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "AllJoynHelpers.h"
+#include "AllJoynBusObjectManager.h"
+
+#define PROJECT_NAMESPACE com::microsoft::Samples::SecureInterface
+
+#include "SecureInterfaceStructures.h"
+#include "TypeConversionHelpers.h"
+#include "SecureInterfaceMethodResults.h"
+#include "SecureInterfaceEventArgs.h"
+#include "ISecureInterfaceService.h"
+#include "SecureInterfaceSignals.h"
+#include "SecureInterfaceProducer.h"
+#include "SecureInterfaceWatcher.h"
+#include "SecureInterfaceConsumer.h"
+#include "SecureInterfaceServiceEventArgs.h"
+#include "SecureInterfaceServiceEventAdapter.h"
\ No newline at end of file
diff --git a/Samples/AllJoyn/Common/Scenario2WinRTComponent/IOnboardingService.h b/Samples/AllJoyn/Common/Scenario2WinRTComponent/IOnboardingService.h
new file mode 100644
index 0000000000..70419c155a
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario2WinRTComponent/IOnboardingService.h
@@ -0,0 +1,68 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+namespace org { namespace alljoyn { namespace Onboarding {
+
+public interface class IOnboardingService
+{
+public:
+ // Implement this function to handle calls to the ConfigureWiFi method.
+ Windows::Foundation::IAsyncOperation^ ConfigureWiFiAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info , _In_ Platform::String^ interfaceMemberSSID, _In_ Platform::String^ interfaceMemberPassphrase, _In_ int16 interfaceMemberAuthType);
+
+ // Implement this function to handle calls to the Connect method.
+ Windows::Foundation::IAsyncOperation^ ConnectAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info );
+
+ // Implement this function to handle calls to the Offboard method.
+ Windows::Foundation::IAsyncOperation^ OffboardAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info );
+
+ // Implement this function to handle calls to the GetScanInfo method.
+ Windows::Foundation::IAsyncOperation^ GetScanInfoAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info );
+
+ // Implement this function to handle requests for the value of the Version property.
+ //
+ // Currently, info will always be null, because no information is available about the requestor.
+ Windows::Foundation::IAsyncOperation^ GetVersionAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+ // Implement this function to handle requests for the value of the State property.
+ //
+ // Currently, info will always be null, because no information is available about the requestor.
+ Windows::Foundation::IAsyncOperation^ GetStateAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+ // Implement this function to handle requests for the value of the LastError property.
+ //
+ // Currently, info will always be null, because no information is available about the requestor.
+ Windows::Foundation::IAsyncOperation^ GetLastErrorAsync(Windows::Devices::AllJoyn::AllJoynMessageInfo^ info);
+
+};
+
+} } }
diff --git a/Samples/AllJoyn/Common/Scenario2WinRTComponent/OnboardingConsumer.cpp b/Samples/AllJoyn/Common/Scenario2WinRTComponent/OnboardingConsumer.cpp
new file mode 100644
index 0000000000..41ce62edae
--- /dev/null
+++ b/Samples/AllJoyn/Common/Scenario2WinRTComponent/OnboardingConsumer.cpp
@@ -0,0 +1,536 @@
+//*********************************************************
+//
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+//
+//*********************************************************
+//-----------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// Tool: AllJoynCodeGenerator.exe
+//
+// This tool is located in the Windows 10 SDK and the Windows 10 AllJoyn
+// Visual Studio Extension in the Visual Studio Gallery.
+//
+// The generated code should be packaged in a Windows 10 C++/CX Runtime
+// Component which can be consumed in any UWP-supported language using
+// APIs that are available in Windows.Devices.AllJoyn.
+//
+// Using AllJoynCodeGenerator - Invoke the following command with a valid
+// Introspection XML file and a writable output directory:
+// AllJoynCodeGenerator -i -o
+//
+//-----------------------------------------------------------------------------
+#include "pch.h"
+
+using namespace concurrency;
+using namespace Microsoft::WRL;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Devices::AllJoyn;
+using namespace org::alljoyn::Onboarding;
+
+std::map OnboardingConsumer::SourceInterfaces;
+
+OnboardingConsumer::OnboardingConsumer(AllJoynBusAttachment^ busAttachment)
+ : m_busAttachment(busAttachment),
+ m_proxyBusObject(nullptr),
+ m_busObject(nullptr),
+ m_sessionListener(nullptr),
+ m_sessionId(0)
+{
+ m_weak = new WeakReference(this);
+ m_signals = ref new OnboardingSignals();
+ m_nativeBusAttachment = AllJoynHelpers::GetInternalBusAttachment(m_busAttachment);
+}
+
+OnboardingConsumer::~OnboardingConsumer()
+{
+ AllJoynBusObjectManager::ReleaseBusObject(m_nativeBusAttachment, AllJoynHelpers::PlatformToMultibyteString(ServiceObjectPath).data());
+ if (SessionListener != nullptr)
+ {
+ alljoyn_busattachment_setsessionlistener(m_nativeBusAttachment, m_sessionId, nullptr);
+ alljoyn_sessionlistener_destroy(SessionListener);
+ }
+ if (nullptr != ProxyBusObject)
+ {
+ alljoyn_proxybusobject_destroy(ProxyBusObject);
+ }
+ delete m_weak;
+}
+
+void OnboardingConsumer::OnSessionLost(_In_ alljoyn_sessionid sessionId, _In_ alljoyn_sessionlostreason reason)
+{
+ if (sessionId == m_sessionId)
+ {
+ AllJoynSessionLostEventArgs^ args = ref new AllJoynSessionLostEventArgs(static_cast(reason));
+ SessionLost(this, args);
+ }
+}
+
+void OnboardingConsumer::OnSessionMemberAdded(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberAddedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ SessionMemberAdded(this, args);
+ }
+}
+
+void OnboardingConsumer::OnSessionMemberRemoved(_In_ alljoyn_sessionid sessionId, _In_ PCSTR uniqueName)
+{
+ if (sessionId == m_sessionId)
+ {
+ auto args = ref new AllJoynSessionMemberRemovedEventArgs(AllJoynHelpers::MultibyteToPlatformString(uniqueName));
+ SessionMemberRemoved(this, args);
+ }
+}
+
+QStatus OnboardingConsumer::AddSignalHandler(_In_ alljoyn_busattachment busAttachment, _In_ alljoyn_interfacedescription interfaceDescription, _In_ PCSTR methodName, _In_ alljoyn_messagereceiver_signalhandler_ptr handler)
+{
+ alljoyn_interfacedescription_member member;
+ if (!alljoyn_interfacedescription_getmember(interfaceDescription, methodName, &member))
+ {
+ return ER_BUS_INTERFACE_NO_SUCH_MEMBER;
+ }
+
+ return alljoyn_busattachment_registersignalhandler(busAttachment, handler, member, NULL);
+}
+
+IAsyncOperation^ OnboardingConsumer::JoinSessionAsync(
+ _In_ AllJoynServiceInfo^ serviceInfo, _Inout_ OnboardingWatcher^ watcher)
+{
+ return create_async([serviceInfo, watcher]() -> OnboardingJoinSessionResult^
+ {
+ auto result = ref new OnboardingJoinSessionResult();
+ result->Status = AllJoynStatus::Ok;
+ result->Consumer = nullptr;
+
+ result->Consumer = ref new OnboardingConsumer(watcher->BusAttachment);
+ result->Status = result->Consumer->JoinSession(serviceInfo);
+
+ return result;
+ });
+}
+
+IAsyncOperation^ OnboardingConsumer::ConfigureWiFiAsync(_In_ Platform::String^ interfaceMemberSSID, _In_ Platform::String^ interfaceMemberPassphrase, _In_ int16 interfaceMemberAuthType)
+{
+ return create_async([this, interfaceMemberSSID, interfaceMemberPassphrase, interfaceMemberAuthType]() -> OnboardingConfigureWiFiResult^
+ {
+ auto result = ref new OnboardingConfigureWiFiResult();
+
+ alljoyn_message message = alljoyn_message_create(m_nativeBusAttachment);
+ size_t argCount = 3;
+ alljoyn_msgarg inputs = alljoyn_msgarg_array_create(argCount);
+
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(inputs, 0), "s", interfaceMemberSSID);
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(inputs, 1), "s", interfaceMemberPassphrase);
+ TypeConversionHelpers::SetAllJoynMessageArg(alljoyn_msgarg_array_element(inputs, 2), "n", interfaceMemberAuthType);
+
+ QStatus status = alljoyn_proxybusobject_methodcall(
+ ProxyBusObject,
+ "org.alljoyn.Onboarding",
+ "ConfigureWiFi",
+ inputs,
+ argCount,
+ message,
+ c_MessageTimeoutInMilliseconds,
+ 0);
+ result->Status = static_cast(status);
+ if (ER_OK == status)
+ {
+ result->Status = AllJoynStatus::Ok;
+ int16 argument0;
+ status = static_cast(TypeConversionHelpers::GetAllJoynMessageArg(alljoyn_message_getarg(message, 0), "n", &argument0));
+ result->Status2 = argument0;
+
+ if (status != ER_OK)
+ {
+ result->Status = static_cast(status);
+ }
+ }
+ else if (ER_BUS_REPLY_IS_ERROR_MESSAGE == status)
+ {
+ alljoyn_msgarg errorArg = alljoyn_message_getarg(message, 1);
+ if (nullptr != errorArg)
+ {
+ uint16 errorStatus;
+ status = alljoyn_msgarg_get_uint16(errorArg, &errorStatus);
+ if (ER_OK == status)
+ {
+ status = static_cast(errorStatus);
+ }
+ }
+ result->Status = static_cast(status);
+ }
+
+ alljoyn_message_destroy(message);
+ alljoyn_msgarg_destroy(inputs);
+
+ return result;
+ });
+}
+IAsyncOperation^ OnboardingConsumer::ConnectAsync()
+{
+ return create_async([this]() -> OnboardingConnectResult^
+ {
+ auto result = ref new OnboardingConnectResult();
+
+ alljoyn_message message = alljoyn_message_create(m_nativeBusAttachment);
+ size_t argCount = 0;
+ alljoyn_msgarg inputs = alljoyn_msgarg_array_create(argCount);
+
+
+ QStatus status = alljoyn_proxybusobject_methodcall(
+ ProxyBusObject,
+ "org.alljoyn.Onboarding",
+ "Connect",
+ inputs,
+ argCount,
+ message,
+ c_MessageTimeoutInMilliseconds,
+ 0);
+ result->Status = static_cast(status);
+
+ alljoyn_message_destroy(message);
+ alljoyn_msgarg_destroy(inputs);
+
+ return result;
+ });
+}
+IAsyncOperation^ OnboardingConsumer::OffboardAsync()
+{
+ return create_async([this]() -> OnboardingOffboardResult^
+ {
+ auto result = ref new OnboardingOffboardResult();
+
+ alljoyn_message message = alljoyn_message_create(m_nativeBusAttachment);
+ size_t argCount = 0;
+ alljoyn_msgarg inputs = alljoyn_msgarg_array_create(argCount);
+
+
+ QStatus status = alljoyn_proxybusobject_methodcall(
+ ProxyBusObject,
+ "org.alljoyn.Onboarding",
+ "Offboard",
+ inputs,
+ argCount,
+ message,
+ c_MessageTimeoutInMilliseconds,
+ 0);
+ result->Status = static_cast(status);
+
+ alljoyn_message_destroy(message);
+ alljoyn_msgarg_destroy(inputs);
+
+ return result;
+ });
+}
+IAsyncOperation^ OnboardingConsumer::GetScanInfoAsync()
+{
+ return create_async([this]() -> OnboardingGetScanInfoResult^
+ {
+ auto result = ref new OnboardingGetScanInfoResult();
+
+ alljoyn_message message = alljoyn_message_create(m_nativeBusAttachment);
+ size_t argCount = 0;
+ alljoyn_msgarg inputs = alljoyn_msgarg_array_create(argCount);
+
+
+ QStatus status = alljoyn_proxybusobject_methodcall(
+ ProxyBusObject,
+ "org.alljoyn.Onboarding",
+ "GetScanInfo",
+ inputs,
+ argCount,
+ message,
+ c_MessageTimeoutInMilliseconds,
+ 0);
+ result->Status = static_cast(status);
+ if (ER_OK == status)
+ {
+ result->Status = AllJoynStatus::Ok;
+ uint16 argument0;
+ status = static_cast