~ubuntu-branches/ubuntu/trusty/liquidsoap/trusty

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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
(*****************************************************************************

  Liquidsoap, a programmable stream generator.
  Copyright 2003-2011 Savonet team

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details, fully stated in the COPYING
  file at the root of the liquidsoap distribution.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 *****************************************************************************)

type clock_variable

(** The liveness type of a source indicates whether or not it can
  * fail to broadcast.
  * A Infallible source never fails; it is always ready. *)
type source_t = Fallible | Infallible

(** The [source] use is to send music frames through the [get] method. *)
class virtual source : ?name:string -> Frame.content_kind ->
object

  (** {1 Naming} *)

  (** Identifier of the source. *)
  method id : string
  method set_id : ?definitive:bool -> string -> unit

  (** {1 Liveness type}
    *
    * [stype] is the liveness type, telling whether a scheduler is
    * fallible or not, i.e. [get] will never fail.
    * It is defined by each operator based on its sources' types. *)

  method virtual stype : source_t

  (** {1 Init/shutdown} *)

  (** Registered server commands for the source *)
  val mutable ns_kind : string
  method register_command : descr:string -> ?usage:string -> string ->
                            (string->string) -> unit

  (** The clock under which the source will run, initially unknown. *)
  method clock : clock_variable

  (** Choose your clock, by adjusting to your children source,
    * or anything custom. *)
  method private set_clock : unit

  (** The operator says to the source that he will ask it frames. *)
  method get_ready : ?dynamic:bool -> source list -> unit

  (** Called when the source must be ready and had no active operator,
    * means that the source has to initialize. *)
  method private wake_up : source list -> unit

  (** Opposite of [get_ready] : the operator no longer needs the source. *)
  method leave : ?dynamic:bool -> source -> unit
  method private sleep : unit

  (** {1 Streaming} *)

  (** What kind of content does this source produce. *)
  method kind : Frame.content_kind

  (** Number of frames left in the current track. Defaults to -1=infinity. *)
  method virtual remaining : int

  (* [self#seek_ticks x] skips [x] master ticks.
   * returns the number of ticks actually skipped.
   * By default it always returns 0, refusing to seek at all.
   * That method may be called from any thread, concurrently
   * with [#get], so they should not interfer. *)
  method seek : int -> int

  (** [is_ready] tells you if [get] can be called. *)
  method virtual is_ready : bool

  (** [get buf] asks the source to fill the buffer [buf] if possible.
    * The [get] call is partial when the buffer is not completely filled.
    * [get] should never be called with a full buffer,
    * and without checking that the source is ready. *)
  method get : Frame.t -> unit
  method private virtual get_frame : Frame.t -> unit

  (** Tells the source to finish the reading of current track. *)
  method virtual abort_track : unit

  method is_output : bool

  (** Wait for output round to finish.
    * Typically, output nodes compute an audio frame (a full buffer),
    * then launch a few output threads, which take care of encoding
    * and outputting (to a file, network, ...).
    * In that case, after_output allows the node to wait for its
    * output threads. *)
  method after_output : unit
  method advance : unit

  (** {1 Utilities} *)

  (** Create a request with a "source" metadata. *)
  method private create_request :
    ?metadata:((string*string) list) ->
    ?persistent:bool ->
    ?indicators:(Request.indicator list) -> string ->
    Request.t

  method private log : Dtools.Log.t

end

(* Entry-points sources, which need to actively perform some task. *)
and virtual active_source : ?name:string -> Frame.content_kind ->
object
  inherit source
  val memo : Frame.t

  (** Special init phase for outputs. This method is called by Root after the
    * standard get_ready propagation, after the Root clock is started.
    * It allows enhancements of the initial latency. *)
  method virtual output_get_ready : unit

  (** Start a new output round, triggers computation of a new frame. *)
  method virtual output : unit

  (** Do whatever needed when the latency gets too big and is reset. *)
  method virtual output_reset : unit

  (** Is the source active ?
    * If the returned value is [false], then [output_reset]
    * should not be called on that source.
    * If [output_reset] does nothing, this function can return any value.
    * TODO that kind of detail could be left inside #output_reset *)
  method virtual is_active : bool
end

(* This is for defining a source which has children *)
class virtual operator : ?name:string -> Frame.content_kind -> source list ->
object
  inherit source
end

(* Most usual active source: the active_operator, pulling one source's data
 * and outputting it. *)
class virtual active_operator :
  ?name:string -> Frame.content_kind -> source list ->
object
  inherit active_source
end

val has_outputs : unit -> bool
val iterate_new_outputs : (active_source -> unit) -> unit

(** {1 Clocks}
  * Tick identifiers are useful (cf. [#get_tick]) but we don't need much
  * more than the guarantee that the next tick is different from the
  * current one. Booleans should be OK, in any case an overflow on int
  * is not a problem. *)

class type clock =
object
  method id : string

  method attach : active_source -> unit
  method detach : (active_source -> bool) -> unit

  method attach_clock : clock_variable -> unit
  method sub_clocks : clock_variable list

  method start_outputs : (active_source -> bool) -> unit -> active_source list
  method get_tick : int
  method end_tick : unit
end

exception Clock_conflict of string*string
exception Clock_loop of string*string

module Clock_variables :
sig
  val to_string : clock_variable -> string
  val create_unknown : sources:(active_source list) ->
                       sub_clocks:(clock_variable list) ->
                       clock_variable
  val create_known : clock -> clock_variable
  val unify : clock_variable -> clock_variable -> unit
  val get : clock_variable -> clock
  val is_known : clock_variable -> bool
end