~ubuntu-branches/ubuntu/precise/libdmapsharing/precise

« back to all changes in this revision

Viewing changes to libdmapsharing/dmap-share.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2010-11-24 17:25:41 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20101124172541-8vv04lkovg5gt9vk
Tags: 2.1.12-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
91
91
        GHashTable *session_ids;
92
92
};
93
93
 
 
94
/* FIXME: name this something else, as it is more than just share/bitwise now */
94
95
struct share_bitwise_t {
95
96
        DMAPShare *share;
96
97
        bitwise bits;
97
98
        GSList *id_list;
 
99
 
 
100
        /* FIXME: ick, void * is DMAPDDb * or GHashTable * 
 
101
         * in next two fields:*/
 
102
        void *db;
 
103
        DMAPRecord *(*lookup_by_id) (void *db, guint id);
 
104
 
 
105
        void (*destroy) (void *);
98
106
};
99
107
 
100
108
static void dmap_share_init       (DMAPShare *share);
1480
1488
}
1481
1489
 
1482
1490
static void
1483
 
write_daap_preamble (SoupMessage *message, GNode *node)
 
1491
write_dmap_preamble (SoupMessage *message, GNode *node)
1484
1492
{
1485
1493
        guint length;
1486
1494
        gchar *data = dmap_structure_serialize (node, &length);
1498
1506
                g_debug ("No more ID's, sending message complete.");
1499
1507
                soup_message_body_complete (message->response_body);
1500
1508
        } else {
1501
 
                gchar *data;
 
1509
                gchar *data = NULL;
1502
1510
                guint length;
1503
1511
                DMAPRecord *record;
1504
1512
                struct MLCL_Bits mb = {NULL,0};
1505
1513
 
1506
 
                record = dmap_db_lookup_by_id (share_bitwise->share->priv->db, GPOINTER_TO_UINT (share_bitwise->id_list->data));
 
1514
                record = share_bitwise->lookup_by_id (share_bitwise->db, GPOINTER_TO_UINT (share_bitwise->id_list->data));
1507
1515
 
1508
1516
                mb.bits = share_bitwise->bits;
1509
1517
                mb.mlcl = dmap_structure_add (NULL, DMAP_CC_MLCL);
1530
1538
chunked_message_finished (SoupMessage *message, struct share_bitwise_t *share_bitwise)
1531
1539
{
1532
1540
        g_debug ("Finished sending chunked data.");
 
1541
        if (share_bitwise->destroy)
 
1542
                share_bitwise->destroy (share_bitwise->db);
1533
1543
        g_free (share_bitwise);
1534
1544
}
1535
1545
 
 
1546
DMAPRecord *
 
1547
g_hash_table_lookup_adapter (GHashTable *ht, guint id)
 
1548
{
 
1549
        /* NOTE: each time this is called by write_next_mlit(), the
 
1550
         * returned value will be unref'ed by write_next_mlit(). We
 
1551
         * also need to destroy the GHashTable, so bump up the reference
 
1552
         * count so that both can happen. */
 
1553
        return g_object_ref (g_hash_table_lookup (ht, GUINT_TO_POINTER (id)));
 
1554
}
 
1555
 
1536
1556
void
1537
1557
_dmap_share_databases (DMAPShare *share,
1538
1558
                       SoupServer        *server,
1691
1711
                struct DMAPMetaDataMap *map;
1692
1712
                gint32 num_songs;
1693
1713
                struct MLCL_Bits mb = {NULL,0};
 
1714
                struct share_bitwise_t *share_bitwise;
1694
1715
 
1695
1716
                record_query = g_hash_table_lookup (query, "query");
1696
1717
                if (record_query) {
1707
1728
                map = DMAP_SHARE_GET_CLASS (share)->get_meta_data_map (share);
1708
1729
                mb.bits = _dmap_share_parse_meta (query, map);
1709
1730
 
 
1731
                /* NOTE:
 
1732
                 * We previously simply called foreach...add_entry_to_mlcl and later serialized the entire
 
1733
                 * structure. This has the disadvantage that the entire response must be in memory before
 
1734
                 * libsoup sends it to the client.
 
1735
                 *
 
1736
                 * Now, we go through the database in multiple passes (as an interim solution):
 
1737
                 *
 
1738
                 * 1. Accumulate the eventual size of the MLCL by creating and then free'ing each MLIT.
 
1739
                 * 2. Generate the DAAP preamble ending with the MLCL (with size fudged for ADBS and MLCL).
 
1740
                 * 3. Setup libsoup response headers, etc.
 
1741
                 * 4. Setup callback to transmit DAAP preamble (write_dmap_preamble)
 
1742
                 * 5. Setup callback to transmit MLIT's (write_next_mlit)
 
1743
                 */
 
1744
 
 
1745
                /* 1: */
 
1746
                /* FIXME: user_data1/2 is ugly: */
 
1747
                guint32 size = 0;
 
1748
                mb.user_data1 = &size;
 
1749
                mb.user_data2 = share;
 
1750
 
 
1751
                share_bitwise = g_new (struct share_bitwise_t, 1);
 
1752
                share_bitwise->share = share;
 
1753
                share_bitwise->bits = mb.bits;
 
1754
                share_bitwise->id_list = NULL;
 
1755
                if (record_query) {
 
1756
                        share_bitwise->db = records;
 
1757
                        share_bitwise->lookup_by_id = g_hash_table_lookup_adapter;
 
1758
                        share_bitwise->destroy = g_hash_table_destroy;
 
1759
                        g_hash_table_foreach (records, (GHFunc) accumulate_ids, &(share_bitwise->id_list));
 
1760
                        g_hash_table_foreach (records, (GHFunc) accumulate_mlcl_size, &mb);
 
1761
                } else {
 
1762
                        share_bitwise->db = share->priv->db;
 
1763
                        share_bitwise->lookup_by_id = dmap_db_lookup_by_id;
 
1764
                        share_bitwise->destroy = NULL;
 
1765
                        dmap_db_foreach (share->priv->db, (GHFunc) accumulate_ids, &(share_bitwise->id_list));
 
1766
                        dmap_db_foreach (share->priv->db, (GHFunc) accumulate_mlcl_size, &mb);
 
1767
                }
 
1768
 
 
1769
                /* 2: */
1710
1770
                adbs = dmap_structure_add (NULL, DMAP_CC_ADBS);
1711
1771
                dmap_structure_add (adbs, DMAP_CC_MSTT, (gint32) DMAP_STATUS_OK);
1712
1772
                dmap_structure_add (adbs, DMAP_CC_MUTY, 0);
1713
1773
                dmap_structure_add (adbs, DMAP_CC_MTCO, (gint32) num_songs);
1714
1774
                dmap_structure_add (adbs, DMAP_CC_MRCO, (gint32) num_songs);
1715
 
 
1716
 
                if (record_query) {
1717
 
                        /* NOTE: still uses old technique: */
1718
 
                        mb.mlcl = dmap_structure_add (adbs, DMAP_CC_MLCL); // Was shared with else before
1719
 
                        g_hash_table_foreach (records, (GHFunc) DMAP_SHARE_GET_CLASS (share)->add_entry_to_mlcl, &mb);
1720
 
                        g_hash_table_destroy (records);
1721
 
                        _dmap_share_message_set_from_dmap_structure (share, message, adbs); // Was shared with else before
1722
 
                        dmap_structure_destroy (adbs); // Was shared with else before
1723
 
                } else {
1724
 
                        /* NOTE:
1725
 
                         * We previously simply called foreach...add_entry_to_mlcl and later serialized the entire
1726
 
                         * structure. This has the disadvantage that the entire response must be in memory before
1727
 
                         * libsoup sends it to the client.
1728
 
                         *
1729
 
                         * Now, we go through the database in multiple passes (as an interim solution):
1730
 
                         *
1731
 
                         * 1. Accumulate the eventual size of the MLCL by creating and then free'ing each MLIT.
1732
 
                         * 2. Generate the DAAP preamble ending with the MLCL (with size fudged for ADBS and MLCL).
1733
 
                         * 3. Setup libsoup response headers, etc.
1734
 
                         * 4. Setup callback to transmit DAAP preamble (write_daap_preamble)
1735
 
                         * 5. Setup callback to transmit MLIT's (write_next_mlit)
1736
 
                         *    NOTE: write_next_mlit uses some tricks to iterate through all record ID's
1737
 
                         */
1738
 
 
1739
 
                        struct share_bitwise_t *share_bitwise;
1740
 
 
1741
 
                        /* 1: */
1742
 
                        /* FIXME: user_data1/2 is ugly: */
1743
 
                        guint32 size = 0;
1744
 
                        mb.user_data1 = &size;
1745
 
                        mb.user_data2 = share;
1746
 
                        dmap_db_foreach (share->priv->db, (GHFunc) accumulate_mlcl_size, &mb);
1747
 
 
1748
 
                        /* 2: */
1749
 
                        mb.mlcl = dmap_structure_add (adbs, DMAP_CC_MLCL);
1750
 
                        dmap_structure_increase_by_predicted_size (adbs, size);
1751
 
                        dmap_structure_increase_by_predicted_size (mb.mlcl, size);
1752
 
 
1753
 
                        /* 3: */
1754
 
                        soup_message_set_status (message, SOUP_STATUS_OK);
1755
 
                        soup_message_headers_set_content_length (message->response_headers, dmap_structure_get_size(adbs));
1756
 
                        /* Free memory after each chunk sent out over network. */
1757
 
                        soup_message_body_set_accumulate (message->response_body, FALSE);
1758
 
 
1759
 
                        soup_message_headers_append (message->response_headers, "Content-Type", "application/x-daap-tagged");
1760
 
                        DMAP_SHARE_GET_CLASS (share)->message_add_standard_headers (share, message);
1761
 
 
1762
 
                        /* 4: */
1763
 
                        g_signal_connect (message, "wrote_headers", G_CALLBACK (write_daap_preamble), adbs);
1764
 
 
1765
 
                        /* 5: */
1766
 
                        share_bitwise = g_new (struct share_bitwise_t, 1);
1767
 
                        share_bitwise->share = share;
1768
 
                        share_bitwise->bits = mb.bits;
1769
 
                        share_bitwise->id_list = NULL;
1770
 
                        dmap_db_foreach (share->priv->db, (GHFunc) accumulate_ids, &(share_bitwise->id_list));
1771
 
                        g_signal_connect (message, "wrote_chunk", G_CALLBACK (write_next_mlit), share_bitwise);
1772
 
                        g_signal_connect (message, "finished", G_CALLBACK (chunked_message_finished), share_bitwise);
1773
 
                }
 
1775
                mb.mlcl = dmap_structure_add (adbs, DMAP_CC_MLCL);
 
1776
                dmap_structure_increase_by_predicted_size (adbs, size);
 
1777
                dmap_structure_increase_by_predicted_size (mb.mlcl, size);
 
1778
 
 
1779
                /* 3: */
 
1780
                /* Free memory after each chunk sent out over network. */
 
1781
                soup_message_body_set_accumulate (message->response_body, FALSE);
 
1782
                soup_message_headers_append (message->response_headers, "Content-Type", "application/x-dmap-tagged");
 
1783
                DMAP_SHARE_GET_CLASS (share)->message_add_standard_headers (share, message);
 
1784
                soup_message_headers_set_content_length (message->response_headers, dmap_structure_get_size(adbs));
 
1785
                soup_message_set_status (message, SOUP_STATUS_OK);
 
1786
 
 
1787
                /* 4: */
 
1788
                g_signal_connect (message, "wrote_headers", G_CALLBACK (write_dmap_preamble), adbs);
 
1789
 
 
1790
                /* 5: */
 
1791
                g_signal_connect (message, "wrote_chunk", G_CALLBACK (write_next_mlit), share_bitwise);
 
1792
                g_signal_connect (message, "finished", G_CALLBACK (chunked_message_finished), share_bitwise);
1774
1793
 
1775
1794
        } else if (g_ascii_strcasecmp ("/1/containers", rest_of_path) == 0) {
1776
1795
        /* APLY database playlists