/// <summary>
        ///     Attempts to play a model of type BaseTrack. This method handles playback and loading
        ///     feedback to the user. If an error occured, the user will see a message dialog.
        /// </summary>
        /// <typeparam name="TSource">A base track source.</typeparam>
        /// <param name="model">SoundByte collection of a base track source.</param>
        /// <param name="startingTrack">The track to start first (can be null)</param>
        /// <param name="shuffle">Should the playlist be shuffled.</param>
        public static async Task PlayAllTracksAsync <TSource>(SoundByteCollection <TSource> model, BaseTrack startingTrack = null, bool shuffle = false) where TSource : ISource
        {
            if (model.Count == 0)
            {
                return;
            }

            // Attempt to create the playlist
            var result = await SimpleIoc.Default.GetInstance <IPlaybackService>().InitializePlaylistAsync(model.Source, model, model.Token);

            if (result.Success == false)
            {
                await NavigationService.Current.CallMessageDialogAsync(result.Message, "Could not build playlist.");

                return;
            }

            // Start playback
            if (shuffle)
            {
                await SimpleIoc.Default.GetInstance <IPlaybackService>().StartRandomTrackAsync();
            }
            else
            {
                await SimpleIoc.Default.GetInstance <IPlaybackService>().StartTrackAsync(startingTrack);
            }
        }
Beispiel #2
0
        public ContentGroup(ISource source, string title, bool isAuthenticatedFeed, List <ContentButton> buttons, Action <ContentGroup>?onClickAction = null, Action <Media.Media>?onItemClickCommand = null)
        {
            Collection          = new SoundByteCollection <ISource>(source);
            Title               = title;
            IsAuthenticatedFeed = isAuthenticatedFeed;
            Buttons             = buttons;

            if (onClickAction != null)
            {
                // Bind to the custom click event
                OnViewAllClickCommand = new MvxCommand(() => onClickAction?.Invoke(this));
            }
            else
            {
                // Nothing was passed through, use the default navigation
                OnViewAllClickCommand = new MvxAsyncCommand(async() =>
                {
                    var navigationService = Mvx.IoCProvider.Resolve <IMvxNavigationService>();
                    await navigationService.Navigate <GenericListViewModel, GenericListViewModel.Holder>(new GenericListViewModel.Holder(Collection, Title));
                });
            }

            OnItemClickCommand = onItemClickCommand == null
                ? new MvxCommand <Media.Media>(async item => await ItemInvokeHelper.InvokeItem(Collection, item))
                : new MvxCommand <Media.Media>(onItemClickCommand);
        }
Beispiel #3
0
        public static async Task InvokeItem <T>(SoundByteCollection <T> collection, Media item) where T : ISource
        {
            var provider = Mvx.IoCProvider.Resolve <IMusicProviderService>().MusicProviders.FirstOrDefault(x => x.Identifier == item.MusicProviderId);

            if (provider == null)
            {
                await Mvx.IoCProvider.Resolve <IDialogService>().ShowErrorMessageAsync("Cannot open item", $"You need the music provider ({item.MusicProviderId}) in order to interact with this item");

                return;
            }

            // Loop through all the item types
            switch (item.MediaType)
            {
            case MediaType.Unknown:
                break;

            case MediaType.Track:
            case MediaType.PodcastEpisode:
                // Build the queue
                var result = await Mvx.IoCProvider.Resolve <IPlaybackService>().InitializeAsync(collection.Source, collection, collection.Token);

                if (!result.Success)
                {
                    await Mvx.IoCProvider.Resolve <IDialogService>().ShowErrorMessageAsync("Could not build playback queue", result.Message);

                    return;
                }

                // Play the song
                await Mvx.IoCProvider.Resolve <IPlaybackService>().StartMediaAsync(item);

                break;

            // Navigate to the user detail view
            case MediaType.User:
                await Mvx.IoCProvider.Resolve <IMvxNavigationService>().Navigate <UserDetailViewModel, User>((User)item);

                break;

            // Navigate to the playlist detail view
            case MediaType.Playlist:
                await Mvx.IoCProvider.Resolve <IMvxNavigationService>().Navigate <PlaylistDetailViewModel, Playlist>((Playlist)item);

                break;

            // Navigate to the podcast detail view
            case MediaType.PodcastShow:
                await Mvx.IoCProvider.Resolve <IMvxNavigationService>().Navigate <PodcastDetailViewModel, PodcastShow>((PodcastShow)item);

                break;
            }
        }
Beispiel #4
0
        public ContentGroup(ISource source, string title, List<ContentButton> buttons, Action<ContentGroup> onClickAction, Action<BaseSoundByteItem> onItemClickCommand = null)
        {
            Collection = new SoundByteCollection<ISource>(source);
            Title = title;
            Buttons = buttons;

            if (onClickAction != null)
                OnViewAllClickCommand = new DelegateCommand<ContentGroup>(onClickAction);

            if (onItemClickCommand != null)
                OnItemClickCommand = new DelegateCommand<BaseSoundByteItem>(onItemClickCommand);
        }
Beispiel #5
0
        public static async Task ShuffleTracksAsync <TSource>(SoundByteCollection <TSource, BaseTrack> model) where TSource : ISource <BaseTrack>
        {
            model.IsLoading = true;

            var startPlayback = await PlaybackService.Instance.StartModelMediaPlaybackAsync(model, true);

            if (!startPlayback.Success)
            {
                await new MessageDialog(startPlayback.Message, "Error playing shuffled tracks.").ShowAsync();
            }

            model.IsLoading = false;
        }
Beispiel #6
0
        private async void OnSearchTrackClickCommand(BaseSoundByteItem item)
        {
            // Create the related track collection
            var relatedTrackCollection = new SoundByteCollection <RelatedTrackSource>();

            relatedTrackCollection.Source.Service = item.Track.ServiceType;
            relatedTrackCollection.Source.TrackId = item.Track.TrackId;

            // Add this track as an initial track
            relatedTrackCollection.Add(item);

            // Play the tracks
            await BaseViewModel.PlayAllTracksAsync(relatedTrackCollection, item.Track);
        }
 /// <summary>
 ///     Helper method for PlayAllTracksAsync to play shuffled tracks. See
 ///     PlayAllTracksAsync for more information
 /// </summary>
 /// <typeparam name="TSource">A base track source.</typeparam>
 /// <param name="model">SoundByte collection of a base track source.</param>
 public static async Task ShufflePlayAllTracksAsync <TSource>(SoundByteCollection <TSource> model) where TSource : ISource
 {
     await PlayAllTracksAsync(model, null, true);
 }
Beispiel #8
0
        public async Task HandleProtocolAsync(string path)
        {
            LoggingService.Log(LoggingService.LogType.Debug, "Performing protocol work using path of " + path);


            if (!string.IsNullOrEmpty(path))
            {
                try
                {
                    if (path == "playUserLikes" || path == "shufflePlayUserLikes")
                    {
                        if (SoundByteV3Service.Current.IsServiceConnected(ServiceType.SoundCloud))
                        {
                            // Navigate to the now playing screen
                            RootFrame.Navigate(typeof(NowPlayingView));

                            // Get and load the user liked items
                            var userLikes = new SoundByteCollection <LikeSoundCloudSource, BaseTrack>();
                            userLikes.Source.User = SoundByteV3Service.Current.GetConnectedUser(ServiceType.SoundCloud);

                            // Loop through loading all the likes
                            while (userLikes.HasMoreItems)
                            {
                                await userLikes.LoadMoreItemsAsync(50);
                            }

                            // Play the list of items
                            await PlaybackService.Instance.StartModelMediaPlaybackAsync(userLikes, path == "shufflePlayUserLikes");

                            return;
                        }
                    }

                    if (path == "playUserStream")
                    {
                        if (SoundByteV3Service.Current.IsServiceConnected(ServiceType.SoundCloud))
                        {
                            // Navigate to the now playing screen
                            RootFrame.Navigate(typeof(NowPlayingView));

                            // Get and load the user liked items
                            var userStream = new SoundByteCollection <StreamSoundCloudSource, GroupedItem>();

                            // Counter so we don't get an insane amount of items
                            var i = 0;

                            // Grab all the users stream / 5 items
                            while (userStream.HasMoreItems && i <= 5)
                            {
                                i++;
                                await userStream.LoadMoreItemsAsync(50);
                            }

                            // Play the list of items
                            await PlaybackService.Instance.StartPlaylistMediaPlaybackAsync(
                                userStream.Where(x => x.Track != null).Select(x => x.Track).ToList());

                            return;
                        }
                    }

                    var parser = DeepLinkParser.Create(path);

                    var section = parser.Root.Split('/')[0].ToLower();
                    var page    = parser.Root.Split('/')[1].ToLower();

                    await App.SetLoadingAsync(true);

                    if (section == "core")
                    {
                        switch (page)
                        {
                        case "track":

                            BaseTrack track = null;

                            switch (parser["service"])
                            {
                            case "soundcloud":
                                track = (await SoundByteV3Service.Current.GetAsync <SoundCloudTrack>(ServiceType.SoundCloud, $"/tracks/{parser["id"]}")).ToBaseTrack();
                                break;

                            case "youtube":
                                break;

                            case "fanburst":
                                track = (await SoundByteV3Service.Current.GetAsync <FanburstTrack>(ServiceType.Fanburst, $"/videos/{parser["id"]}")).ToBaseTrack();
                                break;
                            }

                            if (track != null)
                            {
                                var startPlayback =
                                    await PlaybackService.Instance.StartPlaylistMediaPlaybackAsync(new List <BaseTrack> {
                                    track
                                });

                                if (!startPlayback.Success)
                                {
                                    await new MessageDialog(startPlayback.Message, "Error playing track.").ShowAsync();
                                }
                            }
                            break;

                        case "playlist":
                            var playlist =
                                await SoundByteV3Service.Current.GetAsync <SoundCloudPlaylist>(ServiceType.SoundCloud, $"/playlists/{parser["id"]}");

                            App.NavigateTo(typeof(PlaylistView), playlist.ToBasePlaylist());
                            return;

                        case "user":
                            var user = await SoundByteV3Service.Current.GetAsync <SoundCloudUser>(ServiceType.SoundCloud, $"/users/{parser["id"]}");

                            App.NavigateTo(typeof(UserView), user.ToBaseUser());
                            return;

                        case "changelog":
                            App.NavigateTo(typeof(WhatsNewView));
                            return;
                        }
                    }
                }
                catch (Exception)
                {
                    await new MessageDialog("The specified protocol is not correct. App will now launch as normal.")
                    .ShowAsync();
                }
                await App.SetLoadingAsync(false);
            }

            RootFrame.Navigate(SoundByteV3Service.Current.IsServiceConnected(ServiceType.SoundCloud)
                ? typeof(SoundCloudStreamView)
                : typeof(ExploreView));
        }
Beispiel #9
0
        public async Task HandleProtocolAsync(string path)
        {
            LoggingService.Log(LoggingService.LogType.Debug, "Performing protocol work using path of " + path);

            if (!string.IsNullOrEmpty(path))
            {
                try
                {
                    if (path == "playUserLikes" || path == "shufflePlayUserLikes")
                    {
                        if (SoundByteService.Current.IsServiceConnected(ServiceType.SoundCloud))
                        {
                            // Navigate to the now playing screen
                            RootFrame.Navigate(typeof(NowPlayingView));

                            // Get and load the user liked items
                            var userLikes = new SoundByteCollection <SoundCloudLikeSource, BaseTrack>();
                            userLikes.Source.User = SoundByteService.Current.GetConnectedUser(ServiceType.SoundCloud);

                            // Loop through loading all the likes
                            while (userLikes.HasMoreItems)
                            {
                                await userLikes.LoadMoreItemsAsync(50);
                            }

                            // Play the list of items
                            await BaseViewModel.PlayAllTracksAsync(userLikes, null, path == "shufflePlayUserLikes");

                            return;
                        }
                    }

                    if (path == "playUserStream")
                    {
                        if (SoundByteService.Current.IsServiceConnected(ServiceType.SoundCloud))
                        {
                            // Navigate to the now playing screen
                            RootFrame.Navigate(typeof(NowPlayingView));

                            // Get and load the user liked items
                            var userStream = new SoundByteCollection <SoundCloudStreamSource, GroupedItem>();

                            // Counter so we don't get an insane amount of items
                            var i = 0;

                            // Grab all the users stream / 5 items
                            while (userStream.HasMoreItems && i <= 5)
                            {
                                i++;
                                await userStream.LoadMoreItemsAsync(50);
                            }

                            // Play the list of items
                            var result = await PlaybackService.Instance.InitilizePlaylistAsync <DummyTrackSource>(
                                userStream.Where(x => x.Track != null).Select(x => x.Track).ToList());

                            if (result.Success)
                            {
                                await PlaybackService.Instance.StartTrackAsync();
                            }

                            return;
                        }
                    }

                    var parser = DeepLinkParser.Create(path);

                    var section = parser.Root?.Split('/')[0]?.ToLower();

                    await App.SetLoadingAsync(true);

                    if (section == "core")
                    {
                        var page = parser.Root?.Split('/')[1]?.ToLower();

                        switch (page)
                        {
                        case "track":

                            BaseTrack track = null;

                            switch (parser["service"])
                            {
                            case "soundcloud":
                                track = (await SoundByteService.Current.GetAsync <SoundCloudTrack>(ServiceType.SoundCloud, $"/tracks/{parser["id"]}")).Response.ToBaseTrack();
                                break;

                            case "youtube":
                                break;

                            case "fanburst":
                                track = (await SoundByteService.Current.GetAsync <FanburstTrack>(ServiceType.Fanburst, $"/videos/{parser["id"]}")).Response.ToBaseTrack();
                                break;
                            }

                            if (track != null)
                            {
                                var startPlayback =
                                    await PlaybackService.Instance.InitilizePlaylistAsync <DummyTrackSource>(new List <BaseTrack> {
                                    track
                                });

                                if (startPlayback.Success)
                                {
                                    await PlaybackService.Instance.StartTrackAsync();
                                }
                                else
                                {
                                    await NavigationService.Current.CallMessageDialogAsync(startPlayback.Message,
                                                                                           "Error playing track.");
                                }
                            }
                            break;

                        case "playlist":
                            var playlist =
                                await SoundByteService.Current.GetAsync <SoundCloudPlaylist>(ServiceType.SoundCloud, $"/playlists/{parser["id"]}");

                            App.NavigateTo(typeof(PlaylistView), playlist.Response.ToBasePlaylist());
                            return;

                        case "user":
                            var user = await SoundByteService.Current.GetAsync <SoundCloudUser>(ServiceType.SoundCloud, $"/users/{parser["id"]}");

                            App.NavigateTo(typeof(UserView), user.Response.ToBaseUser());
                            return;

                        case "changelog":
                            await NavigationService.Current.CallDialogAsync <WhatsNewDialog>();

                            break;
                        }
                    }
                    else if (section == "rs" || section == "remote-subsystem")
                    {
                        try
                        {
                            await App.SetLoadingAsync(true);

                            parser.TryGetValue("d", out var data);
                            parser.TryGetValue("t", out var timespan);

                            var result = App.RoamingService.DecodeActivityParameters(data);

                            // Get the current track object
                            BaseTrack currentTrack = null;
                            var       tracks       = new List <BaseTrack>();

                            switch (result.CurrentTrack.Service)
                            {
                            case ServiceType.Fanburst:
                                break;

                            case ServiceType.SoundCloud:
                            case ServiceType.SoundCloudV2:
                                currentTrack = (await SoundByteService.Current.GetAsync <SoundCloudTrack>(ServiceType.SoundCloud, $"/tracks/{result.CurrentTrack.TrackId}")).Response.ToBaseTrack();
                                break;

                            case ServiceType.YouTube:
                                currentTrack = (await SoundByteService.Current.GetAsync <YouTubeVideoHolder>(ServiceType.YouTube, "videos", new Dictionary <string, string>
                                {
                                    { "part", "snippet,contentDetails" },
                                    { "id", result.CurrentTrack.TrackId }
                                })).Response.Tracks.FirstOrDefault()?.ToBaseTrack();
                                break;

                            case ServiceType.ITunesPodcast:
                                // TODO: THIS
                                break;
                            }

                            //TODO: List has to be put back into wanted order.

                            var soundCloudIds = string.Join(',', result.Tracks.Where(x => x.Service == ServiceType.SoundCloud || x.Service == ServiceType.SoundCloudV2).Select(x => x.TrackId));
                            var fanburstIds   = string.Join(',', result.Tracks.Where(x => x.Service == ServiceType.Fanburst).Select(x => x.TrackId));
                            var youTubeIds    = string.Join(',', result.Tracks.Where(x => x.Service == ServiceType.YouTube).Select(x => x.TrackId));

                            // SoundCloud tracks
                            tracks.AddRange((await SoundByteService.Current.GetAsync <List <SoundCloudTrack> >(ServiceType.SoundCloud, $"/tracks?ids={soundCloudIds}")).Response.Select(x => x.ToBaseTrack()));

                            // YouTube Tracks
                            tracks.AddRange((await SoundByteService.Current.GetAsync <YouTubeVideoHolder>(ServiceType.YouTube, "videos", new Dictionary <string, string>
                            {
                                { "part", "snippet,contentDetails" },
                                { "id", youTubeIds }
                            })).Response.Tracks.Select(x => x.ToBaseTrack()));

                            var startPlayback = await PlaybackService.Instance.InitilizePlaylistAsync(result.Source, tracks);

                            if (startPlayback.Success)
                            {
                                TimeSpan?timeSpan = null;

                                if (!string.IsNullOrEmpty(timespan))
                                {
                                    timeSpan = TimeSpan.FromMilliseconds(double.Parse(timespan));
                                }

                                await PlaybackService.Instance.StartTrackAsync(currentTrack, timeSpan);
                            }
                            else
                            {
                                await NavigationService.Current.CallMessageDialogAsync(startPlayback.Message, "The remote protocol subsystem failed.");
                            }

                            await App.SetLoadingAsync(false);
                        }
                        catch (Exception e)
                        {
                            await App.SetLoadingAsync(false);

                            await NavigationService.Current.CallMessageDialogAsync(e.Message, "The remote protocol subsystem failed.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    await NavigationService.Current.CallMessageDialogAsync(
                        "The specified protocol is not correct. App will now launch as normal.\n\n" + ex.Message);
                }
                await App.SetLoadingAsync(false);
            }

            if (DeviceHelper.IsMobile)
            {
                RootFrame.Navigate(typeof(MobileView));
            }
            else
            {
                RootFrame.Navigate(typeof(ExploreView));
            }
        }