}
static gboolean sensitive_play(struct choosenode attribute((unused)) *cn) {
- return !!files_selected && disorder_eclient_connected(client);
+ return (!!files_selected
+ && (disorder_eclient_state(client) & DISORDER_CONNECTED));
}
#if 0
#endif
static gboolean sensitive_properties(struct choosenode attribute((unused)) *cn) {
- return !!files_selected && disorder_eclient_connected(client);
+ return !!files_selected && (disorder_eclient_state(client) & DISORDER_CONNECTED);
}
/* Main menu plumbing ------------------------------------------------------ */
static int choose_properties_sensitive(GtkWidget attribute((unused)) *w) {
- return !!files_selected && disorder_eclient_connected(client);
+ return !!files_selected && (disorder_eclient_state(client) & DISORDER_CONNECTED);
}
static int choose_selectall_sensitive(GtkWidget attribute((unused)) *w) {
static void update_icon(GtkWidget *button,
int visible, int usable) {
/* If the connection is down nothing is ever usable */
- if(!disorder_eclient_connected(client))
+ if(!(disorder_eclient_state(client) & DISORDER_CONNECTED))
usable = 0;
(visible ? gtk_widget_show : gtk_widget_hide)(button);
/* Only both updating usability if the button is visible */
* currently connected then no NOP is sent.
*/
static gboolean maybe_send_nop(gpointer attribute((unused)) data) {
- if(!nop_in_flight && disorder_eclient_connected(client)) {
+ if(!nop_in_flight && (disorder_eclient_state(client) & DISORDER_CONNECTED)) {
nop_in_flight = 1;
disorder_eclient_nop(client, nop_completed, 0);
}
assert(t != 0);
gtk_widget_set_sensitive(properties_widget,
(t->properties_sensitive(tab)
- && disorder_eclient_connected(client)));
+ && (disorder_eclient_state(client) & DISORDER_CONNECTED)));
gtk_widget_set_sensitive(selectall_widget,
t->selectall_sensitive(tab));
}
struct queue_entry attribute((unused)) *q) {
/* We can scratch if the playing track is selected */
return (playing_track
- && disorder_eclient_connected(client)
+ && (disorder_eclient_state(client) & DISORDER_CONNECTED)
&& selection_selected(ql->selection, playing_track->id));
}
struct queue_entry *q) {
/* We can remove if we're hovering over a particular track or any non-playing
* tracks are selected */
- return (disorder_eclient_connected(client)
+ return ((disorder_eclient_state(client) & DISORDER_CONNECTED)
&& ((q
&& q != playing_track)
|| count_selected_nonplaying(ql)));
struct queue_entry attribute((unused)) *q) {
/* "Properties" is sensitive if at least something is selected */
return (hash_count(ql->selection) > 0
- && disorder_eclient_connected(client));
+ && (disorder_eclient_state(client) & DISORDER_CONNECTED));
}
static void properties_activate(GtkMenuItem attribute((unused)) *menuitem,
/* Main menu plumbing ------------------------------------------------------ */
static int queue_properties_sensitive(GtkWidget *w) {
- return !!queue_count_selected(g_object_get_data(G_OBJECT(w), "queue"));
+ return (!!queue_count_selected(g_object_get_data(G_OBJECT(w), "queue"))
+ && (disorder_eclient_state(client) & DISORDER_CONNECTED));
}
static int queue_selectall_sensitive(GtkWidget *w) {
struct vector vec; /**< @brief body */
const disorder_eclient_log_callbacks *log_callbacks; /**< @brief log callbacks */
void *log_v; /**< @brief user data */
- unsigned long statebits; /**< @brief current state */
+ unsigned long statebits; /**< @brief latest state */
};
/* Forward declarations ******************************************************/
xclose(c->fd);
c->fd = -1;
c->state = state_disconnected;
+ c->statebits = 0;
}
c->output.nvec = 0;
c->input.nvec = 0;
op->sent = 0;
}
-/** @brief Return true if @c c is connected
- *
- * By connected it is meant that commands have a reasonable chance of being
- * processed soon, not merely that a TCP connection exists - for instance if
- * the client is still authenticating then that does not count as connected.
- */
-int disorder_eclient_connected(const disorder_eclient *c) {
- switch(c->state) {
- case state_disconnected:
- case state_connecting:
- case state_connected:
- return 0;
- case state_idle:
- case state_cmdresponse:
- case state_body:
- case state_log:
- return 1;
- }
- assert(!"reached");
+/** @brief Return current state */
+unsigned long disorder_eclient_state(const disorder_eclient *c) {
+ return c->statebits | (c->state > state_connected ? DISORDER_CONNECTED : 0);
}
/* Error reporting ***********************************************************/
static void logentry_completed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
if(!c->log_callbacks->completed) return;
+ c->state &= ~DISORDER_PLAYING;
c->log_callbacks->completed(c->log_v, vec[0]);
+ if(c->log_callbacks->state)
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_failed(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
if(!c->log_callbacks->failed)return;
+ c->state &= ~DISORDER_PLAYING;
c->log_callbacks->failed(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->state)
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_moved(disorder_eclient *c,
static void logentry_playing(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
if(!c->log_callbacks->playing) return;
+ c->state |= DISORDER_PLAYING;
c->log_callbacks->playing(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->state)
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_queue(disorder_eclient *c,
static void logentry_scratched(disorder_eclient *c,
int attribute((unused)) nvec, char **vec) {
if(!c->log_callbacks->scratched) return;
+ c->state &= ~DISORDER_PLAYING;
c->log_callbacks->scratched(c->log_v, vec[0], vec[1]);
+ if(c->log_callbacks->state)
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static const struct {
break;
}
if(!c->log_callbacks->state) return;
- c->log_callbacks->state(c->log_v, c->statebits);
+ c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
}
static void logentry_volume(disorder_eclient *c,
/** @brief Random play is enabled */
#define DISORDER_RANDOM_ENABLED 0x00000002
-/** @brief Track is paused */
+/** @brief Track is paused
+ *
+ * This is only meaningful if @ref DISORDER_PLAYING is set
+ */
#define DISORDER_TRACK_PAUSED 0x00000004
+/** @brief Track is playing
+ *
+ * This can be set even if the current track is paused (in which case @ref
+ * DISORDER_TRACK_PAUSED) will also be set.
+ */
+#define DISORDER_PLAYING 0x00000008
+
+/** @brief Connected to server
+ *
+ * By connected it is meant that commands have a reasonable chance of being
+ * processed soon, not merely that a TCP connection exists - for instance if
+ * the client is still authenticating then that does not count as connected.
+ */
+#define DISORDER_CONNECTED 0x00000010
+
struct queue_entry;
struct kvp;
struct sink;
void disorder_eclient_close(disorder_eclient *c);
/* Close C */
-int disorder_eclient_connected(const disorder_eclient *c);
+unsigned long disorder_eclient_state(const disorder_eclient *c);
void disorder_eclient_polled(disorder_eclient *c, unsigned mode);
/* Should be called when c's FD is readable and/or writable, and in any case