0

I have this converter :

    public class MediaSourceConverter : DependencyObject, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || value.ToString().Trim() == "" || value.ToString() == "0")
        {
            // This case is running well
            return null;
        }
        else
        {
            string link = value.ToString();
            if (link.StartsWith("plugin://plugin.video.youtube/?action=play_video&videoid="))
            {
                // This case throw Null Exception in main windows code
                return ("https://www.youtube.com/watch?v=" + link.Substring(link.LastIndexOf('=') + 1));
            }
            else if (link.StartsWith("http://") || link.StartsWith("https://"))
            {
                // This case is running well
                return link;
            }
            else
            {
                // This case throw Null Exception in main windows code
                return ("https://www.youtube.com/watch?v=" + link);
            }
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML is

<MediaElement x:Name="media_Player" 
              Source="{Binding SelectedItem.Key, ElementName=lv_Medias, Converter={StaticResource MediaSourceConverter}}"
              Width="322" Height="181" />

When the converter return a link with youtube, a Null exception is thrown from the main window code. The link is always valid and is retrieved from a web api.

If I remove the converter in the MediaElement binding, the media is playing well when link starting with http*, and, of course, not playing in the other cases but no error is thrown.

Any ideas ?

Thanks

CFou
  • 978
  • 3
  • 13
  • `// This case throw Null Exception in main windows code return ("https://www.youtube.com/watch?v=" + link);` I'd be surprised if that line throw a NRE. What is the _exact_ value of `link` when it occurs? – mjwills Jan 28 '21 at 11:26
  • I am surprised too :(, the link value is a youtube id, this one for instance : "iQJNBVW8QhI" – CFou Jan 28 '21 at 11:28
  • Please don't say the link is valid. Tell us _the exact value_. – mjwills Jan 28 '21 at 11:29
  • Could you share stack trace for the exception? – user2250152 Jan 28 '21 at 11:53
  • I think the problem is that the MediaElement is expecting a link to a media file (MP4 file for example) and you're giving it a Youtube page. Whilst the Youtube page does have a video playing on it, it is not a video file in itself. – Jason Hunt Jan 28 '21 at 12:18
  • @Jason Hunt, that's the point! Thanks, if you change your comment as an answer, I could mark it. @Clemens, Uri are expected, but this wok with strings too as I can test with mp4 file, I think this is because it is a converter. But, this will be not work if defined in main code, like : `mediaElement.Source = mystr;`. You where perfectly right for the `else` statment. Finally, I managed this with a WebBrowser, which allow me to play Youtube embedded video. – CFou Jan 28 '21 at 14:01
  • More information to find the problem. Both in xaml code and in cs code – Meysam Asadi Jan 28 '21 at 14:24
  • @CFou Glad my comment helped and you've managed to find an alternative solution. – Jason Hunt Jan 28 '21 at 19:17
  • @CFou: See the following post: [Embedding Youtube videos in WPF application](https://stackoverflow.com/q/57413970/6630084). – Jackdaw Jan 29 '21 at 00:14

2 Answers2

1

The problem is that the MediaElement is expecting a link to a media file (MP4 file for example) and you're giving it a Youtube page. Whilst the Youtube page does have a video playing on it, it is not a video file in itself

Jason Hunt
  • 354
  • 2
  • 5
1

I answer my own question for those who may be interested in how I handle this (I only need basic video control) I have no other files than mp4 link and no other source than youtube

string link = "";     // direct mp4 (or others) video link
string source = "";   // youtube link
if (dataSource.Key.StartsWith("plugin://plugin.video.youtube/?action=play_video&videoid="))
{
    source = "https://www.youtube-nocookie.com/embed/" + dataSource.Key.Substring(dataSource.Key.LastIndexOf('=') + 1) + "?rel=0&amp;showinfo=0";
}
else if (dataSource.Key.StartsWith("http://") || dataSource.Key.StartsWith("https://"))
{
    link = dataSource.Key;
}
else
{
    source = "https://www.youtube-nocookie.com/embed/" + dataSource.Key + "?rel=0&amp;showinfo=0";
}
if (link == "")
{
    wb_VideoPlayer.Source = new Uri(source);
}
else
{
    wb_VideoPlayer.NavigateToString(@"<!DOCTYPE html>
        <html>
        <head>
            <meta http-equiv='Content-Type' content='text/html; charset=unicode' />
            <meta http-equiv='X-UA-Compatible' content='IE=10' /> 
            <title></title>
            <style>
                html {
                    -ms-overflow-style: none; /* For Internet Explorer and Edge */
                }
                body {
                    padding: 0;
                    margin: 0;
                }
             </style>
        </head>
        <body>
            <div>
                 <video id='player' controls='' preload='metadata' width='421' height='237'>
                    <source src='" + link + @"' type='video/mp4' />
                </video>
            </div>
            <script type='text/javascript'>
                var v = document.getElementById('player');
                var firstDisplayed = true;

                // Sets the default time to 1 second to have a picture displayed
                v.addEventListener('canplay', function() {
                    this.currentTime = 1;
                });
                v.addEventListener('play', function() {
                    if (firstDisplayed)
                    {
                        firstDisplayed = false;
                        v.currentTime = 0;
                    }
                    v.play();
                });
                v.addEventListener('ended', function() {
                    firstDisplayed = true;
                    v.pause();
                    v.currentTime = 1;
                });
            </script>
        </body>
        </html>");
}

in XAML :

<Border HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,28,0,0"
        Width="423" Height="239" Background="Black">
     <WebBrowser x:Name="wb_VideoPlayer" 
                 ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
                 ScrollViewer.VerticalScrollBarVisibility="Hidden" />
</Border>
CFou
  • 978
  • 3
  • 13