void api_CatalogUpdateCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { result.Text = App.HandleError(e.Error); } else { result.Text = "ticket " + e.GetResultData() as string; } }
void api_CatalogDeleteCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { result.Text = App.HandleError(e.Error); } else { Catalog cat = (Catalog)e.GetResultData(); result.Text = "Deleted " + cat.Name + " with ID " + cat.Id; } }
void api_CatalogStatusCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { result.Text = App.HandleError(e.Error); } else { Ticket t = e.GetResultData() as Ticket; result.Text = String.Format("ticket {0} at {1}% updated {2} items", t.Status, t.PercentComplete, t.ItemsUpdated); } }
void api_CatalogListCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { result.Text = App.HandleError(e.Error); } else { result.Text = ((List<Catalog>)e.GetResultData()) .Select<Catalog, string>((cat) => cat.Name + " with ID " + cat.Id) .Aggregate<string>((sofar, current) => sofar + Environment.NewLine + current); } }
void api_SearchSongCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { result.Text = App.HandleError(e.Error); } else { result.Text = ((List<Song>)e.GetResultData()) .Select<Song, string>((so) => so.Title + " by " + so.ArtistName) .Aggregate<string>((sofar, current) => sofar + Environment.NewLine + current); } }
void DownloadAnalyzedSongs_CatalogReadCompleted( object sender, EchoNestApiEventArgs e) { if (e.Error == null) { Catalog cat = (Catalog)e.GetResultData(); if (cat.Items.Count > 0) { StoreDownloadedSongs(cat); } if (SongsToAnalyze.Count == 0) { // Yay, we are done AllDone = true; logger.Info("Completed DownloadAnalyzedSongs"); } else { if (cat.Items.Count == downloadTake) { // There are more songs to download, run again DownloadSkip++; } else { // There are no more songs in the remote catalog, but // we still have unanalyzed songs. Sigh... start // from the beginning DownloadSkip = 0; } logger.Debug("Download of analyzed songs completed, " + "will continue to run until all songs analyzed"); DownloadAnalyzedSongsNeedsToRunAgain(); } } else { logger.Error("Download of analyzed songs failed, retrying"); DownloadAnalyzedSongsNeedsToRunAgain(); } }
void DownloadAnalyzedSongsAlreadyInRemoteCatalog_CatalogReadCompleted( object sender, EchoNestApiEventArgs e) { if (e.Error == null) { Catalog cat = (Catalog)e.GetResultData(); if (cat.Items.Count > 0) { StoreDownloadedSongs(cat); } if (SongsToAnalyze.Count == 0) { // Yay, we are done AllDone = true; logger.Info("No songs left to analyze, all done"); logger.Info("Completed DownloadAnalyzedSongsAlreadyInRemoteCatalog"); } else { if (cat.Items.Count == downloadTake) { // We grabbed a full downloadTake number of items, so // there must be more items logger.Debug("Check if songs are already in remote catalog completed, " + "will run again since extra items are found"); DownloadSkip++; DownloadAnalyzedSongsAlreadyInRemoteCatalogNeedsToRunAgain(); } else { // Or it could be that we are done with the remote catalog, but we // still need to analyze some songs that weren't there, so we need // to go through with the rest of the process DownloadSkip = 0; SongsToAnalyzeBatchDownloadReady = true; logger.Info("Completed DownloadAnalyzedSongsAlreadyInRemoteCatalog"); } } } else { logger.Error("Check if songs are already in remote catalog failed, retrying"); DownloadAnalyzedSongsAlreadyInRemoteCatalogNeedsToRunAgain(); } }
void AnalyzeSongs_CatalogUpdateCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error == null) { // If this was the last batch if ((bool)e.UserState) { SongsToAnalyzeBatchUploadReady = true; logger.Info("Completed AnalyzeSongs"); } else { UploadSkip++; AnalyzeSongsNeedsToRunAgain(); } } else { logger.Error("Upload failed, retrying"); AnalyzeSongsNeedsToRunAgain(); } }
/// <summary> /// Handler for the response body /// </summary> void SendHttpRequestOpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { EchoNestApiEventArgs args = null; Dictionary<string, object> state = (Dictionary<string, object>)e.UserState; string path = (string)state["path"]; object userState = state["userState"]; HttpHelper h = (HttpHelper)sender; // TODO catch exception if network is not present if (e.Cancelled) { args = new EchoNestApiEventArgs(e.Error, true, userState, null); } else if (e.Error == null) { try { string responseString; using (var stream = e.Result) { // TODO Handle 304 response? // var response = h.HttpWebResponse; using (var reader = new StreamReader(stream)) { responseString = reader.ReadToEnd(); } } if (!ResponseContainsError(responseString, out args, userState)) { args = HandleResponse(path, responseString, userState); } } catch (Exception ex) { args = new EchoNestApiEventArgs(ex, h.HttpWebRequest.IsCancelled, userState, null); } } else { var ex = e.Error as WebExceptionWrapper; var response = ex.GetResponse(); bool returnGenericError = true; if (response != null) { using (var stream = response.GetResponseStream()) { if (stream != null) { string responseString; using (var reader = new StreamReader(stream)) { responseString = reader.ReadToEnd(); } if (ResponseContainsError(responseString, out args, userState)) { returnGenericError = false; } } } } if (returnGenericError) { args = new EchoNestApiEventArgs(ex, false, userState, null); } } OnCompleted(path, args); }
/// <summary> /// Regardless whether the response status code is 200 or something else, /// the response could still contain an error if the "code" property in the /// JSON response is not "0", so check for that. /// </summary> /// <param name="args">Null if no error, otherwise will contain error /// information</param> /// <returns>True if the response contains an error status</returns> private bool ResponseContainsError(string responseString, out EchoNestApiEventArgs args, object userState) { args = null; try { JToken jo = JObject.Parse(responseString)["response"]["status"]; int code = (int)jo["code"]; if (code != 0) { EchoNestApiException enx = new EchoNestApiException( (EchoNestApiException.EchoNestApiExceptionType)code, (string)jo["message"]); args = new EchoNestApiEventArgs(enx, false, userState, null); return true; } } catch (Exception) { // If we're here it means we weren't able to extract a status // code out of the response return false; } return false; }
/// <summary> /// Demux callbacks from SendHttpRequest method. /// </summary> private void OnCompleted(string path, EchoNestApiEventArgs args) { EventHandler<EchoNestApiEventArgs> e = null; switch (path) { case EchoNestPaths.SongSearch: e = SongSearchCompleted; break; case EchoNestPaths.CatalogCreate: e = CatalogCreateCompleted; break; case EchoNestPaths.CatalogList: e = CatalogListCompleted; break; case EchoNestPaths.CatalogUpdate: e = CatalogUpdateCompleted; break; case EchoNestPaths.CatalogStatus: e = CatalogStatusCompleted; break; case EchoNestPaths.CatalogRead: e = CatalogReadCompleted; break; case EchoNestPaths.CatalogDelete: e = CatalogDeleteCompleted; break; } if (e != null) { if (dispatchOnUiThread) { // HttpWebRequest does its work on a background thread, // so dispatch to the UI thread for convenience Deployment.Current.Dispatcher.BeginInvoke(() => e(this, args)); } else { // Dispatch on calling thread e(this, args); } } }
static void Api_CatalogUpdateCompleted1(object sender, EchoNestApiEventArgs e) { if (e.Error != null) { if (e.Error is WebExceptionWrapper) { // Transient network error LoadCatalogIdNeedsToRunAgain(); } else if (e.Error is EchoNestApiException) { EchoNestApiException er = e.Error as EchoNestApiException; if (er.Code == EchoNestApiException.EchoNestApiExceptionType.InvalidParameter && String.Equals(er.Message, "This catalog does not exist")) { // They either didn't have a CatalogId in local storage, or // they did have one, but it wasn't on the cloud service. In // both cases, we create a new one LoadCatalogIdNeedsToCreateCatalog(); } } } else { // This catalog exists, everything is great App thisApp = App.Current as App; lock (thisApp.Model.CatalogId) { thisApp.Model.CatalogId = (string)e.UserState; } } }
static void Api_CatalogUpdateCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error == null) { App thisApp = App.Current as App; uploadSkip++; thisApp.Model.SongsToAnalyzeBatchUploadReady = true; } else { // AnalyzeSongs needs to run again ExecutionQueue.Enqueue(new WaitCallback(DataModel.AnalyzeSongs), ExecutionQueue.Policy.Queued); } }
static void Api_CatalogReadCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error == null) { App thisApp = App.Current as App; BeatMachineDataContext context = new BeatMachineDataContext( BeatMachineDataContext.DBConnectionString); Catalog cat = (Catalog)e.GetResultData(); // TODO This check doesn't work well, it won't terminate // especially in the case where the catalog has more items that // the client doesn't know about if (!(cat.Items.Count == 0 && context.AnalyzedSongs.Count() == thisApp.Model.SongsToAnalyzeBatchSize)) { context.AnalyzedSongs.InsertAllOnSubmit( cat.Items.Select<Song, AnalyzedSong>( s => new AnalyzedSong { ItemId = s.Request.ItemId, ArtistName = s.ArtistName ?? s.Request.ArtistName, SongName = s.SongName ?? s.Request.SongName, AudioSummary = s.AudioSummary != null ? new AnalyzedSong.Summary { Tempo = s.AudioSummary.Tempo } : null } )); context.SubmitChanges(); downloadSkip = context.AnalyzedSongs.Count(); DownloadAnalyzedSongsNeedsToRunAgain(); } else { thisApp.Model.SongsToAnalyzeBatchDownloadReady = true; } } else { DownloadAnalyzedSongsNeedsToRunAgain(); } }
static void Api_CatalogCreateCompleted(object sender, EchoNestApiEventArgs e) { if (e.Error == null) { App thisApp = App.Current as App; Catalog cat = (Catalog)e.GetResultData(); // TODO If isolated storage fails here, then the next time they // run the app, we will create another catalog. We need to handle // this somehow - perhaps use the unique device ID (which is bad // practice apparently) as the catalog name to make sure there is // only one catalog created per device ever. lock (thisApp.Model.CatalogId) { // Store in isolated storage IsolatedStorageSettings.ApplicationSettings["CatalogId"] = cat.Id; IsolatedStorageSettings.ApplicationSettings.Save(); thisApp.Model.CatalogId = cat.Id; } } else { // Couldn't create successfully, try again later LoadCatalogIdNeedsToRunAgain(); } }
void LoadCatalogIdNeedsToCheckCatalogId_CatalogUpdateCompleted( object sender, EchoNestApiEventArgs e) { if (e.Error != null) { if (e.Error is WebExceptionWrapper) { // Transient network error logger.Error("Verifying remote CatalogID failed, retrying"); LoadCatalogIdNeedsToRunAgain(); } else if (e.Error is EchoNestApiException) { EchoNestApiException er = e.Error as EchoNestApiException; if (er.Code == EchoNestApiException.EchoNestApiExceptionType.InvalidParameter && String.Equals(er.Message, "This catalog does not exist")) { // They either didn't have a CatalogId in local storage, or // they did have one, but it wasn't on the cloud service. In // both cases, we create a new one logger.Debug("Verifying remote CatalogID succeeded, but it's missing"); LoadCatalogIdNeedsToCreateCatalog(); } } } else { logger.Debug("Verifying remote CatalogID succeeded, it's there"); CatalogId = (string)e.UserState; logger.Info("Completed LoadCatalogId"); } }
void LoadCatalogIdNeedsToCreateCatalog_CatalogCreateCompleted( object sender, EchoNestApiEventArgs e) { if (e.Error == null) { Catalog cat = (Catalog)e.GetResultData(); // TODO If isolated storage fails here, then the next time they // run the app, we will create another catalog. We need to handle // this somehow - perhaps use the unique device ID (which is bad // practice apparently) as the catalog name to make sure there is // only one catalog created per device ever. logger.Debug("Creating remote CatalogID completed successfully"); SafeIsolatedStorageSettings settings = new SafeIsolatedStorageSettings(); settings[CatalogIdPropertyName] = cat.Id; settings.Save(); CatalogId = cat.Id; logger.Info("Completed LoadCatalogId"); } else { logger.Error("Creating remote CatalogID failed, retrying"); LoadCatalogIdNeedsToRunAgain(); } }
/// <summary> /// Handler for writing out the request body if needed /// </summary> void SendHttpRequestOpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e) { EchoNestApiEventArgs args = null; Dictionary<string, object> state = (Dictionary<string, object>)e.UserState; string path = (string)state["path"]; object body = state["body"]; object userState = state["userState"]; Dictionary<string, string> parameters = (Dictionary<string, string>)state["parameters"]; HttpHelper h = (HttpHelper)sender; if (e.Cancelled) { args = new EchoNestApiEventArgs(e.Error, true, userState, null); } else if (e.Error == null) { try { using (var stream = e.Result) { parameters["data"] = JsonConvert.SerializeObject( body, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore }); StreamWriter writer = new StreamWriter(stream); writer.Write(CreateMultipartForm(parameters)); writer.Flush(); } h.OpenReadAsync(new Dictionary<string, object> { {"path", path}, {"userState", userState} }); return; } catch (Exception ex) { args = new EchoNestApiEventArgs(ex, h.HttpWebRequest.IsCancelled, userState, null); } } else { var ex = e.Error as WebExceptionWrapper; if (ex != null) { if (ex.GetResponse() != null) { h.OpenReadAsync(path); return; } } args = new EchoNestApiEventArgs(e.Error, false, userState, null); } OnCompleted(path, args); }