summaryrefslogtreecommitdiff
path: root/src/librygel-server/rygel-browse.vala
blob: a3cadfaaa7f8a7783f805cbe3d4e4e6720f45f19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2008 Zeeshan Ali <zeenix@gmail.com>.
 * Copyright (C) 2007 OpenedHand Ltd.
 *
 * Author: Zeeshan Ali <zeenix@gmail.com>
 *         Jorn Baayen <jorn@openedhand.com>
 *
 * This file is part of Rygel.
 *
 * Rygel is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Rygel is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

using GUPnP;
using Gee;
using Soup;

/**
 * Browse action implementation. This class is more or less the state-machine
 * associated with the Browse action handling that exists to make asynchronous
 * handling of Browse action possible.
 */
internal class Rygel.Browse: Rygel.MediaQueryAction {
    // The media object corresponding to object_id
    private bool fetch_metadata;

    public Browse (ContentDirectory    content_dir,
                   owned ServiceAction action) {
        base (content_dir, action);

        if (this.hacks != null) {
            this.object_id_arg = this.hacks.object_id;
        } else {
            this.object_id_arg = "ObjectID";
        }
    }

    protected override void parse_args () throws Error {
        base.parse_args ();

        this.action.get ("BrowseFlag", typeof (string), out this.browse_flag);

        /* BrowseFlag */
        if (this.browse_flag != null &&
            this.browse_flag == "BrowseDirectChildren") {
            this.fetch_metadata = false;
        } else if (this.browse_flag != null &&
                   this.browse_flag == "BrowseMetadata") {
            this.fetch_metadata = true;
        } else {
            throw new ContentDirectoryError.INVALID_ARGS
                                        (_("Invalid Arguments"));
        }
    }

    protected override async MediaObjects fetch_results
                                        (MediaObject media_object)
                                         throws Error {
        if (this.fetch_metadata) {
            // BrowseMetadata
            return this.handle_metadata_request (media_object);
        } else {
            // BrowseDirectChildren
            return yield this.handle_children_request (media_object);
        }
    }

    private MediaObjects handle_metadata_request (MediaObject media_object)
                                                  throws Error {
        this.total_matches = 1;

        var results = new MediaObjects ();
        results.add (media_object);

        return results;
    }

    private async MediaObjects handle_children_request
                                        (MediaObject media_object)
                                         throws Error {
        if (!(media_object is MediaContainer)) {
            throw new ContentDirectoryError.INVALID_ARGS
                                        (_("Cannot browse children on item"));
        }

        var container = (MediaContainer) media_object;
        if (container.child_count < int.MAX) {
            this.total_matches = container.child_count;
        } else {
            this.total_matches = 0;
        }

        if (this.requested_count == 0) {
            // No max count requested, try to fetch all children
            this.requested_count = this.total_matches;
        }

        debug ("Fetching %u children of container '%s' from index %u..",
               this.requested_count,
               this.object_id,
               this.index);

        var sort_criteria = this.sort_criteria ?? container.sort_criteria;

        var children = yield container.get_children (this.index,
                                                     this.requested_count,
                                                     sort_criteria,
                                                     this.cancellable);

        debug ("Fetched %u children of container '%s' from index %u.",
               this.requested_count,
               this.object_id,
               this.index);

        return children;
    }

    protected override void handle_error (Error error) {
        warning (_("Failed to browse '%s': %s\n"),
                 this.object_id,
                 error.message);

        base.handle_error (error);
    }
}