summaryrefslogtreecommitdiff
path: root/src/plugins/media-export/rygel-media-export-dvd-container.vala
blob: 44f64900226b26ad28613c48a165b7586e4b00ef (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
137
138
139
140
/*
 * Copyright (C) 2015 Jens Georg <mail@jensge.org>.
 *
 * 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 Rygel;
using Gee;

internal class Rygel.MediaExport.DVDContainer : SimpleContainer, UpdatableObject {
    public new const string UPNP_CLASS = MediaContainer.PLAYLIST + ".DVD";
    public const string PREFIX = "dvd";
    public const string TRACK_PREFIX = "dvd-track";

    public string path { get; construct set; }

    private GUPnP.XMLDoc doc;

    public DVDContainer (string          id,
                         MediaContainer? parent,
                         string          title,
                         string          path) {
        Object (id : id,
                upnp_class : DVDContainer.UPNP_CLASS,
                title : title,
                parent : parent,
                child_count : 0,
                path : path);
    }

    public override void constructed () {
        base.constructed ();

        this.add_uri (File.new_for_path (path).get_uri ());

        var cache_path = this.get_cache_path (this.path);
        var doc = Xml.Parser.read_file (cache_path,
                                        null,
                                        Xml.ParserOption.NOERROR |
                                        Xml.ParserOption.NOWARNING |
                                        Xml.ParserOption.NOBLANKS |
                                        Xml.ParserOption.RECOVER |
                                        Xml.ParserOption.NOENT |
                                        Xml.ParserOption.NONET);
        this.doc = new GUPnP.XMLDoc (doc);

        var context = new Xml.XPath.Context (this.doc.get_doc ());
        var xpo = context.eval ("/lsdvd/track");
        if (xpo->type != Xml.XPath.ObjectType.NODESET) {
            warning ("No tracks found in DVD");
        } else {
            for (int i = 0; i < xpo->nodesetval->length (); i++) {
                var node = xpo->nodesetval->item (i);
                var item = this.get_item_for_xml (i, node);
                this.add_child_item (item);
            }
        }

        delete xpo;
    }

    public override async MediaObject? find_object (string id,
                                                    Cancellable? cancellable)
                                                    throws Error {
        if (!id.has_prefix (DVDContainer.TRACK_PREFIX)) {
            return null;
        }

        var parts = id.split (":");
        var track = int.parse (parts[2]);
        var context = new Xml.XPath.Context (this.doc.get_doc ());
        var xpo = context.eval ("/lsdvd/track");
        if (!(xpo->type == Xml.XPath.ObjectType.NODESET &&
              xpo->nodesetval->length () >= track)) {
            delete xpo;

            warning ("No track %s in DVD", parts[2]);

            return null;
        }

        var object = this.get_item_for_xml (int.parse (parts[2]),
                                            xpo->nodesetval->item (track));
        delete xpo;

        return object;
    }

    private string get_cache_path (string image_path) {
        unowned string user_cache = Environment.get_user_cache_dir ();
        var id = Checksum.compute_for_string (ChecksumType.MD5, image_path);
        var cache_folder = Path.build_filename (user_cache,
                                                "rygel",
                                                "dvd-content");
        DirUtils.create_with_parents (cache_folder, 0700);
        return Path.build_filename (cache_folder, id);
    }

    public async void commit () throws Error {
        yield this.commit_custom (true);
    }

    public async void commit_custom (bool override_guarded) throws Error {
        MediaCache.get_default ().save_container (this);
    }

    private string get_track_id (int track) {
        var parts = this.id.split (":");

        parts[0] = "dvd-track";
        parts += track.to_string ();

        return string.joinv (":", parts);
    }

    private MediaFileItem get_item_for_xml (int track, Xml.Node *node) {
        var item = new DVDTrack (this.get_track_id (track),
                                 this,
                                 _("Title %d").printf (track + 1),
                                 track,
                                 node);
        item.parent_ref = this;

        return item;
    }
}