internal async void HandleMetadata(SongMetadata songMetadata, StationStream currentStream) { if (songMetadata == null || songMetadata.IsUnknownMetadata) { SetCurrentMetadataToUnknown(); return; } await metadataLock.WaitAsync(); try { CurrentStation = await NepApp.Stations.GetStationByNameAsync(currentStream.ParentStation); StationProgram currentProgram = null; if (IsHostedStationProgramBeginning(songMetadata, CurrentStation, out currentProgram)) { //we're tuning into a hosted radio program. this may be a DJ playing remixes, for example. ActivateStationProgrammingMode(songMetadata, currentStream, currentProgram); //block programs are handled differently. } else { //we're tuned into regular programming/music HandleStationSongMetadata(songMetadata, currentStream, CurrentStation); } } finally { metadataLock.Release(); } }
public override async Task TryConnectAsync(StationStream stream) { var httpRequest = new HttpRequestMessage(HttpMethod.Get, stream.StreamUrl); //some servers don't support head. we need a better way to poke the server var httpResponse = await httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead); if (!httpResponse.IsSuccessStatusCode) { throw new Neptunium.Core.NeptuniumStreamConnectionFailedException(stream); } //collect header information here httpRequest.Dispose(); httpResponse.Dispose(); httpClient.Dispose(); await Task.Delay(500); StreamMediaSource = MediaSource.CreateFromUri(stream.StreamUrl); var station = await NepApp.Stations.GetStationByNameAsync(stream.ParentStation); RaiseMetadataChanged(new Core.Media.Metadata.SongMetadata() { Artist = "Unknown Artist", Track = "Unknown Song", StationPlayedOn = stream.ParentStation, StationLogo = station.StationLogoUrl, IsUnknownMetadata = true }); }
public NeptuniumStreamConnectionFailedException(StationStream stream, Exception inner = null) : base(inner) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } Stream = stream; _message = string.Format("We were unable to stream {0} for some reason. ", Stream.SpecificTitle) + inner?.Message; }
private void ActivateStationProgrammingMode(SongMetadata songMetadata, StationStream currentStream, StationProgram currentProgram) { StationRadioProgramStarted?.Invoke(this, new NepAppStationProgramStartedEventArgs() { RadioProgram = currentProgram, Metadata = songMetadata, Station = currentStream?.ParentStation }); CurrentProgram = currentProgram; SetCurrentMetadataToUnknownInternal(currentProgram.Name); }
public NeptuniumStreamConnectionFailedException(StationStream stream, string message, Exception inner = null) : base(inner) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (string.IsNullOrWhiteSpace(message)) { throw new ArgumentNullException(nameof(message)); } Stream = stream; _message = message; }
private async void HandleStationSongMetadata(SongMetadata songMetadata, StationStream currentStream, StationItem currentStation) { if (CurrentProgram != null) { if (CurrentProgram.Style == StationProgramStyle.Hosted) { CurrentProgram = null; //hosted program ended. } } //filter out station messages if (!string.IsNullOrWhiteSpace(currentStream.ParentStation)) { if (currentStation.StationMessages != null) { if (currentStation.StationMessages.Contains(songMetadata.Track) || currentStation.StationMessages.Contains(songMetadata.Artist)) { NepAppStationMessageReceived?.Invoke(this, new NepAppStationMessageReceivedEventArgs(songMetadata)); metadataLock.Release(); return; } } } if (CurrentSong != null) { if (CurrentSong.ToString().Equals(songMetadata.ToString())) { return; } } CurrentSong = songMetadata; //this is used for the now playing bar via data binding. RaisePropertyChanged(nameof(CurrentSong)); PreSongChanged?.Invoke(this, new NepAppSongChangedEventArgs(songMetadata)); await HandleStationSongMetadataStage2Async(songMetadata); }
private static async Task StreamLastPlayedStationAsync() { var station = await NepApp.Stations.GetStationByNameAsync(NepApp.Stations.LastPlayedStationName); if (station != null) { var controller = await NepApp.UI.Overlay.ShowProgressDialogAsync(string.Format("Connecting to {0}...", station.Name), "Please wait..."); controller.SetIndeterminate(); try { StationStream stream = null; if (stream == null) { //check if we need to automatically choose a lower bitrate. if ((int)NepApp.Network.NetworkUtilizationBehavior < 2) //check if we're on "conservative" or "opt-in" { //grab the stream with the lowest bitrate stream = station.Streams.OrderBy(x => x.Bitrate).First(); } else { stream = station.Streams.OrderByDescending(x => x.Bitrate).First(); //otherwise, grab a higher bitrate } } await NepApp.MediaPlayer.TryStreamStationAsync(stream); } catch (Exception ex) { await NepApp.UI.ShowInfoDialogAsync("Uh-oh! Couldn't do that!", ex.Message); } finally { await controller.CloseAsync(); } } }
public override async Task TryConnectAsync(StationStream stream) { try { streamSource = await ShoutcastStreamFactory.ConnectAsync(stream.StreamUrl, new ShoutcastStreamFactoryConnectionSettings() { UserAgent = "Neptunium (http://github.com/Amrykid/Neptunium)", RelativePath = stream.RelativePath, RequestSongMetdata = stream.RequestMetadata }); streamSource.Reconnected += StreamSource_Reconnected; streamSource.MetadataChanged += ShoutcastStream_MetadataChanged; StreamMediaSource = MediaSource.CreateFromMediaStreamSource(streamSource.MediaStreamSource); StreamMediaSource.StateChanged += StreamMediaSource_StateChanged; this.StationPlaying = await NepApp.Stations.GetStationByNameAsync(stream.ParentStation); ShoutcastStationInfo = streamSource.StationInfo; RaiseStationInfoAcquired(streamSource.StationInfo); } catch (Exception ex) { if (ex is System.Runtime.InteropServices.COMException) { if (ex.HResult == -2147014836) { /* A connection attempt failed because the connected party did not properly respond after a period of time, or * established connection failed because connected host has failed to respond. */ //At this point, we've already timed out and informed the user. We can use return out of this. return; } } throw new Neptunium.Core.NeptuniumStreamConnectionFailedException(stream, ex); } }
public abstract Task TryConnectAsync(StationStream stream);
public async Task TryStreamStationAsync(StationStream stream) { if (!NepApp.Network.IsConnected) { throw new NeptuniumNetworkConnectionRequiredException(); } await playLock.WaitAsync(); ConnectingBegin?.Invoke(this, EventArgs.Empty); BasicNepAppMediaStreamer streamer = CreateStreamerForServerFormat(stream.ServerFormat); Task timeoutTask = null; Task connectionTask = null; timeoutTask = Task.Delay(10000); connectionTask = streamer.TryConnectAsync(stream); //a failure to connect is caught as a Neptunium.Core.NeptuniumStreamConnectionFailedException by AppShellViewModel Task result = await Task.WhenAny(connectionTask, timeoutTask); if (result == timeoutTask || connectionTask.IsFaulted) { ConnectingEnd?.Invoke(this, EventArgs.Empty); streamer.Dispose(); playLock.Release(); throw new NeptuniumStreamConnectionFailedException(stream, connectionTask.Exception?.InnerException?.Message ?? "Connection timed out."); } ShutdownPreviousPlaybackSession(); CurrentPlayer = new MediaPlayer(); MediaTransportControls = CurrentPlayer.SystemMediaTransportControls; MediaTransportControls.IsChannelDownEnabled = false; MediaTransportControls.IsChannelUpEnabled = false; MediaTransportControls.IsFastForwardEnabled = false; MediaTransportControls.IsNextEnabled = false; MediaTransportControls.IsPreviousEnabled = false; MediaTransportControls.IsRewindEnabled = false; MediaTransportControls.IsRewindEnabled = false; MediaTransportControls.IsPlayEnabled = true; MediaTransportControls.IsPauseEnabled = true; CurrentPlayer.AudioCategory = MediaPlayerAudioCategory.Media; CurrentPlayer.CommandManager.IsEnabled = true; CurrentPlayer.AudioDeviceType = MediaPlayerAudioDeviceType.Multimedia; CurrentPlayer.Volume = playerVolume; CurrentPlayer.MediaFailed += CurrentPlayer_MediaFailed; CurrentPlayerSession = CurrentPlayer.PlaybackSession; CurrentPlayerSession.PlaybackStateChanged += PlaybackSession_PlaybackStateChanged; streamer.InitializePlayback(CurrentPlayer); await CurrentPlayer.WaitForMediaOpenAsync(); streamer.MetadataChanged += Streamer_MetadataChanged; CurrentStreamer = streamer; CurrentStream = stream; NepApp.SongManager.SetCurrentStation(await NepApp.Stations.GetStationByNameAsync(CurrentStream.ParentStation)); SetMediaEngagement(true); NepApp.Stations.SetLastPlayedStation(stream.ParentStation, DateTime.Now); NepApp.SongManager.SetCurrentMetadataToUnknown(); streamer.Play(); ConnectingEnd?.Invoke(this, EventArgs.Empty); playLock.Release(); }