Exemple #1
0
        /*
         * Ask the server to skip the current song.
         */
        private IEnumerator SkipPlay(JSONNode play)
        {
            Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/play/" + play["id"] + "/skip");

            yield return StartCoroutine(SignedRequest (ajax));

            if ((current == null) || (current.play != play)) {
                // current song has since changed - we don't care about this response any more
                yield break;
            }

            if (ajax.success) {
                if (pendingPlay != null) {
                    // skip to play already queued up
                    JSONNode pp = pendingPlay;
                    pendingPlay = null;

                    AssignCurrentPlay(pp);

                } else if (pendingRequest != null) {
                    // we're waiting for a pending request to come in
                    AssignCurrentPlay(null, true);

                } else {
                    // we're probably out of music here, since a 'start' notification
                    // should have already kicked off a 'requestNextPlay()' call
                    AssignCurrentPlay(null);
                }

                yield break;

            } else {
                current.canSkip = false;  // prevent future tries until we get next song

                if (onSkipDenied != null) onSkipDenied(this);

                yield break;
            }
        }
Exemple #2
0
        /*
         * Tell the server that we're starting playback of our active song
         */
        private IEnumerator StartPlay(JSONNode play)
        {
            while (true) {
                Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/play/" + play["id"] + "/start");

                yield return StartCoroutine(SignedRequest(ajax));

                if ((current == null) || (current.play != play)) {
                    // nobody cares about this song any more
                    yield break;
                }

                if (ajax.success) {
                    current.canSkip = ajax.response["can_skip"].AsBool;
                    current.started = true;

                    if (onPlayStarted != null) onPlayStarted(this, play);

                    // start looking for the next song
                    yield return StartCoroutine(RequestNextPlay());

                    yield break;

                } else if (ajax.error == (int) FeedError.PlaybackStarted) {
                    // we appear to have missed the response to the original start.
                    // assume the song was good
                    current.canSkip = true;
                    current.started = true;

                    if (onPlayStarted != null) onPlayStarted(this, play);

                    // start looking for the next song
                    yield return StartCoroutine(RequestNextPlay());

                    yield break;

                } else {
                    current.retryCount++;

                    yield return new WaitForSeconds(2.0f);

                    // try again later
                }

            }
        }
Exemple #3
0
        /*
         * Ask the server to create a new play for us, and queue it up
         */
        private IEnumerator RequestNextPlay()
        {
            if (pendingRequest != null) {
                // we're already waiting for a play to come in
                yield break;
            }

            yield return StartCoroutine (EnsureClientId ());

            while (clientId != null) {
                Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/play");
                ajax.addParameter("formats", formats);
                ajax.addParameter("client_id", clientId);
                ajax.addParameter("max_bitrate", maxBitrate);

                if (!String.IsNullOrEmpty(_placementId)) {
                    ajax.addParameter("placement_id", _placementId);
                }

                if (!String.IsNullOrEmpty(_stationId)) {
                    ajax.addParameter ("station_id", _stationId);
                }

                // let the rest of the code know we're awaiting a response
                pendingRequest = new PendingRequest {
                    ajax = ajax,
                    retryCount = 0
                };

                yield return StartCoroutine(SignedRequest(ajax));

                if ((pendingRequest == null) || (pendingRequest.ajax != ajax)) {
                    // another request snuck in while waiting for the response to this one,
                    // so we don't care about this one any more - just quit
                    yield break;
                }

                if (ajax.success) {
                    inUS = true;

                    pendingRequest = null;

                    if (current != null) {
                        // play this when the current song is complete
                        pendingPlay = ajax.response["play"];

                    } else {
                        // start playing this right now, since nothing else is active
                        AssignCurrentPlay (ajax.response["play"]);
                    }

                    yield break;

                } else if (ajax.error == (int) FeedError.NoMoreMusic) {

                    if (current != null) {
                        // ran out of music to play, but we're still playing something, so
                        // just make a note here
                        pendingPlay = null;

                    } else {
                        // ran out of music, and nothing else to play

                        exhausted = true;

                        if (onPlaysExhausted != null) onPlaysExhausted(this);

                    }

                    pendingRequest = null;

                    yield break;

                } else if (ajax.error == (int) FeedError.NotUS) {
                    // user isn't in the united states, so can't play anything
                    inUS = false;

                    if (onNotInUS != null) onNotInUS(this);

                    yield break;

                } else {
                    // some unknown error
                    pendingRequest.retryCount++;

                    // wait for an increasingly long time before retrying
                    yield return new WaitForSeconds(0.5f * (float) Math.Pow(2.0, pendingRequest.retryCount));

                }
            }
        }
Exemple #4
0
        /************** internal API ******************/
        /*
         * Send an ajax request to the server along with authentication information
         */
        private IEnumerator SignedRequest(Ajax ajax)
        {
            // add in authentication header
            ajax.addHeader ("Authorization",
                            "Basic " + System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(token + ":" + secret)));

            yield return StartCoroutine(ajax.Request());

            if (!ajax.success && (ajax.error == (int) FeedError.BadCredentials)) {
                throw new Exception("Invalid credentials provided!");
            }

            //ajax.DebugResponse();

            yield break;
        }
Exemple #5
0
        private IEnumerator InvalidatePlay(JSONNode play)
        {
            int retryCount = 0;

            while (true) {
                Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/play/" + play["id"] + "/invalidate");

                yield return StartCoroutine (SignedRequest (ajax));

                if ((current == null) || (current.play != play)) {
                    // nboody cares about this song any more
                    yield break;
                }

                if (ajax.success) {
                    if (pendingPlay != null) {
                        // skip to play already queued up
                        JSONNode pp = pendingPlay;
                        pendingPlay = null;

                        AssignCurrentPlay(pp);

                    } else {
                        // invalidate current song
                        AssignCurrentPlay(null, true);

                        // If nothing is queued up, that might be because we haven't tried to 'start'
                        // this play yet, triggering the 'requestNextPlay'. So trigger it here.
                        yield return StartCoroutine(RequestNextPlay());
                    }

                    yield break;

                } else {
                    retryCount++;

                    yield return new WaitForSeconds(0.2f * (float) Math.Pow(2.0, retryCount));

                }
            }
        }
Exemple #6
0
        /*
         * Request information about the placement referred to by placementId. If it is
         * empty, then request a default placement and set placementId.
         */
        private IEnumerator GetPlacementInformation()
        {
            if (!String.IsNullOrEmpty(_placementId) && (placement != null) && ((string) placement["id"] == _placementId)) {
                // we already have this placement loaded up
                yield break;
            }

            while (true) {
                Ajax ajax;

                if (String.IsNullOrEmpty(_placementId)) {
                    ajax = new Ajax(Ajax.RequestType.GET, apiServerBase + "/placement");

                } else {
                    ajax = new Ajax(Ajax.RequestType.GET, apiServerBase + "/placement/" + _placementId);

                }

                yield return StartCoroutine (SignedRequest (ajax));

                if (ajax.success) {
                    placement = ajax.response["placement"];
                    stations = ajax.response["stations"];

                    if (String.IsNullOrEmpty(_placementId)) {
                        if (onPlacementChanged != null) onPlacementChanged(this, _placementId);
                    }

                    if (_placementId != placement["id"]) {
                        _placementId = placement["id"];

                        if (onPlacement != null) onPlacement(this, placement);
                    }

                    if (String.IsNullOrEmpty(_stationId) && (stations.Count > 0)) {
                        _stationId = stations[0]["id"];

                        if (onStationChanged != null) onStationChanged(this, _stationId);
                    }

                    if (onStations != null) onStations(this, stations);

                    yield break;

                } else if (ajax.error == (int) FeedError.MissingObject) {

                    // can't find placement - no point in continuing
                    if (String.IsNullOrEmpty(_placementId)) {

                        // no default placement
                        throw new Exception("No default placement for these credentials");

                    } else {

                        // no such placement
                        throw new Exception("No such placement with id " + _placementId);
                    }

                }

                yield return new WaitForSeconds(0.5f);
            }
        }
Exemple #7
0
        /*
         * Ensure we've got a clientId
         */
        private IEnumerator EnsureClientId()
        {
            if (clientId != null) {
                yield break;
            }

            if (PlayerPrefs.HasKey ("feedfm.client_id")) {
                // have one already, so use it
                clientId = PlayerPrefs.GetString("feedfm.client_id");

                if (onClientRegistered != null) onClientRegistered(this);

                yield break;

            } else {
                // need to get an id

                while (true) {
                    Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/client");

                    yield return StartCoroutine(SignedRequest (ajax));

                    if (ajax.success) {
                        clientId = ajax.response["client_id"];

                        try {
                            PlayerPrefs.SetString ("feedfm.client_id", clientId);

                        } catch (PlayerPrefsException) {
                            // ignore, *sigh*
                        }

                        if (onClientRegistered != null) onClientRegistered(this);

                        yield break;

                    } else if (ajax.error == (int) FeedError.NotUS) {

                        // user isn't in the united states, so can't play anything
                        inUS = false;

                        if (onNotInUS != null) onNotInUS(this);

                        yield break;
                    }

                    // no success, so wait bit and then try again
                    yield return new WaitForSeconds(1.0f);
                }
            }
        }
Exemple #8
0
        /*
         * Tell the server we've completed the current play, and make any pending
         * play active.
         */
        private IEnumerator CompletePlay()
        {
            Ajax ajax = new Ajax(Ajax.RequestType.POST, apiServerBase + "/play/" + current.play["id"] + "/complete");

            yield return StartCoroutine(SignedRequest (ajax));

            // we really don't care what the response was, really

            if (pendingRequest == null) {
                // start playing whatever we've got queued up
                JSONNode pp = pendingPlay;
                pendingPlay = null;

                AssignCurrentPlay(pp);

            } else {
                // waiting for a request to come in, so kill current song and announce that we're waiting
                AssignCurrentPlay (null, true);
            }
        }
Exemple #9
0
        /*
         * Tell the server how much of the song we've listened to
         */
        public virtual void ReportPlayElapsed(int seconds)
        {
            if (current == null) {
                throw new Exception ("Attempt to report elapsed play time, but the pay hasn't started");
            }

            Ajax ajax = new Ajax (Ajax.RequestType.POST, apiServerBase + "/play/" + current.play ["id"] + "/elapse");
            ajax.addParameter ("seconds", seconds.ToString ());

            StartCoroutine (SignedRequest (ajax));
        }