int main (int argc, char **argv) { GMainLoop *ml; xmmsv_t *operands; xmmsc_result_t *result; xmmsc_connection_t *connection; if (argc != 4) { fprintf (stderr, "Usage: %s service-id op1 op2\n", argv[0]); return EXIT_FAILURE; } /* Connect as usual. */ connection = xmmsc_init ("sumclient"); if (!connection) { fprintf (stderr, "OOM!\n"); exit (EXIT_FAILURE); } if (!xmmsc_connect (connection, getenv ("XMMS_PATH"))) { fprintf (stderr, "Connection failed: %s\n", xmmsc_get_last_error (connection)); exit (EXIT_FAILURE); } ml = g_main_loop_new (NULL, FALSE); /* Build a list of two operands for sumservice (tut9). */ operands = xmmsv_build_list (xmmsv_new_int (atoi(argv[2])), xmmsv_new_int (atoi(argv[3])), XMMSV_LIST_END); /* And send the list to the sumservice. * We use the reply policy of only expecting a single reply, * which means the receiving client will get an error from * the server if it attempts to reply to this message more * than once. */ result = xmmsc_c2c_send (connection, atoi(argv[1]), XMMS_C2C_REPLY_POLICY_SINGLE_REPLY, operands); xmmsv_unref (operands); xmmsc_result_notifier_set (result, print_sum, ml); xmmsc_result_unref (result); xmmsc_mainloop_gmain_init (connection); g_main_loop_run (ml); xmmsc_unref (connection); return EXIT_SUCCESS; }
static xmmsv_t * xmms_medialib_entry_to_tree (xmms_medialib_session_t *session, xmms_medialib_entry_t entry) { s4_resultset_t *set; s4_val_t *song_id; xmmsv_t *ret, *id; gint i; song_id = s4_val_new_int (entry); set = xmms_medialib_filter (session, "song_id", song_id, S4_COND_PARENT, NULL, NULL, S4_FETCH_PARENT | S4_FETCH_DATA); s4_val_free (song_id); ret = xmmsv_new_dict (); for (i = 0; i < s4_resultset_get_rowcount (set); i++) { const s4_result_t *res; res = s4_resultset_get_result (set, 0, 0); while (res != NULL) { xmmsv_t *v_entry = NULL; const s4_val_t *val; const char *s; gint32 i; val = s4_result_get_val (res); if (s4_val_get_str (val, &s)) { v_entry = xmmsv_new_string (s); } else if (s4_val_get_int (val, &i)) { v_entry = xmmsv_new_int (i); } xmms_medialib_tree_add_tuple (ret, s4_result_get_key (res), s4_result_get_src (res), v_entry); xmmsv_unref (v_entry); res = s4_result_next (res); } } s4_resultset_free (set); id = xmmsv_new_int (entry); xmms_medialib_tree_add_tuple (ret, "id", "server", id); xmmsv_unref (id); return ret; }
/** List a playlist */ static GList * xmms_playlist_client_list_entries (xmms_playlist_t *playlist, const gchar *plname, xmms_error_t *err) { GList *entries = NULL; xmmsv_coll_t *plcoll; xmms_medialib_entry_t entry; xmmsv_list_iter_t *it; g_return_val_if_fail (playlist, NULL); g_mutex_lock (playlist->mutex); plcoll = xmms_playlist_get_coll (playlist, plname, err); if (plcoll == NULL) { g_mutex_unlock (playlist->mutex); return NULL; } xmmsv_get_list_iter (xmmsv_coll_idlist_get (plcoll), &it); for (xmmsv_list_iter_first (it); xmmsv_list_iter_valid (it); xmmsv_list_iter_next (it)) { xmmsv_list_iter_entry_int (it, &entry); entries = g_list_prepend (entries, xmmsv_new_int (entry)); } xmmsv_list_iter_explicit_destroy (it); g_mutex_unlock (playlist->mutex); entries = g_list_reverse (entries); return entries; }
static void update_playtime (xmms_output_t *output, int advance) { guint buffersize = 0; g_mutex_lock (&output->playtime_mutex); output->played += advance; g_mutex_unlock (&output->playtime_mutex); buffersize = xmms_output_plugin_method_latency_get (output->plugin, output); if (output->played < buffersize) { buffersize = output->played; } g_mutex_lock (&output->playtime_mutex); if (output->format) { guint ms = xmms_sample_bytes_to_ms (output->format, output->played - buffersize); if ((ms / 100) != (output->played_time / 100)) { xmms_object_emit (XMMS_OBJECT (output), XMMS_IPC_SIGNAL_PLAYBACK_PLAYTIME, xmmsv_new_int (ms)); } output->played_time = ms; } g_mutex_unlock (&output->playtime_mutex); }
static xmmsv_t * aggregate_set (xmmsv_t *current, gint int_value, const gchar *str_value) { set_data_t *data; xmmsv_t *value; gpointer key; guint length; if (current == NULL) { set_data_t init = { .ht = g_hash_table_new (NULL, NULL), .list = xmmsv_new_list () }; current = xmmsv_new_bin ((guchar *) &init, sizeof (set_data_t)); } xmmsv_get_bin (current, (const guchar **) &data, &length); if (str_value != NULL) { value = xmmsv_new_string (str_value); key = (gpointer) str_value; } else { value = xmmsv_new_int (int_value); key = GINT_TO_POINTER (int_value); } if (g_hash_table_lookup (data->ht, key) == NULL) { g_hash_table_insert (data->ht, key, value); xmmsv_list_append (data->list, value); } xmmsv_unref (value); return current; }
/** * Trigger a removed siginal to the client. This should be * called when an entry has been removed from the medialib * * @param entry Entry to signal a remove for. */ static void xmms_medialib_entry_send_removed (xmms_medialib_t *medialib, xmms_medialib_entry_t entry) { xmms_object_emit (XMMS_OBJECT (medialib), XMMS_IPC_SIGNAL_MEDIALIB_ENTRY_REMOVED, xmmsv_new_int (entry)); }
static xmmsv_t * aggregate_random (xmmsv_t *current, gint int_value, const gchar *str_value) { random_data_t *data; guint length; if (current == NULL) { random_data_t init = { 0 }; current = xmmsv_new_bin ((guchar *) &init, sizeof (random_data_t)); } xmmsv_get_bin (current, (const guchar **) &data, &length); data->n++; if (g_random_int_range (0, data->n) == 0) { if (data->data != NULL) { xmmsv_unref (data->data); } if (str_value != NULL) { data->data = xmmsv_new_string (str_value); } else { data->data = xmmsv_new_int (int_value); } } return current; }
static xmms_xspf_track_attr_t * xmms_xspf_track_attr_from_node (const xmms_xspf_track_prop_t *prop, xmlNodePtr node) { xmmsv_t *value; xmms_xspf_track_attr_t *attr; switch (prop->attr_type) { case XMMS_XSPF_TRACK_ATTR_TYPE_STRING: value = xmmsv_new_string ((char *)node->children->content); break; case XMMS_XSPF_TRACK_ATTR_TYPE_INT32: { /* TODO: check for errors */ gint32 val = strtol ((char *)node->children->content, (char **)NULL, 10); value = xmmsv_new_int (val); break; } } if (!value) { return NULL; } attr = g_new0 (xmms_xspf_track_attr_t, 1); attr->key = prop->name; attr->value = value; return attr; }
static void xmms_medialib_entry_send_update (xmms_medialib_t *medialib, xmms_medialib_entry_t entry) { xmms_object_emit (XMMS_OBJECT (medialib), XMMS_IPC_SIGNAL_MEDIALIB_ENTRY_UPDATE, xmmsv_new_int (entry)); }
gboolean xmms_xform_metadata_set_int (xmms_xform_t *xform, const char *key, int val) { g_hash_table_insert (xform->metadata, g_strdup (key), xmmsv_new_int (val)); xform->metadata_changed = TRUE; return TRUE; }
void xmms_xform_metadata_set_int (xmms_xform_t *xform, const char *key, int val) { XMMS_DBG ("Setting '%s' to %d", key, val); g_hash_table_insert (xform->metadata, g_strdup (key), xmmsv_new_int (val)); xform->metadata_changed = TRUE; }
void xmms_xform_browse_add_entry_property_int (xmms_xform_t *xform, const gchar *key, gint value) { xmmsv_t *val = xmmsv_new_int (value); xmms_xform_browse_add_entry_property (xform, key, val); xmmsv_unref (val); }
static xmmsv_t * create_data (int type, const char *data, uint32_t len) { switch (type) { case JSON_STRING: return xmmsv_new_string (data); case JSON_INT: return xmmsv_new_int (atoi(data)); case JSON_FLOAT: return xmmsv_new_float (strtof (data, NULL)); case JSON_NULL: return xmmsv_new_none (); case JSON_TRUE: return xmmsv_new_int (1); case JSON_FALSE: return xmmsv_new_int (0); default: return xmmsv_new_error ("Unknown data type."); } }
/* Converts an S4 resultset into an xmmsv_t, based on the fetch specification */ xmmsv_t * xmms_medialib_query_to_xmmsv (s4_resultset_t *set, xmms_fetch_spec_t *spec) { GHashTable *set_table; GList *sets; xmmsv_t *val, *ret = NULL; gint i; switch (spec->type) { case FETCH_COUNT: ret = xmmsv_new_int (s4_resultset_get_rowcount (set)); break; case FETCH_METADATA: ret = metadata_to_xmmsv (set, spec); break; case FETCH_ORGANIZE: ret = xmmsv_new_dict (); for (i = 0; i < spec->data.organize.count; i++) { val = xmms_medialib_query_to_xmmsv (set, spec->data.organize.data[i]); if (val != NULL) { xmmsv_dict_set (ret, spec->data.organize.keys[i], val); xmmsv_unref (val); } } break; case FETCH_CLUSTER_LIST: sets = cluster_list (set, spec); ret = xmmsv_new_list (); for (; sets != NULL; sets = g_list_delete_link (sets, sets)) { set = sets->data; val = xmms_medialib_query_to_xmmsv (set, spec->data.cluster.data); if (val != NULL) { xmmsv_list_append (ret, val); xmmsv_unref (val); } s4_resultset_free (set); } break; case FETCH_CLUSTER_DICT: set_table = cluster_dict (set, spec); ret = convert_ghashtable_to_xmmsv (set_table, spec->data.cluster.data); g_hash_table_destroy (set_table); break; default: g_assert_not_reached (); } return ret; }
/** * Return a new value object which is a deep copy of the input value * * @param val #xmmsv_t to copy. * @return 1 the address to the new copy of the value. */ xmmsv_t * xmmsv_copy (xmmsv_t *val) { xmmsv_t *cur_val = NULL; xmmsv_type_t type; int64_t i; const char *s; float f; x_return_val_if_fail (val, 0); type = xmmsv_get_type (val); switch (type) { case XMMSV_TYPE_DICT: cur_val = duplicate_dict_value (val); break; case XMMSV_TYPE_LIST: cur_val = duplicate_list_value (val); break; case XMMSV_TYPE_INT64: xmmsv_get_int (val, &i); cur_val = xmmsv_new_int (i); break; case XMMSV_TYPE_FLOAT: xmmsv_get_float (val, &f); cur_val = xmmsv_new_float (f); break; case XMMSV_TYPE_STRING: xmmsv_get_string (val, &s); cur_val = xmmsv_new_string (s); break; case XMMSV_TYPE_ERROR: xmmsv_get_error (val, &s); cur_val = xmmsv_new_error (s); break; case XMMSV_TYPE_COLL: cur_val = duplicate_coll_value (val); break; case XMMSV_TYPE_BIN: cur_val = xmmsv_new_bin (val->value.bin.data, val->value.bin.len); break; case XMMSV_TYPE_BITBUFFER: cur_val = xmmsv_new_bitbuffer (); xmmsv_bitbuffer_put_data (cur_val, val->value.bit.buf, val->value.bit.len / 8); xmmsv_bitbuffer_goto (cur_val, xmmsv_bitbuffer_pos (val)); break; default: cur_val = xmmsv_new_none (); break; } assert (cur_val); return cur_val; }
static xmmsv_t * aggregate_max (xmmsv_t *current, gint int_value, const gchar *str_value) { gint old_value; if (str_value != NULL) { /* 'max' only applies to numbers */ return current; } if (current == NULL) { return xmmsv_new_int (int_value); } xmmsv_get_int (current, &old_value); if (old_value < int_value) { return xmmsv_new_int (int_value); } return current; }
static gboolean kill_server (gpointer object) { xmms_main_t *mainobj = (xmms_main_t *) object; gint uptime = time (NULL) - mainobj->starttime; xmms_object_emit (XMMS_OBJECT (object), XMMS_IPC_SIGNAL_QUIT, xmmsv_new_int (uptime)); xmms_object_unref (object); exit (EXIT_SUCCESS); }
static xmmsv_t * aggregate_first (xmmsv_t *current, gint int_value, const gchar *str_value) { if (current != NULL) { return current; } if (str_value != NULL) { current = xmmsv_new_string (str_value); } else { current = xmmsv_new_int (int_value); } return current; }
static xmmsv_t * aggregate_sum (xmmsv_t *current, gint int_value, const gchar *str_value) { int64_t old_value = 0; if (str_value != NULL) { /* 'sum' only applies to numbers */ return current; } if (current != NULL) { xmmsv_get_int64 (current, &old_value); } return xmmsv_new_int (old_value + int_value); }
/** * This returns the main stats for the server */ static GTree * xmms_main_client_stats (xmms_object_t *object, xmms_error_t *error) { GTree *ret; gint starttime; ret = g_tree_new_full ((GCompareDataFunc) strcmp, NULL, NULL, (GDestroyNotify) xmmsv_unref); starttime = ((xmms_main_t*)object)->starttime; g_tree_insert (ret, (gpointer) "version", xmmsv_new_string (XMMS_VERSION)); g_tree_insert (ret, (gpointer) "uptime", xmmsv_new_int (time (NULL) - starttime)); return ret; }
void xmms_object_emit_f (xmms_object_t *object, guint32 signalid, xmmsv_type_t type, ...) { va_list ap; xmmsv_t *arg; va_start (ap, type); switch (type) { case XMMSV_TYPE_NONE: arg = xmmsv_new_none (); break; case XMMSV_TYPE_INT32: arg = xmmsv_new_int (va_arg (ap, gint32)); break; case XMMSV_TYPE_STRING: arg = xmmsv_new_string (va_arg (ap, gchar *)); break; case XMMSV_TYPE_DICT: arg = xmms_create_xmmsv_dict (va_arg (ap, GTree *)); break; case XMMSV_TYPE_END: default: XMMS_DBG ("OBJECT: trying to emit value of unsupported type (%d)!", (int)type); g_assert_not_reached (); break; } va_end (ap); xmms_object_emit (object, signalid, arg); /* In all cases above, we created a new xmmsv_t, which we * now destroy. * In some cases, those xmmsv_t's are created from GLib objects, * such as GTrees. Here we must not destroy those GLib objects, * because the caller wants to do that. However, the xmmsv_t's * don't hold onto those GLib objects, so unreffing the * xmmsv_t doesn't kill the GLib object. */ xmmsv_unref (arg); }
static gboolean song_changed (void *data) { /* executes in the output thread; NOT the filler thread */ xmms_output_song_changed_arg_t *arg = (xmms_output_song_changed_arg_t *)data; xmms_medialib_entry_t entry; xmms_stream_type_t *type; entry = xmms_xform_entry_get (arg->chain); XMMS_DBG ("Running hotspot! Song changed!! %d", entry); arg->output->played = 0; arg->output->current_entry = entry; type = xmms_xform_outtype_get (arg->chain); if (!xmms_output_format_set (arg->output, type)) { gint fmt, rate, chn; fmt = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_FORMAT); rate = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_SAMPLERATE); chn = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_CHANNELS); XMMS_DBG ("Couldn't set format %s/%d/%d, stopping filler..", xmms_sample_name_get (fmt), rate, chn); xmms_output_filler_state_nolock (arg->output, FILLER_STOP); xmms_ringbuf_set_eos (arg->output->filler_buffer, TRUE); return FALSE; } if (arg->flush) xmms_output_flush (arg->output); xmms_object_emit (XMMS_OBJECT (arg->output), XMMS_IPC_SIGNAL_PLAYBACK_CURRENTID, xmmsv_new_int (entry)); return TRUE; }
static GTree * xmms_volume_map_to_dict (xmms_volume_map_t *vl) { GTree *ret; gint i; ret = g_tree_new_full ((GCompareDataFunc) strcmp, NULL, NULL, (GDestroyNotify) xmmsv_unref); if (!ret) { return NULL; } for (i = 0; i < vl->num_channels; i++) { xmmsv_t *val; val = xmmsv_new_int (vl->values[i]); g_tree_replace (ret, (gpointer) vl->names[i], val); } return ret; }
static gboolean xmms_output_status_set (xmms_output_t *output, gint status) { gboolean ret = TRUE; if (!output->plugin) { XMMS_DBG ("No plugin to set status on.."); return FALSE; } g_mutex_lock (&output->status_mutex); if (output->status != status) { if (status == XMMS_PLAYBACK_STATUS_PAUSE && output->status != XMMS_PLAYBACK_STATUS_PLAY) { XMMS_DBG ("Can only pause from play."); ret = FALSE; } else { output->status = status; if (status == XMMS_PLAYBACK_STATUS_STOP) { xmms_object_unref (output->format); output->format = NULL; } if (!xmms_output_plugin_method_status (output->plugin, output, status)) { xmms_log_error ("Status method returned an error!"); output->status = XMMS_PLAYBACK_STATUS_STOP; ret = FALSE; } xmms_object_emit (XMMS_OBJECT (output), XMMS_IPC_SIGNAL_PLAYBACK_STATUS, xmmsv_new_int (output->status)); } } g_mutex_unlock (&output->status_mutex); return ret; }
xmmsv_t * xmms_medialib_entry_property_get_value (xmms_medialib_session_t *session, xmms_medialib_entry_t id_num, const gchar *property) { xmmsv_t *ret = NULL; s4_val_t *prop; const gchar *s; gint32 i; prop = xmms_medialib_entry_property_get (session, id_num, property); if (prop == NULL) return NULL; if (s4_val_get_str (prop, &s)) { ret = xmmsv_new_string (s); } else if (s4_val_get_int (prop, &i)) { ret = xmmsv_new_int (i); } s4_val_free (prop); return ret; }
static void __int_xmms_cmd_get_id (xmms_object_t *object, xmms_object_cmd_arg_t *arg) { xmmsv_t *t; if (xmmsv_list_get_size (arg->args) != 1) { XMMS_DBG ("Wrong number of arguments to get_id (%d)", xmmsv_list_get_size (arg->args)); xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Wrong number of arguments to get_id"); return; } const char * argval0; if (!xmmsv_list_get (arg->args, 0, &t)) { XMMS_DBG ("Missing arg 0 in get_id"); xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Missing arg 0 in get_id"); return; } if (!xmmsv_get_string (t, &argval0)) { XMMS_DBG ("Error parsing arg 0 in get_id"); xmms_error_set (&arg->error, XMMS_ERROR_INVAL, "Error parsing arg 0 in get_id"); return; } arg->retval = xmmsv_new_int (xmms_medialib_client_get_id ((xmms_medialib_t *) object, argval0, &arg->error)); }
static bool _internal_get_from_bb_value_of_type_alloc (xmmsv_t *bb, xmmsv_type_t type, xmmsv_t **val) { int32_t i; uint32_t len; char *s; xmmsv_coll_t *c; unsigned char *d; switch (type) { case XMMSV_TYPE_ERROR: if (!_internal_get_from_bb_error_alloc (bb, &s, &len)) { return false; } *val = xmmsv_new_error (s); free (s); break; case XMMSV_TYPE_INT32: if (!_internal_get_from_bb_int32 (bb, &i)) { return false; } *val = xmmsv_new_int (i); break; case XMMSV_TYPE_STRING: if (!_internal_get_from_bb_string_alloc (bb, &s, &len)) { return false; } *val = xmmsv_new_string (s); free (s); break; case XMMSV_TYPE_DICT: if (!xmmsc_deserialize_dict (bb, val)) { return false; } break; case XMMSV_TYPE_LIST : if (!xmmsc_deserialize_list (bb, val)) { return false; } break; case XMMSV_TYPE_COLL: if (!_internal_get_from_bb_collection_alloc (bb, &c)) { return false; } *val = xmmsv_new_coll (c); xmmsv_coll_unref (c); break; case XMMSV_TYPE_BIN: if (!_internal_get_from_bb_bin_alloc (bb, &d, &len)) { return false; } *val = xmmsv_new_bin (d, len); free (d); break; case XMMSV_TYPE_NONE: *val = xmmsv_new_none (); break; default: x_internal_error ("Got message of unknown type!"); return false; } return true; }
void xmms_xform_auxdata_set_int (xmms_xform_t *xform, const char *key, int intval) { xmmsv_t *val = xmmsv_new_int (intval); xmms_xform_auxdata_set_val (xform, g_strdup (key), val); }