locked
Convert C# code to C++

    Question

  • async private void SetLocalMedia()
    {
        var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
    
        openPicker.SuggestedStartLocation = 
            Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
    
        openPicker.FileTypeFilter.Add(".wmv");
        openPicker.FileTypeFilter.Add(".mp4");
    
        var file = await openPicker.PickSingleFileAsync();
    
        var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
    
        // mediaControl is a MediaElement defined in XAML
        mediaControl.SetSource(stream, file.ContentType);
    
        mediaControl.Play();
    }

    This is a sample code clip for C# in MSDN, but no C++ sample. It looks quite simple in C#. But I can not convert it to C++. There is no var stream in C++. Any references?


    Charlie Chang L


    • Edited by Charlie C Friday, August 03, 2012 2:35 PM
    Friday, August 03, 2012 2:34 PM

Answers

  • You are absolutely right. I tried the code and st returned 0.

    Below is the nest task solution. No syntax error. But I believe it is a bug of VS 2012, when I run mediaControl->SetSource(stream, file->ContentType) the program crash. By running old dual .then code I have gotten SetSource working sometimes.

    auto openPicker = ref new Windows::Storage::Pickers::FileOpenPicker(); openPicker->SuggesterStartLocation = Windows::Storage::Pickers::PickerLocationId::VideosLibrary; openPicker->FileTypeFilter->Add( ".wmv"); openPicker->FileTypeFilter->Add( ".mp4"); create_task( openPicker->PickSingleFileAsync()).then([=](StorageFile^ file) {
    if (file != nullptr) { create_task(file->OpenAsync(Windows::Storage::FileAccessMode::Read)).then([=](IRandomAccessStream^ stream) { mediaControl->SetSource( stream, st ); mediaControl->Play();
    }
    }
    });


    Charlie Chang L

    • Proposed as answer by Jesse Jiang Monday, August 06, 2012 8:40 AM
    • Marked as answer by Jesse Jiang Thursday, August 09, 2012 5:51 AM
    Sunday, August 05, 2012 4:57 PM

All replies

  • auto openPicker = ref new Windows::Storage::Pickers::FileOpenPicker();
    openPicker->SuggesterStartLocation = Windows::Storage::Pickers::PickerLocationId::VideosLibrary;
    openPicker->FileTypeFilter->Add( ".wmv");
    openPicker->FileTypeFilter->Add( ".mp4");
    create_task( openPicker->PickSingleFileAsync()).then([this](StorageFile^ file) -> IAsyncOperation<IRandomAccessStream^>^
    {
       return file->OpenAsync( Windows::Storage::FileAccessMode::Read);
    }).then([this,file]( IRandomAccessStream^ stream)
    {
       mediaControl->SetSource( stream, file->ContentType);
       mediaControl->Play();
    });
    Friday, August 03, 2012 4:36 PM
  • Tried this cute, weird code, there are two errors:

    1. at the first then([this] ...

    it said a local lambda is not allowed in a member function of a Win RT class.

    2. at the second then([this, file]<...>

    it said identify "file" is undefined.

    BTW Is this C++ anymore? Anyway it is a kind of cute code.


    Charlie Chang L


    • Edited by Charlie C Friday, August 03, 2012 5:20 PM
    Friday, August 03, 2012 5:19 PM
  • ad 1. remove "this" from brackets when it's not in class
    ad 2. change it to:

    create_task( openPicker->PickSingleFileAsync()).then([=](StorageFile^ file) -> IAsyncOperation<IRandomAccessStream^>^
    {
       return file->OpenAsync( Windows::Storage::FileAccessMode::Read);
    }).then([=]( IRandomAccessStream^ stream)
    {
       mediaControl->SetSource( stream, file->ContentType);
       mediaControl->Play();
    });

    Friday, August 03, 2012 5:32 PM
  • * mediaControl->SetSource( stream,file->ContentType);

    file in here still undefined.


    Charlie Chang L

    Friday, August 03, 2012 6:20 PM
  • I added a new variable st and set mutable in careat_task, the compile can be passed. But it carshed when executed SetSource().

    Below is the new code:

    auto openPicker = ref new Windows::Storage::Pickers::FileOpenPicker(); openPicker->SuggesterStartLocation = Windows::Storage::Pickers::PickerLocationId::VideosLibrary; openPicker->FileTypeFilter->Add( ".wmv"); openPicker->FileTypeFilter->Add( ".mp4");

    String^ st; create_task( openPicker->PickSingleFileAsync()).then([=](StorageFile^ file) mutable -> IAsyncOperation<IRandomAccessStream^>^ {
    st = file->ContentType return file->OpenAsync( Windows::Storage::FileAccessMode::Read); }).then([=]( IRandomAccessStream^ stream) { mediaControl->SetSource( stream, st ); mediaControl->Play(); });


    Charlie Chang L

    Friday, August 03, 2012 7:50 PM
  • Your lambdas passed in .then are capturing everything by value "[=]".  When the first lambda does st = file->ContentType, it is changing the copy of the st variable which is contained within the lambda class (hence why you had to make the lambda mutable).  The second lambda when it does "->SetSource( stream, st )" is seeing the copy of st which it made when .then was originally called (an empty string).  It is not seeing the changes which were made by the first continuation.  I imagine that this wasn't the intent.

    If you need to pass data like this between continuations where it's not part of the return value of the task -- you should do this via one of a few alternatives:

    • Make a heap allocation (e.g.: through a std::shared_ptr), capture that allocation, and use that memory.  See the data reader/writer sdk sample: http://code.msdn.microsoft.com/windowsapps/Reading-and-writing-data-75ea10a3/view/SourceCode#content and the C++ ReadBytes.xaml.cpp's HexDump function for a sample of this technique.
    • Nest the tasks and the inner task can just do the capture (e.g.: return create_task( file->OpenAsync(...) ).then([=](IRandomAccessStream^ stream) {...}); from the inside of the PickSingleFileAsync continuation.
    • Keep the data somewhere else it is directly accessible by both continuations.
    Saturday, August 04, 2012 5:44 PM
  • You are absolutely right. I tried the code and st returned 0.

    Below is the nest task solution. No syntax error. But I believe it is a bug of VS 2012, when I run mediaControl->SetSource(stream, file->ContentType) the program crash. By running old dual .then code I have gotten SetSource working sometimes.

    auto openPicker = ref new Windows::Storage::Pickers::FileOpenPicker(); openPicker->SuggesterStartLocation = Windows::Storage::Pickers::PickerLocationId::VideosLibrary; openPicker->FileTypeFilter->Add( ".wmv"); openPicker->FileTypeFilter->Add( ".mp4"); create_task( openPicker->PickSingleFileAsync()).then([=](StorageFile^ file) {
    if (file != nullptr) { create_task(file->OpenAsync(Windows::Storage::FileAccessMode::Read)).then([=](IRandomAccessStream^ stream) { mediaControl->SetSource( stream, st ); mediaControl->Play();
    }
    }
    });


    Charlie Chang L

    • Proposed as answer by Jesse Jiang Monday, August 06, 2012 8:40 AM
    • Marked as answer by Jesse Jiang Thursday, August 09, 2012 5:51 AM
    Sunday, August 05, 2012 4:57 PM
  • This one is Perfect. It runs properly in my App. Thanx!
    Friday, August 29, 2014 9:47 PM