/// <summary> /// Start the stream /// </summary> /// <param name="id"></param> /// <returns></returns> public async Task <bool> Start(int id) { Stream stream; // Stream does not exist if ((stream = await _streamLogic.For(_user).Get(id)) == null) { return(false); } // Stream already started if (_state.StreamItems.ContainsKey(id) && _state.StreamItems[id].State == StreamStatusEnum.Started) { return(false); } var streamRipperInstance = _streamRipperProxy.Proxy(new Uri(stream.Url)); streamRipperInstance.SongChangedEventHandlers += async(_, arg) => { var songMetaData = arg.SongInfo.SongMetadata; var track = $"{songMetaData.Artist}-{songMetaData.Title}"; var filename = $"{track}.mp3"; if (_filterSongLogic.ShouldInclude(arg.SongInfo.Stream, track, stream.Filter, out var duration)) { var aggregatedSink = await _sinkService.ResolveStreamSink(stream); // Upload the stream await aggregatedSink(arg.SongInfo.Stream.Reset(), filename); var extendedSongMetadata = await _songMetaDataExtract.Populate(ExtendedSongMetadata.Extend( arg.SongInfo.SongMetadata, x => { x.Duration = duration; })); // Invoke socket await _hub.Clients.User(_user.Id.ToString()).SendAsync("download", filename, extendedSongMetadata, arg.SongInfo.Stream.Reset().ConvertToBase64(), new { stream.Name, stream.Id } ); } else { await _hub.Clients.User(_user.Id.ToString()) .SendAsync("log", $"Stream {id} with name {filename} skipped"); } }; streamRipperInstance.StreamEndedEventHandlers += async(sender, arg) => { await _hub.Clients.User(_user.Id.ToString()).SendAsync("log", $"Stream {id} ended"); _state.StreamItems[id].State = StreamStatusEnum.Stopped; }; streamRipperInstance.StreamFailedHandlers += async(sender, arg) => { await _hub.Clients.User(_user.Id.ToString()).SendAsync("log", $"Stream {id} failed", arg.Exception?.Message); _state.StreamItems[id].State = StreamStatusEnum.Fail; _logger.LogError($"Failed to start {id}", arg.Exception); }; streamRipperInstance.StreamStartedEventHandlers += async(sender, arg) => { await _hub.Clients.User(_user.Id.ToString()).SendAsync("log", $"Stream {id} started"); }; streamRipperInstance.StreamUpdateEventHandlers += async(sender, arg) => { await _hub.Clients.User(_user.Id.ToString()).SendAsync("log", $"Stream {id} updated with {arg.SongRawPartial.Length} bytes"); }; // Start the ripper streamRipperInstance.Start(); // Add to the dictionary _state.StreamItems[id] = new StreamItem { User = _user, StreamRipper = streamRipperInstance, State = StreamStatusEnum.Started }; await _configLogic.UpdateGlobalConfig(c => new GlobalConfigViewModel(c) { StartedStreams = c.StartedStreams.Add(id) }); return(true); }