Exemplo n.º 1
0
 private async Task PlayFromOffset(
     string userId,
     Station station,
     NowPlaying ownerNP,
     StationServiceResult result,
     TimeSpan error = default)
 {
     if (error.Equals(default))
Exemplo n.º 2
0
        public async Task <StationServiceResult> Start(string userId, string stationId)
        {
            if (string.IsNullOrEmpty(userId))
            {
                throw new ArgumentNullException(nameof(userId));
            }
            if (string.IsNullOrEmpty(stationId))
            {
                throw new ArgumentNullException(nameof(stationId));
            }

            var result = new StationServiceResult {
                Logs = new List <MetricLogEntry>()
            };

            string sId     = Station.CanonicalId(stationId);
            var    station = await _data.GetOrDefault(sId, sId);

            if (station == null)
            {
                return new StationServiceResult {
                           Status = 404, Message = $"Station ({stationId}) not found"
                }
            }
            ;

            // Does station have an owner, and is it this user?
            if (station.OwnerUserId != null && station.OwnerUserId != userId)
            {
                result.Message = $"Station ({stationId}) already has another owner. Change owner before starting.";

                result.Status = 500;
                result.Code   = StationServiceResult.StationHasOwner;
                return(result);
            }

            var np = await GetNowPlaying(userId, result);

            if (!np.IsPlaying)
            {
                result.Message = "User's device is not active";
                result.Status  = 202;
                result.Code    = StationServiceResult.UserDeviceNotActive;
                return(result);
            }

            if (!ContextSupported(np))
            {
                result.Message = $"Spotify playback context ({np.Context?.Type}) is not supported.";
                result.Status  = 500;
                result.Code    = StationServiceResult.ContextNotSupported;
                return(result);
            }

            // set player
            await _playerService.SetPlayer(stationId, userId, np);

            // set owner
            station.OwnerUserId = userId;

            // set startdate
            station.StartDateTime = DateTimeOffset.UtcNow;

            await _data.Replace(station, station.ETag);

            result.Status  = 200;
            result.Message = "Playing";
            result.Success = true;
            return(result);
        }
Exemplo n.º 3
0
        public async Task <StationServiceResult> Join(string userId, string stationId)
        {
            if (string.IsNullOrEmpty(userId))
            {
                throw new ArgumentNullException(nameof(userId));
            }
            if (string.IsNullOrEmpty(stationId))
            {
                throw new ArgumentNullException(nameof(stationId));
            }

            var result = new StationServiceResult {
                Logs = new List <MetricLogEntry>()
            };

            string sId     = Station.CanonicalId(stationId);
            var    station = await _data.GetOrDefault(sId, sId);

            if (station == null)
            {
                return new StationServiceResult {
                           Status = 404, Message = $"Station ({stationId}) not found"
                }
            }
            ;

            if (station.OwnerUserId == null)
            {
                return new StationServiceResult
                       {
                           Status  = 500,
                           Message = $"Station ({stationId}) has no owner. Start the station to continue.",
                           Code    = StationServiceResult.StationHasNoOwner
                       }
            }
            ;

            var ownerNP = await GetNowPlaying(station.OwnerUserId, result);

            if (!ownerNP.IsPlaying)
            {
                // set player
                await _playerService.SetPlayer(stationId, station.OwnerUserId, ownerNP);

                return(new StationServiceResult
                {
                    Status = 202,
                    Message = $"Station ({stationId}) Owner's device is not active",
                    Code = StationServiceResult.StationOwnersDeviceNotActive
                });
            }

            if (!ContextSupported(ownerNP))
            {
                // set player
                await _playerService.SetPlayer(stationId, station.OwnerUserId, ownerNP);

                result.Message = $"Spotify playback context ({ownerNP.Context?.Type}) is not supported.";
                result.Status  = 500;
                result.Code    = StationServiceResult.ContextNotSupported;
                return(result);
            }

            // ONE
            var np1 = await GetNowPlaying(userId, result);

            if (!np1.IsPlaying)
            {
                // set player
                await _playerService.SetPlayer(stationId, userId, np1);

                return(new StationServiceResult
                {
                    Status = 202,
                    Message = "User's device is not active",
                    Code = StationServiceResult.UserDeviceNotActive
                });
            }

            // SYNC user to owner
            await TurnOffShuffleRepeat(userId, np1);

            try
            {
                // mute joining player
                await MuteUnmute(userId, np1, true);

                // TWO
                await PlayFromOffset(userId, station, ownerNP, result);

                // THREE
                //CALCULATE ERROR, if greater than 250ms, DO FOUR
                var ownerNP2 = await GetNowPlaying(station.OwnerUserId, result);

                var error = CalculateError(ownerNP2, await GetNowPlaying(userId, result), result);

                if (Math.Abs(error.TotalMilliseconds) > 500)
                {
                    // FOUR
                    // PLAY OFFSET AGAIN
                    await PlayFromOffset(userId, station, ownerNP2, result, error : error);

                    var ownerNP3 = await GetNowPlaying(station.OwnerUserId, result);

                    var error2 = CalculateError(ownerNP3, await GetNowPlaying(userId, result), result);

                    if (Math.Abs(error2.TotalMilliseconds) > 500)
                    {
                        // FIVE
                        // PLAY OFFSET AGAIN
                        await PlayFromOffset(userId, station, ownerNP3, result, error : error2);

                        CalculateError(await GetNowPlaying(station.OwnerUserId, result), await GetNowPlaying(userId, result), result);
                    }
                }
            }
            finally
            {
                // unmute joining player
                await MuteUnmute(userId, np1, false, volume : np1.Device.VolumePercent ?? 100);
            }

            // set Owner.Player
            await _playerService.SetPlayer(stationId, station.OwnerUserId, ownerNP);

            // set User.Player
            await _playerService.SetPlayer(stationId, userId, np1);

            result.Status  = 200;
            result.Message = "Playing";
            return(result);
        }