void dpap_share_server_info (DMAPShare * share, SoupServer * server, SoupMessage * message, const char *path, GHashTable * query, SoupClientContext * context) { /* MSRV server info response * MSTT status * MPRO dpap version * PPRO dpap version * MINM name * MSAU authentication method * MSLR login required * MSTM timeout interval * MSAL supports auto logout * MSUP supports update * MSPI supports persistent ids * MSEX supports extensions * MSBR supports browse * MSQY supports query * MSIX supports index * MSRS supports resolve * MSDC databases count */ gchar *nameprop; GNode *msrv; g_debug ("Path is %s.", path); g_object_get ((gpointer) share, "name", &nameprop, NULL); msrv = dmap_structure_add (NULL, DMAP_CC_MSRV); dmap_structure_add (msrv, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK); dmap_structure_add (msrv, DMAP_CC_MPRO, (gdouble) DMAP_VERSION); dmap_structure_add (msrv, DMAP_CC_PPRO, (gdouble) DPAP_VERSION); dmap_structure_add (msrv, DMAP_CC_MINM, nameprop); /*dmap_structure_add (msrv, DMAP_CC_MSAU, _dmap_share_get_auth_method (share)); */ /* authentication method * 0 is nothing * 1 is name & password * 2 is password only */ dmap_structure_add (msrv, DMAP_CC_MSLR, 0); dmap_structure_add (msrv, DMAP_CC_MSTM, (gint32) DPAP_TIMEOUT); dmap_structure_add (msrv, DMAP_CC_MSAL, (gchar) 0); /*dmap_structure_add (msrv, DMAP_CC_MSUP, (gchar) 1); *dmap_structure_add (msrv, DMAP_CC_MSPI, (gchar) 0); *dmap_structure_add (msrv, DMAP_CC_MSEX, (gchar) 0); *dmap_structure_add (msrv, DMAP_CC_MSBR, (gchar) 0); *dmap_structure_add (msrv, DMAP_CC_MSQY, (gchar) 0); */ dmap_structure_add (msrv, DMAP_CC_MSIX, (gchar) 0); /* dmap_structure_add (msrv, DMAP_CC_MSRS, (gchar) 0); */ dmap_structure_add (msrv, DMAP_CC_MSDC, (gint32) 1); _dmap_share_message_set_from_dmap_structure (share, message, msrv); dmap_structure_destroy (msrv); g_free (nameprop); }
static void add_to_category_listing (gpointer key, gpointer user_data) { GNode *mlit; GNode *node = (GNode *) user_data; mlit = dmap_structure_add (node, DMAP_CC_MLIT); dmap_structure_add (mlit, DMAP_RAW, (char *) key); }
void dacp_share_ctrl_int (DMAPShare * share, SoupServer * server, SoupMessage * message, const char *path, GHashTable * query, SoupClientContext * context) { const char *rest_of_path; DACPShare *dacp_share = DACP_SHARE (share); g_debug ("Path is %s.", path); if (query) { g_hash_table_foreach (query, debug_param, NULL); } rest_of_path = strchr (path + 1, '/'); /* If calling /ctrl-int without args, the client doesnt need a * session-id, otherwise it does and it should be validated. */ if ((rest_of_path != NULL) && (!_dmap_share_session_id_validate (share, context, message, query, NULL))) { soup_message_set_status (message, SOUP_STATUS_FORBIDDEN); return; } if (rest_of_path == NULL) { /* CACI control-int * MSTT status * MUTY update type * MTCO specified total count * MRCO returned count * MLCL listing * MLIT listing item * MIID item id * CMIK Unknown (TRUE) * CMSP Unknown (TRUE) * CMSV Unknown (TRUE) * CASS Unknown (TRUE) * CASU Unknown (TRUE) * CASG Unknown (TRUE) */ GNode *caci; GNode *mlcl; GNode *mlit; // dacp.controlint caci = dmap_structure_add (NULL, DMAP_CC_CACI); // dmap.status dmap_structure_add (caci, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK); // dmap.updatetype dmap_structure_add (caci, DMAP_CC_MUTY, 0); // dmap.specifiedtotalcount dmap_structure_add (caci, DMAP_CC_MTCO, (gint32) 1); // dmap.returnedcount dmap_structure_add (caci, DMAP_CC_MRCO, (gint32) 1); // dmap.listing mlcl = dmap_structure_add (caci, DMAP_CC_MLCL); // dmap.listingitem mlit = dmap_structure_add (mlcl, DMAP_CC_MLIT); // dmap.itemid dmap_structure_add (mlit, DMAP_CC_MIID, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CMIK, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CMSP, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CMSV, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CASS, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CASU, (gint32) 1); // Unknown (TRUE) dmap_structure_add (mlit, DMAP_CC_CASG, (gint32) 1); _dmap_share_message_set_from_dmap_structure (share, message, caci); dmap_structure_destroy (caci); } else if (g_ascii_strcasecmp ("/1/getproperty", rest_of_path) == 0) { gchar *properties_query, **properties, **property; GNode *cmgt; properties_query = g_hash_table_lookup (query, "properties"); if (!properties_query) { g_warning ("No property specified"); return; } cmgt = dmap_structure_add (NULL, DMAP_CC_CMGT); dmap_structure_add (cmgt, DMAP_CC_MSTT, DMAP_STATUS_OK); properties = g_strsplit (properties_query, ",", -1); for (property = properties; *property; property++) { if (g_ascii_strcasecmp (*property, "dmcp.volume") == 0) { gulong volume; g_object_get (dacp_share->priv->player, "volume", &volume, NULL); //g_debug ("Sending volume: %lu", volume); dmap_structure_add (cmgt, DMAP_CC_CMVO, volume); } else { g_warning ("Unhandled property %s", *property); } } g_strfreev (properties); _dmap_share_message_set_from_dmap_structure (share, message, cmgt); dmap_structure_destroy (cmgt); } else if (g_ascii_strcasecmp ("/1/setproperty", rest_of_path) == 0) { if (g_hash_table_lookup (query, "dmcp.volume")) { gdouble volume = strtod (g_hash_table_lookup (query, "dmcp.volume"), NULL); g_object_set (dacp_share->priv->player, "volume", (gulong) volume, NULL); } soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("/1/getspeakers", rest_of_path) == 0) { GNode *casp; casp = dmap_structure_add (NULL, DMAP_CC_CASP); dmap_structure_add (casp, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK); dmap_structure_add (casp, DMAP_CC_MDCL); dmap_structure_add (casp, DMAP_CC_CAIA, TRUE); dmap_structure_add (casp, DMAP_CC_MINM, "Computer"); dmap_structure_add (casp, DMAP_CC_MSMA, (gint32) 0); _dmap_share_message_set_from_dmap_structure (share, message, casp); dmap_structure_destroy (casp); } else if (g_ascii_strcasecmp ("/1/playstatusupdate", rest_of_path) == 0) { gchar *revision = g_hash_table_lookup (query, "revision-number"); gint revision_number = atoi (revision); if (revision_number >= dacp_share->priv->current_revision) { g_object_ref (message); dacp_share->priv->update_queue = g_slist_prepend (dacp_share-> priv->update_queue, message); g_signal_connect_object (message, "finished", G_CALLBACK (status_update_message_finished), dacp_share, 0); soup_server_pause_message (server, message); } else { dacp_share_fill_playstatusupdate (dacp_share, message); } } else if (g_ascii_strcasecmp ("/1/playpause", rest_of_path) == 0) { dacp_player_play_pause (dacp_share->priv->player); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("/1/pause", rest_of_path) == 0) { dacp_player_pause (dacp_share->priv->player); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("/1/nextitem", rest_of_path) == 0) { dacp_player_next_item (dacp_share->priv->player); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("/1/previtem", rest_of_path) == 0) { dacp_player_prev_item (dacp_share->priv->player); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("/1/nowplayingartwork", rest_of_path) == 0) { guint width = 320; guint height = 320; gchar *artwork_filename; gchar *buffer; gsize buffer_len; if (g_hash_table_lookup (query, "mw")) width = atoi (g_hash_table_lookup (query, "mw")); if (g_hash_table_lookup (query, "mh")) height = atoi (g_hash_table_lookup (query, "mh")); artwork_filename = dacp_player_now_playing_artwork (dacp_share-> priv->player, width, height); if (!artwork_filename) { g_debug ("No artwork for currently playing song"); soup_message_set_status (message, SOUP_STATUS_NOT_FOUND); return; } #ifdef HAVE_GDKPIXBUF GdkPixbuf *artwork = gdk_pixbuf_new_from_file_at_scale (artwork_filename, width, height, TRUE, NULL); if (!artwork) { g_debug ("Error loading image file"); g_free (artwork_filename); soup_message_set_status (message, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } if (!gdk_pixbuf_save_to_buffer (artwork, &buffer, &buffer_len, "png", NULL, NULL)) { g_debug ("Error saving artwork to PNG"); g_object_unref (artwork); g_free (artwork_filename); soup_message_set_status (message, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } g_object_unref (artwork); #else if (!g_file_get_contents (artwork_filename, &buffer, &buffer_len, NULL)) { g_debug ("Error getting artwork data"); g_free (artwork_filename); soup_message_set_status (message, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } #endif g_free (artwork_filename); soup_message_set_status (message, SOUP_STATUS_OK); soup_message_set_response (message, "image/png", SOUP_MEMORY_TAKE, buffer, buffer_len); } else if (g_ascii_strcasecmp ("/1/cue", rest_of_path) == 0) { gchar *command; command = g_hash_table_lookup (query, "command"); if (!command) { g_debug ("No CUE command specified"); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); return; } else if (g_ascii_strcasecmp ("clear", command) == 0) { dacp_player_cue_clear (dacp_share->priv->player); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); } else if (g_ascii_strcasecmp ("play", command) == 0) { GNode *cacr; gchar *record_query; gchar *sort_by; GHashTable *records; GList *sorted_records; GSList *filter_def; DMAPDb *db; gint index = atoi (g_hash_table_lookup (query, "index")); g_object_get (share, "db", &db, NULL); record_query = g_hash_table_lookup (query, "query"); filter_def = _dmap_share_build_filter (record_query); records = dmap_db_apply_filter (db, filter_def); sorted_records = g_hash_table_get_values (records); sort_by = g_hash_table_lookup (query, "sort"); if (g_strcmp0 (sort_by, "album") == 0) { sorted_records = g_list_sort_with_data (sorted_records, (GCompareDataFunc) daap_record_cmp_by_album, db); } else if (sort_by != NULL) { g_warning ("Unknown sort column: %s", sort_by); } dacp_player_cue_play (dacp_share->priv->player, sorted_records, index); g_list_free (sorted_records); g_hash_table_unref (records); dmap_share_free_filter (filter_def); cacr = dmap_structure_add (NULL, DMAP_CC_CACR); dmap_structure_add (cacr, DMAP_CC_MSTT, DMAP_STATUS_OK); dmap_structure_add (cacr, DMAP_CC_MIID, index); _dmap_share_message_set_from_dmap_structure (share, message, cacr); dmap_structure_destroy (cacr); } else { g_warning ("Unhandled cue command: %s", command); soup_message_set_status (message, SOUP_STATUS_NO_CONTENT); return; } } else { g_warning ("Unhandled ctrl-int command: %s", rest_of_path); soup_message_set_status (message, SOUP_STATUS_BAD_REQUEST); } }
static void dacp_share_fill_playstatusupdate (DACPShare * share, SoupMessage * message) { GNode *cmst; DAAPRecord *record; DACPPlayState play_state; DACPRepeatState repeat_state; gboolean shuffle_state; guint playing_time; g_object_get (share->priv->player, "play-state", &play_state, "repeat-state", &repeat_state, "shuffle-state", &shuffle_state, "playing-time", &playing_time, NULL); record = dacp_player_now_playing_record (share->priv->player); cmst = dmap_structure_add (NULL, DMAP_CC_CMST); dmap_structure_add (cmst, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK); dmap_structure_add (cmst, DMAP_CC_CMSR, share->priv->current_revision); dmap_structure_add (cmst, DMAP_CC_CAPS, (gint32) play_state); dmap_structure_add (cmst, DMAP_CC_CASH, shuffle_state ? 1 : 0); dmap_structure_add (cmst, DMAP_CC_CARP, (gint32) repeat_state); if (record) { gchar *title; gchar *artist; gchar *album; gint duration; guint track_time; g_object_get (record, "title", &title, "songartist", &artist, "songalbum", &album, "duration", &duration, NULL); track_time = duration * 1000; //dmap_structure_add (cmst, DMAP_CC_CAVC, 1); dmap_structure_add (cmst, DMAP_CC_CAAS, 2); dmap_structure_add (cmst, DMAP_CC_CAAR, 6); dmap_structure_add (cmst, DMAP_CC_CANP, (gint64) 0); if (title) dmap_structure_add (cmst, DMAP_CC_CANN, title); if (artist) dmap_structure_add (cmst, DMAP_CC_CANA, artist); if (album) dmap_structure_add (cmst, DMAP_CC_CANL, album); dmap_structure_add (cmst, DMAP_CC_CANG, ""); dmap_structure_add (cmst, DMAP_CC_ASAI, 0); //dmap_structure_add (cmst, DMAP_CC_AEMK, 1); g_debug ("Playing time: %u, Track time: %u", playing_time, track_time); dmap_structure_add (cmst, DMAP_CC_CANT, track_time - playing_time); dmap_structure_add (cmst, DMAP_CC_CAST, track_time); g_free (title); g_free (artist); g_free (album); g_object_unref (record); } _dmap_share_message_set_from_dmap_structure (DMAP_SHARE (share), message, cmst); dmap_structure_destroy (cmst); }
static void add_entry_to_mlcl (gpointer id, DMAPRecord * record, gpointer _mb) { GNode *mlit; struct MLCL_Bits *mb = (struct MLCL_Bits *) _mb; mlit = dmap_structure_add (mb->mlcl, DMAP_CC_MLIT); if (_dmap_share_client_requested (mb->bits, ITEM_KIND)) dmap_structure_add (mlit, DMAP_CC_MIKD, (gchar) DPAP_ITEM_KIND_PHOTO); if (_dmap_share_client_requested (mb->bits, ITEM_ID)) dmap_structure_add (mlit, DMAP_CC_MIID, GPOINTER_TO_UINT (id)); if (_dmap_share_client_requested (mb->bits, ITEM_NAME)) { gchar *filename = NULL; g_object_get (record, "filename", &filename, NULL); if (filename) { dmap_structure_add (mlit, DMAP_CC_MINM, filename); g_free (filename); } else g_debug ("Filename requested but not available"); } if (_dmap_share_client_requested (mb->bits, PERSISTENT_ID)) dmap_structure_add (mlit, DMAP_CC_MPER, GPOINTER_TO_UINT (id)); if (TRUE) { /* dpap-sharp claims iPhoto '08 will not show thumbnails without PASP * and this does seem to be the case when testing. */ gchar *aspect_ratio = NULL; g_object_get (record, "aspect-ratio", &aspect_ratio, NULL); if (aspect_ratio) { dmap_structure_add (mlit, DMAP_CC_PASP, aspect_ratio); g_free (aspect_ratio); } else g_debug ("Aspect ratio requested but not available"); } if (_dmap_share_client_requested (mb->bits, PHOTO_CREATIONDATE)) { gint creation_date = 0; g_object_get (record, "creation-date", &creation_date, NULL); dmap_structure_add (mlit, DMAP_CC_PICD, creation_date); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGEFILENAME)) { gchar *filename = NULL; g_object_get (record, "filename", &filename, NULL); if (filename) { dmap_structure_add (mlit, DMAP_CC_PIMF, filename); g_free (filename); } else g_debug ("Filename requested but not available"); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGEFORMAT)) { gchar *format = NULL; g_object_get (record, "format", &format, NULL); if (format) { dmap_structure_add (mlit, DMAP_CC_PFMT, format); g_free (format); } else g_debug ("Format requested but not available"); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGEFILESIZE)) { GByteArray *thumbnail = NULL; g_object_get (record, "thumbnail", &thumbnail, NULL); dmap_structure_add (mlit, DMAP_CC_PIFS, thumbnail ? thumbnail->len : 0); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGELARGEFILESIZE)) { gint large_filesize = 0; g_object_get (record, "large-filesize", &large_filesize, NULL); dmap_structure_add (mlit, DMAP_CC_PLSZ, large_filesize); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGEPIXELHEIGHT)) { gint pixel_height = 0; g_object_get (record, "pixel-height", &pixel_height, NULL); dmap_structure_add (mlit, DMAP_CC_PHGT, pixel_height); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGEPIXELWIDTH)) { gint pixel_width = 0; g_object_get (record, "pixel-width", &pixel_width, NULL); dmap_structure_add (mlit, DMAP_CC_PWTH, pixel_width); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGERATING)) { gint rating = 0; g_object_get (record, "rating", &rating, NULL); dmap_structure_add (mlit, DMAP_CC_PRAT, rating); } if (_dmap_share_client_requested (mb->bits, PHOTO_IMAGECOMMENTS)) { gchar *comments = NULL; g_object_get (record, "comments", &comments, NULL); if (comments) { dmap_structure_add (mlit, DMAP_CC_PCMT, comments); g_free (comments); } else g_debug ("Comments requested but not available"); } if (_dmap_share_client_requested (mb->bits, PHOTO_FILEDATA)) { size_t size = 0; unsigned char *data = NULL; GByteArray *thumbnail = NULL; if (_dmap_share_client_requested (mb->bits, PHOTO_THUMB)) { g_object_get (record, "thumbnail", &thumbnail, NULL); if (thumbnail) { data = thumbnail->data; size = thumbnail->len; } else { data = NULL; size = 0; } } else { /* Should be PHOTO_HIRES */ char *location = NULL; g_object_get (record, "location", &location, NULL); if (mapped_file) { /* Free any previously mapped image */ g_mapped_file_unref (mapped_file); mapped_file = NULL; } mapped_file = file_to_mmap (location); if (mapped_file == NULL) { g_warning ("Error opening %s", location); data = NULL; size = 0; } else { data = (unsigned char *) g_mapped_file_get_contents (mapped_file); size = g_mapped_file_get_length (mapped_file); } g_free (location); } dmap_structure_add (mlit, DMAP_CC_PFDT, data, size); } }
static void databases_browse_xxx (DMAPShare * share, SoupServer * server, SoupMessage * msg, const char *path, GHashTable * query, SoupClientContext * context) { /* ABRO database browse * MSTT status * MUTY update type * MTCO specified total count * MRCO returned count * ABGN genre listing * MLIT listing item * ... */ DMAPDb *db; const gchar *rest_of_path; GNode *abro, *node; gchar *filter; GSList *filter_def; GHashTable *filtered; guint num_genre; const gchar *browse_category; GHashTable *category_items; DMAPContentCode category_cc; GList *values; rest_of_path = strchr (path + 1, '/'); browse_category = rest_of_path + 10; category_items = g_hash_table_new (g_str_hash, g_str_equal); filter = g_hash_table_lookup (query, "filter"); filter_def = _dmap_share_build_filter (filter); g_object_get (share, "db", &db, NULL); filtered = dmap_db_apply_filter (db, filter_def); if (g_ascii_strcasecmp (browse_category, "genres") == 0) { g_hash_table_foreach (filtered, (GHFunc) genre_tabulator, category_items); category_cc = DMAP_CC_ABGN; } else if (g_ascii_strcasecmp (browse_category, "artists") == 0) { g_hash_table_foreach (filtered, (GHFunc) artist_tabulator, category_items); category_cc = DMAP_CC_ABAR; } else if (g_ascii_strcasecmp (browse_category, "albums") == 0) { g_hash_table_foreach (filtered, (GHFunc) album_tabulator, category_items); category_cc = DMAP_CC_ABAL; } else { g_warning ("Unsupported browse category: %s", browse_category); goto _bad_category; } abro = dmap_structure_add (NULL, DMAP_CC_ABRO); dmap_structure_add (abro, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK); dmap_structure_add (abro, DMAP_CC_MUTY, 0); num_genre = g_hash_table_size (category_items); dmap_structure_add (abro, DMAP_CC_MTCO, (gint32) num_genre); dmap_structure_add (abro, DMAP_CC_MRCO, (gint32) num_genre); node = dmap_structure_add (abro, category_cc); values = g_hash_table_get_keys (category_items); if (values && g_hash_table_lookup (query, "include-sort-headers")) { g_debug ("Sorting..."); values = g_list_sort (values, (GCompareFunc) g_ascii_strcasecmp); } g_list_foreach (values, add_to_category_listing, node); g_list_free (values); _dmap_share_message_set_from_dmap_structure (share, msg, abro); dmap_structure_destroy (abro); _bad_category: dmap_share_free_filter (filter_def); /* Free's hash table but not data (points into real DB): */ g_hash_table_destroy (filtered); g_hash_table_destroy (category_items); }
static void add_entry_to_mlcl (gpointer id, DMAPRecord * record, gpointer _mb) { GNode *mlit; gboolean has_video = 0; struct MLCL_Bits *mb = (struct MLCL_Bits *) _mb; mlit = dmap_structure_add (mb->mlcl, DMAP_CC_MLIT); g_object_get (record, "has-video", &has_video, NULL); if (_dmap_share_client_requested (mb->bits, ITEM_KIND)) dmap_structure_add (mlit, DMAP_CC_MIKD, (gchar) DAAP_ITEM_KIND_AUDIO); if (_dmap_share_client_requested (mb->bits, ITEM_ID)) dmap_structure_add (mlit, DMAP_CC_MIID, GPOINTER_TO_UINT (id)); if (_dmap_share_client_requested (mb->bits, ITEM_NAME)) { gchar *title = NULL; g_object_get (record, "title", &title, NULL); if (title) { dmap_structure_add (mlit, DMAP_CC_MINM, title); g_free (title); } else g_debug ("Title requested but not available"); } if (_dmap_share_client_requested (mb->bits, PERSISTENT_ID)) dmap_structure_add (mlit, DMAP_CC_MPER, GPOINTER_TO_UINT (id)); if (_dmap_share_client_requested (mb->bits, CONTAINER_ITEM_ID)) dmap_structure_add (mlit, DMAP_CC_MCTI, GPOINTER_TO_UINT (id)); if (_dmap_share_client_requested (mb->bits, SONG_DATA_KIND)) dmap_structure_add (mlit, DMAP_CC_ASDK, (gchar) DAAP_SONG_DATA_KIND_NONE); /* FIXME: Any use for this? * if (_dmap_share_client_requested (mb->bits, SONG_DATA_URL)) * dmap_structure_add (mlit, DMAP_CC_ASUL, "daap://192.168.0.100:%u/databases/1/items/%d.%s?session-id=%s", data->port, *id, daap_record_get_format (DAAP_RECORD (record)), data->session_id); */ if (_dmap_share_client_requested (mb->bits, SONG_ALBUM)) { gchar *album = NULL; g_object_get (record, "songalbum", &album, NULL); if (album) { dmap_structure_add (mlit, DMAP_CC_ASAL, album); g_free (album); } else g_debug ("Album requested but not available"); } if (_dmap_share_client_requested (mb->bits, SONG_GROUPING)) dmap_structure_add (mlit, DMAP_CC_AGRP, ""); if (_dmap_share_client_requested (mb->bits, SONG_ARTIST)) { gchar *artist = NULL; g_object_get (record, "songartist", &artist, NULL); if (artist) { dmap_structure_add (mlit, DMAP_CC_ASAR, artist); g_free (artist); } else g_debug ("Artist requested but not available"); } if (_dmap_share_client_requested (mb->bits, SONG_BITRATE)) { gint32 bitrate = 0; g_object_get (record, "bitrate", &bitrate, NULL); if (bitrate != 0) dmap_structure_add (mlit, DMAP_CC_ASBR, (gint32) bitrate); } if (_dmap_share_client_requested (mb->bits, SONG_BPM)) dmap_structure_add (mlit, DMAP_CC_ASBT, (gint32) 0); if (_dmap_share_client_requested (mb->bits, SONG_COMMENT)) dmap_structure_add (mlit, DMAP_CC_ASCM, ""); if (_dmap_share_client_requested (mb->bits, SONG_COMPILATION)) dmap_structure_add (mlit, DMAP_CC_ASCO, (gchar) FALSE); if (_dmap_share_client_requested (mb->bits, SONG_COMPOSER)) dmap_structure_add (mlit, DMAP_CC_ASCP, ""); if (_dmap_share_client_requested (mb->bits, SONG_DATE_ADDED)) { gint32 firstseen = 0; g_object_get (record, "firstseen", &firstseen, NULL); dmap_structure_add (mlit, DMAP_CC_ASDA, firstseen); } if (_dmap_share_client_requested (mb->bits, SONG_DATE_MODIFIED)) { gint32 mtime = 0; g_object_get (record, "mtime", &mtime, NULL); dmap_structure_add (mlit, DMAP_CC_ASDM, mtime); } if (_dmap_share_client_requested (mb->bits, SONG_DISC_COUNT)) dmap_structure_add (mlit, DMAP_CC_ASDC, (gint32) 0); if (_dmap_share_client_requested (mb->bits, SONG_DISC_NUMBER)) { gint32 disc = 0; g_object_get (record, "disc", &disc, NULL); dmap_structure_add (mlit, DMAP_CC_ASDN, disc); } if (_dmap_share_client_requested (mb->bits, SONG_DISABLED)) dmap_structure_add (mlit, DMAP_CC_ASDB, (gchar) FALSE); if (_dmap_share_client_requested (mb->bits, SONG_EQ_PRESET)) dmap_structure_add (mlit, DMAP_CC_ASEQ, ""); if (_dmap_share_client_requested (mb->bits, SONG_FORMAT)) { gchar *format = NULL; gchar *transcode_mimetype = NULL; g_object_get (mb->share, "transcode-mimetype", &transcode_mimetype, NULL); // Not presently transcoding videos (see also same comments elsewhere). if (! has_video && transcode_mimetype) { format = g_strdup (dmap_mime_to_format (transcode_mimetype)); g_free (transcode_mimetype); } else { g_object_get (record, "format", &format, NULL); } if (format) { dmap_structure_add (mlit, DMAP_CC_ASFM, format); g_free (format); } else g_debug ("Format requested but not available"); } if (_dmap_share_client_requested (mb->bits, SONG_GENRE)) { gchar *genre = NULL; g_object_get (record, "songgenre", &genre, NULL); if (genre) { dmap_structure_add (mlit, DMAP_CC_ASGN, genre); g_free (genre); } else g_debug ("Genre requested but not available"); } if (_dmap_share_client_requested (mb->bits, SONG_DESCRIPTION)) dmap_structure_add (mlit, DMAP_CC_ASDT, ""); /* FIXME: e.g., wav audio file */ if (_dmap_share_client_requested (mb->bits, SONG_RELATIVE_VOLUME)) dmap_structure_add (mlit, DMAP_CC_ASRV, 0); if (_dmap_share_client_requested (mb->bits, SONG_SAMPLE_RATE)) dmap_structure_add (mlit, DMAP_CC_ASSR, 0); if (_dmap_share_client_requested (mb->bits, SONG_SIZE)) { guint64 filesize = 0; g_object_get (record, "filesize", &filesize, NULL); dmap_structure_add (mlit, DMAP_CC_ASSZ, (gint32) filesize); } if (_dmap_share_client_requested (mb->bits, SONG_START_TIME)) dmap_structure_add (mlit, DMAP_CC_ASST, 0); if (_dmap_share_client_requested (mb->bits, SONG_STOP_TIME)) dmap_structure_add (mlit, DMAP_CC_ASSP, 0); if (_dmap_share_client_requested (mb->bits, SONG_TIME)) { gint32 duration; g_object_get (record, "duration", &duration, NULL); dmap_structure_add (mlit, DMAP_CC_ASTM, (1000 * duration)); } if (_dmap_share_client_requested (mb->bits, SONG_TRACK_COUNT)) dmap_structure_add (mlit, DMAP_CC_ASTC, 0); if (_dmap_share_client_requested (mb->bits, SONG_TRACK_NUMBER)) { gint32 track = 0; g_object_get (record, "track", &track, NULL); dmap_structure_add (mlit, DMAP_CC_ASTN, track); } if (_dmap_share_client_requested (mb->bits, SONG_USER_RATING)) { gint32 rating = 0; g_object_get (record, "rating", &rating, NULL); dmap_structure_add (mlit, DMAP_CC_ASUR, rating); } if (_dmap_share_client_requested (mb->bits, SONG_YEAR)) { gint32 year = 0; g_object_get (record, "year", &year, NULL); dmap_structure_add (mlit, DMAP_CC_ASYR, year); } if (_dmap_share_client_requested (mb->bits, SONG_HAS_VIDEO)) { dmap_structure_add (mlit, DMAP_CC_AEHV, has_video); } if (_dmap_share_client_requested (mb->bits, SONG_SORT_ARTIST)) { gchar *sort_artist = NULL; g_object_get (record, "sort-artist", &sort_artist, NULL); if (sort_artist) { dmap_structure_add (mlit, DMAP_CC_ASSA, sort_artist); g_free (sort_artist); } else { g_debug ("Sort artist requested but not available"); } } if (_dmap_share_client_requested (mb->bits, SONG_SORT_ALBUM)) { gchar *sort_album = NULL; g_object_get (record, "sort-album", &sort_album, NULL); if (sort_album) { dmap_structure_add (mlit, DMAP_CC_ASSU, sort_album); g_free (sort_album); } else { g_debug ("Sort album requested but not available"); } } if (_dmap_share_client_requested (mb->bits, SONG_MEDIAKIND)) { gint mediakind = 0; g_object_get (record, "mediakind", &mediakind, NULL); dmap_structure_add (mlit, DMAP_CC_AEMK, mediakind); } }