From 4190a4d995970b1897e43693546a6201a52e9059 Mon Sep 17 00:00:00 2001 Message-Id: <4190a4d995970b1897e43693546a6201a52e9059.1714698690.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sun, 8 Jun 2008 15:58:52 +0100 Subject: [PATCH] Further eclient error API change. Organization: Straylight/Edgeware From: Richard Kettlewell --- disobedience/choose.c | 44 ++++++++++++++++++++++--------------- disobedience/disobedience.c | 31 ++++++++++---------------- disobedience/queue.c | 42 +++++++++++++++++++---------------- disobedience/users.c | 8 ++++++- lib/eclient.c | 35 +++++++++++++++-------------- lib/eclient.h | 21 ++++++++++++++---- 6 files changed, 103 insertions(+), 78 deletions(-) diff --git a/disobedience/choose.c b/disobedience/choose.c index bfeae10..8e3a576 100644 --- a/disobedience/choose.c +++ b/disobedience/choose.c @@ -214,9 +214,9 @@ static struct choosenode *newnode(struct choosenode *parent, void (*fill)(struct choosenode *)); static void fill_root_node(struct choosenode *cn); static void fill_directory_node(struct choosenode *cn); -static void got_files(void *v, int nvec, char **vec); +static void got_files(void *v, const char *error, int nvec, char **vec); static void got_resolved_file(void *v, const char *error, const char *track); -static void got_dirs(void *v, int nvec, char **vec); +static void got_dirs(void *v, const char *error, int nvec, char **vec); static void expand_node(struct choosenode *cn, int contingent); static void contract_node(struct choosenode *cn); @@ -358,20 +358,14 @@ static void filled(struct choosenode *cn) { /** @brief Fill the root */ static void fill_root_node(struct choosenode *cn) { - struct callbackdata *cbd; - D(("fill_root_node")); clear_children(cn); /* More de-duping possible here */ if(cn->flags & CN_GETTING_ANY) return; gtk_label_set_text(GTK_LABEL(report_label), "getting files"); - cbd = xmalloc(sizeof *cbd); - cbd->u.choosenode = cn; - disorder_eclient_dirs(client, got_dirs, "", 0, cbd); - cbd = xmalloc(sizeof *cbd); - cbd->u.choosenode = cn; - disorder_eclient_files(client, got_files, "", 0, cbd); + disorder_eclient_dirs(client, got_dirs, "", 0, cn); + disorder_eclient_files(client, got_files, "", 0, cn); cn->flags |= CN_GETTING_FILES|CN_GETTING_DIRS; gets_in_flight += 2; } @@ -423,11 +417,15 @@ static void clear_children(struct choosenode *cn) { } /** @brief Called with a list of files just below some node */ -static void got_files(void *v, int nvec, char **vec) { - struct callbackdata *cbd = v; - struct choosenode *cn = cbd->u.choosenode; +static void got_files(void *v, const char *error, int nvec, char **vec) { + struct choosenode *cn = v; int n; + if(error) { + popup_protocol_error(0, error); + return; + } + D(("got_files %d files for %s %s", nvec, cn->path, cnflags(cn))); /* Complicated by the need to resolve aliases. */ cn->flags &= ~CN_GETTING_FILES; @@ -472,10 +470,14 @@ static void got_resolved_file(void *v, const char *error, const char *track) { } /** @brief Called with a list of directories just below some node */ -static void got_dirs(void *v, int nvec, char **vec) { - struct callbackdata *cbd = v; - struct choosenode *cn = cbd->u.choosenode; +static void got_dirs(void *v, const char *error, int nvec, char **vec) { + struct choosenode *cn = v; int n; + + if(error) { + popup_protocol_error(0, error); + return; + } D(("got_dirs %d dirs for %s %s", nvec, cn->path, cnflags(cn))); /* TODO this depends on local configuration for trackname_transform(). @@ -680,10 +682,16 @@ static struct choosenode *first_search_result(struct choosenode *cn) { * and also from initiate_seatch with an always empty list to indicate that * we're not searching for anything in particular. */ static void search_completed(void attribute((unused)) *v, + const char *error, int nvec, char **vec) { int n; char *s; + if(error) { + popup_protocol_error(0, error); + return; + } + search_in_flight = 0; /* Contract any choosenodes that were only expanded to show search * results */ @@ -768,13 +776,13 @@ static void initiate_search(void) { /* The search terms are bad! We treat this as if there were no search * terms at all. Some kind of feedback would be handy. */ fprintf(stderr, "bad terms [%s]\n", terms); /* TODO */ - search_completed(0, 0, 0); + search_completed(0, 0, 0, 0); } else { search_in_flight = 1; } } else { /* No search terms - we want to see all tracks */ - search_completed(0, 0, 0); + search_completed(0, 0, 0, 0); } } diff --git a/disobedience/disobedience.c b/disobedience/disobedience.c index a3b09af..2a65d67 100644 --- a/disobedience/disobedience.c +++ b/disobedience/disobedience.c @@ -352,35 +352,28 @@ static gboolean maybe_send_nop(gpointer attribute((unused)) data) { /** @brief Called when a rtp-address command succeeds */ static void got_rtp_address(void attribute((unused)) *v, + const char *error, int attribute((unused)) nvec, char attribute((unused)) **vec) { ++suppress_actions; rtp_address_in_flight = 0; - rtp_supported = 1; - rtp_is_running = rtp_running(); - control_monitor(0); - --suppress_actions; -} - -/** @brief Called when a rtp-address command fails */ -static void no_rtp_address(struct callbackdata attribute((unused)) *cbd, - int attribute((unused)) code, - const char attribute((unused)) *msg) { - ++suppress_actions; - rtp_address_in_flight = 0; - rtp_supported = 0; - rtp_is_running = 0; + if(error) { + /* An error just means that we're not using network play */ + rtp_supported = 0; + rtp_is_running = 0; + } else { + rtp_supported = 1; + rtp_is_running = rtp_running(); + control_monitor(0); + } control_monitor(0); --suppress_actions; } /** @brief Called to check whether RTP play is available */ static void check_rtp_address(void) { - if(!rtp_address_in_flight) { - struct callbackdata *const cbd = xmalloc(sizeof *cbd); - cbd->onerror = no_rtp_address; - disorder_eclient_rtp_address(client, got_rtp_address, cbd); - } + if(!rtp_address_in_flight) + disorder_eclient_rtp_address(client, got_rtp_address, NULL); } /* main -------------------------------------------------------------------- */ diff --git a/disobedience/queue.c b/disobedience/queue.c index 7f3a278..ecfc9e6 100644 --- a/disobedience/queue.c +++ b/disobedience/queue.c @@ -1466,34 +1466,38 @@ GtkWidget *added_widget(void) { * disobedience/queue.c requires @ref queue_entry structures with a valid and * unique @c id field. This function fakes it. */ -static void new_completed(void attribute((unused)) *v, int nvec, char **vec) { - struct queue_entry *q, *qh, *qlast = 0, **qq = &qh; - int n; - - for(n = 0; n < nvec; ++n) { - q = xmalloc(sizeof *q); - q->prev = qlast; - q->track = vec[n]; - q->id = vec[n]; - *qq = q; - qq = &q->next; - qlast = q; +static void new_completed(void *v, + const char *error, + int nvec, char **vec) { + if(error) + popup_protocol_error(0, error); + else { + struct queuelist *ql = v; + /* Convert the vector result to a queue linked list */ + struct queue_entry *q, *qh, *qlast = 0, **qq = &qh; + int n; + + for(n = 0; n < nvec; ++n) { + q = xmalloc(sizeof *q); + q->prev = qlast; + q->track = vec[n]; + q->id = vec[n]; + *qq = q; + qq = &q->next; + qlast = q; + } + *qq = 0; + queuelike_completed(ql, 0, qh); } - *qq = 0; - queuelike_completed(&ql_added, 0, qh); } /** @brief Update the newly-added list */ void added_update(void) { - struct callbackdata *cbd; D(("added_update")); - cbd = xmalloc(sizeof *cbd); - cbd->onerror = 0; - cbd->u.ql = &ql_added; gtk_label_set_text(GTK_LABEL(report_label), "updating newly added track list"); - disorder_eclient_new_tracks(client, new_completed, 0/*all*/, cbd); + disorder_eclient_new_tracks(client, new_completed, 0/*all*/, &ql_added); } /* Main menu plumbing ------------------------------------------------------ */ diff --git a/disobedience/users.c b/disobedience/users.c index 589716e..0590d69 100644 --- a/disobedience/users.c +++ b/disobedience/users.c @@ -109,10 +109,16 @@ static int users_find_user(const char *user, * * If users_deferred_select is set then that user is selected. */ -static void users_got_list(void attribute((unused)) *v, int nvec, char **vec) { +static void users_got_list(void attribute((unused)) *v, + const char *error, + int nvec, char **vec) { int n; GtkTreeIter iter; + if(error) { + popup_protocol_error(0, error); + return; + } /* Present users in alphabetical order */ qsort(vec, nvec, sizeof (char *), usercmp); /* Set the list contents */ diff --git a/lib/eclient.c b/lib/eclient.c index 768220f..69069f5 100644 --- a/lib/eclient.c +++ b/lib/eclient.c @@ -925,7 +925,7 @@ static void queue_response_opcallback(disorder_eclient *c, for(n = 0; n < c->vec.nvec; ++n) { q = xmalloc(sizeof *q); D(("queue_unmarshall %s", c->vec.vec[n])); - if(!queue_unmarshall(q, c->vec.vec[n], eclient_queue_error, op)) { + if(!queue_unmarshall(q, c->vec.vec[n], NULL, op)) { q->prev = qlast; *qtail = q; qtail = &q->next; @@ -955,7 +955,7 @@ static void playing_response_opcallback(disorder_eclient *c, switch(c->rc % 10) { case 2: if(queue_unmarshall(q = xmalloc(sizeof *q), c->line + 4, - eclient_queue_error, c)) + NULL, c)) completed(op->v, "cannot parse result", 0); else completed(op->v, 0, q); @@ -974,15 +974,14 @@ static void playing_response_opcallback(disorder_eclient *c, /* for commands that expect a list of some sort */ static void list_response_opcallback(disorder_eclient *c, struct operation *op) { + disorder_eclient_list_response *const completed = + (disorder_eclient_list_response *)op->completed; + D(("list_response_callback")); - if(c->rc / 100 == 2) { - if(op->completed) - ((disorder_eclient_list_response *)op->completed)(op->v, - c->vec.nvec, - c->vec.vec); - } else - /* TODO don't use protocol_error here */ - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + if(c->rc / 100 == 2) + completed(op->v, NULL, c->vec.nvec, c->vec.vec); + else + completed(op->v, errorstring(c), 0, 0); } /* for volume */ @@ -1269,17 +1268,19 @@ int disorder_eclient_new_tracks(disorder_eclient *c, static void rtp_response_opcallback(disorder_eclient *c, struct operation *op) { + disorder_eclient_list_response *const completed = + (disorder_eclient_list_response *)op->completed; D(("rtp_response_opcallback")); if(c->rc / 100 == 2) { - if(op->completed) { - int nvec; - char **vec = split(c->line + 4, &nvec, SPLIT_QUOTES, 0, 0); + int nvec; + char **vec = split(c->line + 4, &nvec, SPLIT_QUOTES, 0, 0); - ((disorder_eclient_list_response *)op->completed)(op->v, nvec, vec); - } + if(vec) + completed(op->v, NULL, nvec, vec); + else + completed(op->v, "error parsing response", 0, 0); } else - /* TODO don't use protocol_error here */ - protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line); + completed(op->v, errorstring(c), 0, 0); } /** @brief Determine the RTP target address diff --git a/lib/eclient.h b/lib/eclient.h index e37dda9..86caf75 100644 --- a/lib/eclient.h +++ b/lib/eclient.h @@ -201,8 +201,8 @@ typedef void disorder_eclient_volume_response(void *v, * @param error Error string or NULL on success * @param q Head of queue data list * - * @p error will be NULL on success. In this case @p q be the (head of the) - * result. + * @p error will be NULL on success. In this case @p q will be the (head of + * the) result. * * @p error will be non-NULL on failure. In this case @p q may be NULL but * MIGHT also be some subset of the queue. For consistent behavior it should @@ -212,8 +212,21 @@ typedef void disorder_eclient_queue_response(void *v, const char *error, struct queue_entry *q); -typedef void disorder_eclient_list_response(void *v, int nvec, char **vec); -/* completion callback for file listing etc */ +/** @brief List request completion callback + * @param v User data + * @param error Error string or NULL on success + * @param nvec Number of elements in response list + * @param vec Pointer to response list + * + * @p error will be NULL on success. In this case @p nvec and @p vec will give + * the result. + * + * @p error will be non-NULL on failure. In this case @p nvec and @p vec will + * be 0 and NULL. + */ +typedef void disorder_eclient_list_response(void *v, + const char *error, + int nvec, char **vec); disorder_eclient *disorder_eclient_new(const disorder_eclient_callbacks *cb, void *u); -- [mdw]