private string CreateMediaAdaptiveCardJson() { var card = new AdaptiveCard { Version = "1.1", FallbackText = "This card requires Media to be viewed. Ask your platform to update to Adaptive Cards v1.1 for this an more!" }; // Create caption text. var caption = new AdaptiveTextBlock { Size = TextSize.ExtraLarge, Weight = TextWeight.Bolder, Text = "Publish Adaptive Card schema" }; // Create video media. var media = new AdaptiveMedia { Poster = PosterUrl }; media.Sources.Add(new AdaptiveMediaSource { MimeType = "video/mp4", Url = MediaUrl }); // Add all above to our card. card.Body.Add(caption); card.Body.Add(media); return(card.ToJson().ToString()); }
public void Media() { AdaptiveMediaSource mediaSource1 = new AdaptiveMediaSource { MimeType = "audio/mp4", Url = "https://www.stuff.com/media.mp4" }; Assert.AreEqual("audio/mp4", mediaSource1.MimeType); Assert.AreEqual("https://www.stuff.com/media.mp4", mediaSource1.Url); AdaptiveMediaSource mediaSource2 = new AdaptiveMediaSource { MimeType = "audio/mpeg", Url = "https://www.stuff.com/media.mp3" }; Assert.AreEqual("audio/mpeg", mediaSource2.MimeType); Assert.AreEqual("https://www.stuff.com/media.mp3", mediaSource2.Url); AdaptiveMedia media = new AdaptiveMedia { AltText = "This is some audio", Height = HeightType.Stretch, Id = "MediaId", IsVisible = false, Poster = "https://www.stuff.com/poster.jpg", Separator = true, Spacing = Spacing.Large }; ValidateBaseElementProperties(media, "MediaId", false, true, Spacing.Large, HeightType.Stretch); Assert.AreEqual("This is some audio", media.AltText); Assert.AreEqual("https://www.stuff.com/poster.jpg", media.Poster); media.Sources.Add(mediaSource1); media.Sources.Add(mediaSource2); Assert.AreEqual("https://www.stuff.com/media.mp4", media.Sources[0].Url); Assert.AreEqual("https://www.stuff.com/media.mp3", media.Sources[1].Url); var jsonString = media.ToJson().ToString(); Assert.AreEqual("{\"altText\":\"This is some audio\",\"height\":\"Stretch\",\"id\":\"MediaId\",\"isVisible\":false,\"poster\":\"https://www.stuff.com/poster.jpg\",\"separator\":true,\"sources\":[{\"mimeType\":\"audio/mp4\",\"url\":\"https://www.stuff.com/media.mp4\"},{\"mimeType\":\"audio/mpeg\",\"url\":\"https://www.stuff.com/media.mp3\"}],\"spacing\":\"large\",\"type\":\"Media\"}", jsonString); }
/** Get poster image from either card payload or host config */ private static Image GetPosterImage(AdaptiveMedia media, AdaptiveRenderContext context) { Image uiPosterImage = null; if (!string.IsNullOrEmpty(media.Poster) && context.Config.ResolveFinalAbsoluteUri(media.Poster) != null) { // Use the provided poster uiPosterImage = new Image(); uiPosterImage.SetImageSource(media.Poster, context); } else if (!string.IsNullOrEmpty(context.Config.Media.DefaultPoster) && context.Config.ResolveFinalAbsoluteUri(context.Config.Media.DefaultPoster) != null) { // Use the default poster from host uiPosterImage = new Image(); uiPosterImage.SetImageSource(context.Config.Media.DefaultPoster, context); } return(uiPosterImage); }
public async Task Media() { AdaptiveCard card = new AdaptiveCard { Version = "1.3" }; AdaptiveMediaSource mediaSource = new AdaptiveMediaSource { MimeType = "audio/mp4", Url = "https://www.stuff.com/media.mp4" }; AdaptiveMedia media = new AdaptiveMedia(); media.Sources.Add(mediaSource); card.Body.Add(media); await RenderInDispatcher(card); }
public virtual void Visit(AdaptiveMedia media) { }
/** Get the first media URI with a supported mime type */ private static AdaptiveMediaSource GetMediaSource(AdaptiveMedia media, AdaptiveRenderContext context) { // Check if sources contain an invalid mix of MIME types (audio and video) bool?isLastMediaSourceAudio = null; foreach (var source in media.Sources) { if (!isLastMediaSourceAudio.HasValue) { isLastMediaSourceAudio = IsAudio(source); } else { if (IsAudio(source) != isLastMediaSourceAudio.Value) { // If there is one pair of sources with different MIME types, // it's an invalid mix and a warning should be logged context.Warnings.Add(new AdaptiveWarning(-1, "A Media element contains an invalid mix of MIME type")); return(null); } isLastMediaSourceAudio = IsAudio(source); } } // Return the first supported source with not-null URI bool isAllHttps = true; AdaptiveMediaSource httpsSource = null; foreach (var source in media.Sources) { if (_supportedMimeTypes.Contains(source.MimeType)) { Uri finalMediaUri = context.Config.ResolveFinalAbsoluteUri(source.Url); if (finalMediaUri != null) { // Since https is not supported by WPF, // try to use non-https sources first if (finalMediaUri.Scheme != "https") { isAllHttps = false; return(source); } else if (httpsSource == null) { httpsSource = source; } } } } // If all sources are https, log a warning and return the first one if (isAllHttps) { context.Warnings.Add(new AdaptiveWarning(-1, "All sources have unsupported https scheme. The host would be responsible for playing the media.")); return(httpsSource); } // No valid source is found context.Warnings.Add(new AdaptiveWarning(-1, "A Media element does not have any valid source")); return(null); }
public static FrameworkElement Render(AdaptiveMedia media, AdaptiveRenderContext context) { // If host doesn't support interactivity or no media source is provided // just return the poster image if present if (!context.Config.SupportsInteractivity || media.Sources.Count == 0) { return(GetPosterImage(media, context)); } AdaptiveMediaSource mediaSource = GetMediaSource(media, context); if (mediaSource == null) { return(null); } // Main element to return var uiMedia = new Grid(); #region Thumbnail button var mediaConfig = context.Config.Media; var uiThumbnailButton = new Grid { Name = "thumbnailButton", Visibility = Visibility.Visible }; /* Poster Image */ // A poster container is necessary to handle background color and opacity mask // in case poster image is not found or does not exist var uiPosterContainer = new Grid() { Background = _controlBackgroundColor, }; Image uiPosterImage = GetPosterImage(media, context); if (uiPosterImage != null) { uiPosterContainer.Children.Add(uiPosterImage); } uiThumbnailButton.Children.Add(uiPosterContainer); // Play button var uiPlayButton = RenderThumbnailPlayButton(context); uiThumbnailButton.Children.Add(uiPlayButton); // Mouse hover handlers to signify playable media element uiThumbnailButton.MouseEnter += (sender, e) => { uiPosterContainer.OpacityMask = _controlBackgroundColor; }; uiThumbnailButton.MouseLeave += (sender, e) => { uiPosterContainer.OpacityMask = null; }; #endregion uiMedia.Children.Add(uiThumbnailButton); // Inline playback is possible only when inline playback is allowed by the host and the chosen media source is not https bool isInlinePlaybackPossible = mediaConfig.AllowInlinePlayback && context.Config.ResolveFinalAbsoluteUri(mediaSource.Url).Scheme != "https"; FrameworkElement uiMediaPlayer = null; if (isInlinePlaybackPossible) { // Media player is only created if inline playback is allowed uiMediaPlayer = RenderMediaPlayer(context, mediaSource, uiMedia); uiMediaPlayer.Visibility = Visibility.Collapsed; uiMedia.Children.Add(uiMediaPlayer); } // Play the media uiThumbnailButton.MouseUp += (sender, e) => { if (isInlinePlaybackPossible) { if (IsAudio(mediaSource) && uiPosterImage != null) { // If media is audio, keep only the poster image (if present) // and disable the thumbnail button to prevent further clicks uiPlayButton.Visibility = Visibility.Collapsed; uiThumbnailButton.IsEnabled = false; } else { // Otherwise, collapse all the thumbnail button uiThumbnailButton.Visibility = Visibility.Collapsed; } // Show the media player to start uiMediaPlayer.Visibility = Visibility.Visible; } // Raise an event to send the media to host else { context.ClickMedia(uiPosterContainer, new AdaptiveMediaEventArgs(media)); // Prevent nested events from triggering e.Handled = true; } }; return(uiMedia); }
public AdaptiveMediaEventArgs(AdaptiveMedia media) { Media = media; }
private AdaptiveCard SetCard() { AdaptiveCard _card = new AdaptiveCard("1.1"); var _container = new AdaptiveContainer(); var colum = new AdaptiveColumnSet(); var _columnImage = new AdaptiveColumn() { Width = AdaptiveColumnWidth.Auto }; _columnImage.Items.Add(new AdaptiveImage() { Url = new Uri(this.UrlImage), Size = AdaptiveImageSize.Small, Style = AdaptiveImageStyle.Person, AltText = "Bootty" }); var _columnContent = new AdaptiveColumn() { Width = AdaptiveColumnWidth.Stretch }; _columnContent.Items.Add(new AdaptiveTextBlock() { Text = "Booty", Size = AdaptiveTextSize.Medium, Weight = AdaptiveTextWeight.Default, Color = AdaptiveTextColor.Default, Wrap = true, Spacing = AdaptiveSpacing.Default }); _columnContent.Items.Add(new AdaptiveTextBlock() { Text = DateTime.Now.ToString(), Size = AdaptiveTextSize.Small, Color = AdaptiveTextColor.Default, Wrap = true, IsSubtle = true, Spacing = AdaptiveSpacing.None }); var _textMessage = new AdaptiveTextBlock() { Text = this.Title, Size = AdaptiveTextSize.Medium, Color = AdaptiveTextColor.Default, Weight = AdaptiveTextWeight.Bolder, Wrap = true, IsSubtle = false }; var _textMessage2 = new AdaptiveTextBlock() { Text = this.Description, Size = AdaptiveTextSize.Small, Color = AdaptiveTextColor.Default, Weight = AdaptiveTextWeight.Default, Wrap = true, IsSubtle = false }; colum.Columns.Add(_columnImage); colum.Columns.Add(_columnContent); _container.Items.Add(colum); _card.Body.Add(_container); _card.Body.Add(_textMessage); _card.Body.Add(_textMessage2); var video = this.Actions.Where(p => p.TypeCard == TypeCards.VIDEO).SingleOrDefault(); if (video != null) { var _video = new AdaptiveMedia(); _video.Sources.Add(new AdaptiveMediaSource() { MimeType = "video/mp4", Url = video.Result }); _card.Body.Add(_video); } _card.Actions.AddRange(this.GetAdaptiveActions()); return(_card); }