Cast video to TV using MediaPlayerElement - c++

I have the following XAML
<MediaPlayerElement x:Name="EmbeddedPlayer" AreTransportControlsEnabled="True" HorizontalAlignment="Stretch" IsDoubleTapEnabled="True" DoubleTapped="OnEmbeddedPlayerDoubleTapped"> </MediaPlayerElement>
According to this official documentation, I should be able to use the available Cast button to cast the video to my TV. The Movies & TV app can does that: When I clicked the cast button in that app, it lists the available targets. But when I do the same thing for my app, it asks me to make sure that the devices are discoverable and no progress ring indicating device searching/discovery was going on. (I am on a Lumia 635.) Once again, I feel the frustration of mismatching between documentation and reality!
Is there a complete working example for video/audio casting?
EDIT: I added the simplified code following the third method for device discovery given in the article:
using namespace Windows::Devices::Enumeration;
MainPage::MainPage()
{
// Other set up
DeviceWatcher ^deviceWatcher;
CastingConnection ^castingConnection;
//Create our watcher and have it find casting devices capable of video casting
deviceWatcher = DeviceInformation::CreateWatcher(CastingDevice::GetDeviceSelector(CastingPlaybackTypes::Video));
//Register for watcher events
deviceWatcher->Added += ref new TypedEventHandler<DeviceWatcher^, DeviceInformation^>(this, &MainPage::DeviceWatcher_Added);
deviceWatcher->Start();
}
void MainPage::DeviceWatcher_Added(Windows::Devices::Enumeration::DeviceWatcher^ sender, Windows::Devices::Enumeration::DeviceInformation^ args)
{
Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([args]()
{
//Add each discovered device to our listbox
create_task(CastingDevice::FromIdAsync(args->Id)).then([](CastingDevice^ addedDevice)
{
OutputDebugString(("Found cast device " + addedDevice->FriendlyName + "\n")->Data());
}, task_continuation_context::use_current());
//castingDevicesListBox.Items.Add(addedDevice);
}));
}
As I anticipated, there is no device discovered. There might probably be some extra steps to take care of permission (allow app to discover & cast to devices) etc. that are never specified in the documentation.

Contrary to the documentation, one MUST NOT use MediaPlayerElement but the deprecated MediaElement for casting on mobile. This hint is taken from https://social.msdn.microsoft.com/Forums/en-US/0c37a74f-1331-4fb8-bfdf-3df11d953098/uwp-mediaplayerelement-mediacasting-is-broken-?forum=wpdevelop
This also solves a problem I previously asked about showing video in fullscreen: Fullscreen works like a charm for MediaElement on mobile; but not the supposely upgraded MediaPlayerElement.
I should have realized this obvious fact given that Microsoft already abandoned Windows 10 Mobile.

Related

Correctly setting up MMDevice in a DirectX project

I am currently trying to piece together a shader-based music visualizer. The plan is to read data from the current MMDevice, which I'm trying to follow the documentation for, but I must be doing something wrong because I had to jump through all sorts of hoops to get even just the MMDeviceEnumerator to compile.
In order for the uuids of MMDeviceEnumerator and IMMDeviceEnumerator to be defined, I had to set #define WINAPI_FAMILY WINAPI_FAMILY_GAMES. This was also required for EDataFlow and ERole enumerations to be defined. My first question is if I've missed some configuration somewhere, or if this is the intended method of enabling these things.
Currently, I have the following code in an AudioStream class:
class AudioStream {
public:
AudioStream() {
//SUCCEEDING(CoInitializeEx(nullptr, COINIT_MULTITHREADED));
SUCCEEDING(CoCreateInstance(
__uuidof(IMMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(MMDeviceEnumerator),
(void**)&this->mmDeviceEnumerator));
SUCCEEDING(this->mmDeviceEnumerator->GetDefaultAudioEndpoint(
eRender,
eConsole,
&this->mmDevice));
}
private:
IAudioClient* audioClient = NULL;
IAudioCaptureClient* captureClient = NULL;
IMMDeviceEnumerator* mmDeviceEnumerator = NULL;
IMMDevice* mmDevice = NULL;
};
If you're familiar with what the DirectX 12 project template looks like, this object is being instantiated in the Sample3DSceneRenderer constructor. The main issue I'm having right now is the following two errors which are immediately raised during startup:
onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!75AA0DFF: (caller: 75B1CF2C) ReturnHr(1) tid(42a8) 80040154 Class not registered
onecore\com\combase\dcomrem\resolver.cxx(2507)\combase.dll!75B1CF4D: (caller: 75AA29E4) ReturnHr(2) tid(42a8) 80040154 Class not registered
This causes the entire app to hang, and the project template visualization to never appear (the succeeding macro exits). Does anyone have any idea why this is failing? It must have to be something with the CoCreateInstance call :(
You are writing a Universal Windows Platform (UWP) app because that's what the "built-in" DirectX 12 App project template creates in Visual Studio. UWPs do not have access to all the same APIs and IMMDevice is not part of the UWP API surface area.
The fact that you defined WINAPI_FAMILY_GAMES means you hacked the API Family Partition macros which will define the API in a UWP context, but it doesn't mean that API actually works from the AppContainer process that all UWPs run in.
You really have two options:
(1) If you want to write a UWP, then you will need to enumerate audio devices via the proper Windows Runtime APIs which are in the Windows::Devices::Enumeration namespace.
Assuming you are using C++/CX language extensions (instead of the more modern C++/WinRT projections), then this code works:
auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
while (operation->Status == Windows::Foundation::AsyncStatus::Started)
{
Sleep(100);
}
if (operation->Status != Windows::Foundation::AsyncStatus::Completed)
{
throw std::runtime_error("FindAllAsync");
}
DeviceInformationCollection^ devices = operation->GetResults();
for (unsigned i = 0; i < devices->Size; ++i)
{
using Windows::Devices::Enumeration::DeviceInformation;
DeviceInformation^ d = devices->GetAt(i);
// d->Id->Data();
// d->Name->Data();
}
Also, if you want to get access to the audio capture device from a UWP, you must add a capability to your manifest to request it via <DeviceCapability Name="microphone"/>. See Microsoft Docs.
You should take the time to read the Microsoft Docs on UWPs so you have a better idea of what's supported and what's not.
(2) If you want to write a Win32 desktop app, use the directx-vs-templates instead which include DirectX 12 starting templates for Win32 desktop apps (plus alternative DirectX templates for UWP if that's your thing).
Whichever appmodel you use, you may want to take a look at DirectX Tool Kit for Audio.
BTW, WINAPI_FAMILY_GAMES is used by the Microsoft GDK for Xbox which is for writing titles for Xbox One and Xbox Series X|S. It uses Win32 APIs and doesn't use Windows Runtime APIs, so it has the IMMDevice interface in it's API surface. See Microsoft Docs.

How to allow device to support allocations for both RX_DIGITIZER and RX_DIGITIZER_CHANNELIZER?

I'm using CentOS 6.6 (64-bit) and RH 1.10.2
I have a waveform that requires a FRONTEND::TUNER device that is of type RX_DIGITIZER. I also have a 1.10.2 based device that is a RX_DIGITIZER_CHANNELIZER. This device has all the functionality that the waveform needs, but the waveform will not use it because of the different tuner type.
I see that it is not picked because FrontendTunerDevice<TunerStatusStructType>::allocateCapacity() (in fe_tuner_device.cpp) that my device inherits looks for an exact match on tuner_type.
I'm not seeing any elegant ways around this. Here are the two not so elegant ways I can see around it.
I can either completely override allocateCapacity and duplicate 95% of its logic, but explicitly accept both tuner types.
Or I can override allocateCapacity and modify the capabilities before passing to the superclass method. In pseudo-code:
CORBA::Boolean MyDevice::allocateCapacity(const CF::Properties & capacities)
{
if ( capacities ask for RX_DITIGIZER ) {
CF::Properties caps = capacities;
change type to RX_DITIGIZER_CHANNELIZER
return super::allocateCapacity(caps);
} else {
return super::allocateCapacity(capacities);
}
}
Is there a better way?
The FrontEnd interfaces specification as outlined in Appendix E of the REDHAWK User Manual is a guide and has been known to be interpreted in different ways by REDHAWK device developers. In your case, the simplest solution would be to change the allocation in your waveform to an RX_DIGITIZER_CHANNELIZER and connect a listener to the device, assuming the device has the ability to output wideband data (RX_DIGITIZER). Otherwise, your suggested approach is correct while keeping in mind that the device must perform the appropriate bookkeeping should a user allocated DDCs against the CHANNELIZER portion of this device.
For more information, please refer to section E.2 on Frontend Tuner Types.

Google Play Services C++ / Run UI on second activity using IntentHandler

I am developing a mobile game using Cocos2D-x engine for android platform and i want to integrate GPGS on it.
I achieved to show leaderboards, but there is a little annoying problem. When leaderboard is visible, if i go background and then come back to app, the gamescene goes to black. I think opengl context being released and doesnt restore again. In my opinion running leaderboard on same activity causes this, the game engine cant understand whats happening there. Whatever, because of this I want to run leaderboard (and also all GPGS things) on a new activity using intent.
Google likes "Providing"
In the reference documents of Google Play Game Services C++ SDK, there is a few unclear/fuzzy explanation about using SetOptionalIntentHandlerForUI method.
"Provide a function that can start a provided UI intent at any point, using startActivityForResult."
What is the mean of "Providing"? What is a provided Intent? How will I use startActivityForResult method? Unfortunately, "using" and "providing methods" are not clear expressions for coding. There is no sample about
using this method in the documents of GPGS for C++. Eventually,
Google's document is so poor and
there is no useful information on the internet. If someone from Google helps me, I will be so happy.
As i understand, I wrote the code like this. But it gives error when starting.
AppActivity.java
public void runGPGSActivity(Intent i) {
startActivityForResult(i,100);
}
AndroidPlatformConfiguration.h (From C++ gpg lib)
typedef std::function<void(jobject)> IntentHandler;
AndroidPlatformConfiguration &SetOptionalIntentHandlerForUI(
IntentHandler intent_handler);
main.cpp (JNI binding, the working code, GPGS runs on same activity )
gpg::AndroidPlatformConfiguration platform_configuration;
platform_configuration.SetActivity(activity);
StateManager::InitServices( ...
main.cpp (JNI binding, GPGS must be run on new activity )
gpg::AndroidPlatformConfiguration platform_configuration;
jclass activityClass = env->FindClass("org/cocos2dx/cpp/AppActivity");
jmethodID jIntentHandlerMethodID = env->GetMethodID(activityClass,"runGPGSActivity","(Landorid/content/Intent;)V");
jobject jIntentHandler = env->NewObject(activityClass, jIntentHandlerMethodID);
gpg::AndroidPlatformConfiguration::IntentHandler mIntentHandler; /*= [](jobject mjIntentHandler){};*/
std::function<void(jobject)> intentHandler = std::bind(mIntentHandler,jIntentHandler);
platform_configuration.SetOptionalIntentHandlerForUI(intentHandler);
platform_configuration.SetActivity(activity);
StateManager::InitServices(
There is no build error, but the application crashes when launching.
03-24 14:12:24.301: A/libc(21352): Fatal signal 6 (SIGABRT) at
0x00005368 (code=-6), thread 21352 (main)
And some links about this issue:
IntentHandler reference
StartActivityForResult reference
/// Thank you in advance. ///
...Yeah I solved the problem, but didn't use IntentHandler method.
I was using this code in my app, to show weekly leaderboard data.
gameServices->Leaderboards().ShowUIBlocking(leaderboardId,gpg::LeaderboardTimeSpan::WEEKLY);
But return value is not void, it is UIStatus (whatever it is)
I've reverted back to this code, app is not going to black screen now. This method returns void, I think I have to catch some callbacks when using ShowUIBlocking method, with that UIStatus thing.
gameServices->Leaderboards().ShowUI(leaderboardId);
But now, I can't benefit from timespan feature of leaderboards.
I am going to research how it can be used. There is no problem for now. But, documentation of SetOptionalIntentHandlerForUI must be written more explicit, for programmers who want to use it.

How to disable cache in Windows 8 Xaml based ListView?

What I'm trying to do is to fill ListView in Windows 8 Metro application dynamically with pre-loaded images.
for each item (URI) I'm doing it plain simple with the code like this (C++):
Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapSrc =
ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();
bitmapSrc->CreateOptions = Windows::UI::Xaml::Media::Imaging::BitmapCreateOptions::IgnoreImageCache;
bitmapSrc->UriSource = uri;
img->Source = bitmapSrc;
LoadListView->Items->Append(img);
but when I delete (in the app) source image described by URI and I create new file with the same name and try to reload it into the list then I fail and image shown is the old one (deleted). I presume some cache works here. I tried to avoid caching by IgnoreImageCache value in CreateOptions but it didn't work.
Any clues how to disable caching of BitmapSource (Image) potentially bound to ListView in Windows 8 app?
I tried several directions inspired by Silverlight and WPF, none worked unfortunately.
Encouraged by comments, I put answer I've found myself.
Broader context (and also C# perspective) is explained here:
http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/171dfe66-78b5-4340-bd78-244337f31287/
Shortly I believe it's a problem with reference counting here.
WinRT keeps the image loaded (cached) in BitmapImage^ as long as Uri is valid and asigned to the object instance, that in my example is added to the list.
Cleaning Uri from BitmapImage^ prior to releasing it from the list solved problem in my case.
According to example in question, below code solves the problem (included in the part where the list removal is performed):
auto item = (Image^)LoadListView->Items->GetAt(selected);
auto src = (Windows::UI::Xaml::Media::Imaging::BitmapImage^)item->Source;
src->UriSource = nullptr; //this line is critical
LoadListView->Items->RemoveAt(selected);

Adobe Adam and Eve (C++ ASL): how to bind Eve variable so to get it updated inside C++ application?

So we know how to compile it, we have seen its demos and loved it. We have seen probably only one real life opensource project based on it. So I look at the samples and see only 3 quite long C++ applications that can be ofmy intrest ASL\test\adam_tutorial\, ASL\test\adam_smoke\, ASL\test\eve_smoke\. But I still do not get how htving simple Eve file with:
dialog(name: "Clipping Path")
{
column(child_horizontal: align_fill)
{
popup(name: "Path:", bind: #path, items:
[
{ name: "None", value: empty },
{ name: "Path 1", value: 1 },
{ name: "Path 2", value: 2 }
]);
edit_number(name: "Flatness:", digits: 9, bind: #flatness);
}
button(name: "OK", default: true, bind: #result);
}
in it, Adam file bound to it (theoretically, because I do not quite get how to bind Eve to adam and see no tutorialon how to do this), with
sheet clipping_path
{
output:
result <== { path: path, flatness: flatness };
interface:
unlink flatness : 0.0 <== (path == empty) ? 0.0 : flatness;
path : 1;
}
in it, make each time flatness variableis changed some C++ function of mine called (A simple one couting new flatness value for example)
So How to implement such thing with Adobe Adam and Eve and Boost ofcourse?
Update
We have tried to do it here and it worked but not in a live feedback way - only on dialog close action. And than here but due to our compile evrething on linux absession we have paused our development in ASL programming and started investing time into ASL compilation on Linux OS.
A good place to ask questions about ASL is on the ASL developer mailing list: http://sourceforge.net/mail/?group_id=132417.
You might want to look at the "Begin" test app . Although this only runs Mac and Win it does demonstrate how to wire things up.
The basic idea is that when a layout description (Eve) is parsed it will call your add_view_proc http://stlab.adobe.com/structadobe_1_1eve__callback__suite__t.html#a964b55af7417ae24aacbf552d1efbda4 with the arguments expression. Normally you use bind_layout_proc for the callback which will handle the argument evaluation for your and call a simplified callback that takes a dictionary with the arguments.
When your callback is invoked, you would typically create an appropriate widget and associate the dictionary to the widget or extract the arguments of interest from the dictionary and store them in a struct. Using the bind argument, you can setup callbacks with the associated sheet (Adam), using the monitor_xxxx functions on sheet_t. Usually you'll use monitor_value and monitor_enabled. When called, you set the value or enabled state on the widget. When the widgets value is changed by the user, and widget is invoked (it may be through an event handler, or a callback, or whatever mechanism your UI toolkit supports) you call sheet_t::set() to set the value of the cell and then sheet_t::update() to cause the sheet to recalculate.
That's about it - When trying to get Adam/Eve going with a new UI framework - start small. I usually start with just a window containing two checkboxs and wire up Eve first. Once that is going add Adam and a simple sheet connecting two boolean cells so you can see if things are happening correctly. Once you have that going you'll find it's pretty simple to get much more complex UIs wired up.