summaryrefslogtreecommitdiff
path: root/src/librygel-server/rygel-dlna-available-seek-response.vala
blob: c262d30e703fc007a076e620a6fc082fa3be5a7d (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
/*
 * Copyright (C) 2014  Cable Television Laboratories, Inc.
 * Contact: http://www.cablelabs.com/
 *
 * Author: Craig Pratt <craig@ecaspia.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.1 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

public class Rygel.DLNAAvailableSeekRangeResponse : Rygel.HTTPResponseElement {
    public const string AVAILABLE_SEEK_RANGE_HEADER = "availableSeekRange.dlna.org";
    /**
     * The Limited Operation mode (0 or 1)
     */
    public int mode { get; private set; }

    /**
     * Available range start time, in microseconds
     */
    public int64 start_time { get; private set; }

    /**
     * Available range end time, in microseconds
     */
    public int64 end_time { get; private set; }

    /**
     * The start of the available range in bytes
     */
    public int64 start_byte { get; private set; }

    /**
     * The end of the available range in bytes (inclusive)
     */
    public int64 end_byte { get; private set; }

    /**
     * The length of the available range in bytes
     */
    public int64 range_length { get; private set; }

    public DLNAAvailableSeekRangeResponse (int mode,
                                           int64 start_time,
                                           int64 end_time,
                                           int64 start_byte,
                                           int64 end_byte) {
        base ();
        this.mode = mode;
        this.start_time = start_time;
        this.end_time = end_time;
        this.start_byte = start_byte;
        this.end_byte = end_byte;
        this.range_length = end_byte - start_byte + 1;
    }

    public DLNAAvailableSeekRangeResponse.time_only (int mode,
                                                     int64 start_time,
                                                     int64 end_time) {
        base ();
        this.mode = mode;
        this.start_time = start_time;
        this.end_time = end_time;
        this.start_byte = this.end_byte = this.range_length = UNSPECIFIED;
    }

    public override void add_response_headers (Rygel.HTTPRequest request) {
        var response = this.get_response_string ();
        if (response != null) {
            request.msg.response_headers.append (AVAILABLE_SEEK_RANGE_HEADER,
                                                 response);
        }
    }

    private string? get_response_string () {
        if (start_time == UNSPECIFIED) {
            return null;
        }

        // The availableSeekRange format:
        //
        // availableSeekRange.dlna.org:
        // MODE npt=START_TIME-END_TIME bytes=START_BYTE-END_BYTE
        //
        // The MODE can be either "0" or "1", indicating the limited operation
        // mode being used by the server.
        //
        // The "bytes=" field can be ommitted in some cases. (e.g. ORG_OP
        // b-val==0 and lop-bytes is 0).

        // It's not our job at this level to enforce all the semantics of the
        // availableSeekRange response, as we don't have enough context.
        // Setting up the correct HTTPTimeSeekRequest object is the
        // responsibility of the object owner. To form the response, we just
        // use what is set.

        var response = new StringBuilder ();
        response.append (mode.to_string ());
        response.append (" npt=");
        response.append_printf ("%.3f-",
                                (double) this.start_time / TimeSpan.SECOND);
        response.append_printf ("%.3f",
                                (double) this.end_time / TimeSpan.SECOND);

        if (this.start_byte != UNSPECIFIED) {
            response.append (" bytes=");
            response.append (this.start_byte.to_string ());
            response.append ("-");
            response.append (this.end_byte.to_string ());
        }

        return response.str;
   }

    public override string to_string () {
        return ("HTTPTimeSeekResponse (%s)".printf
                                        (this.get_response_string ()));
    }
}