~ubuntu-branches/ubuntu/natty/gnome-dvb-daemon/natty

« back to all changes in this revision

Viewing changes to src/ChannelFactory.vala

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2009-11-19 15:55:34 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20091119155534-lky88n43jb0htalm
Tags: 0.1.13-1
* New upstream release:
  + debian/control.in:
    - Update build dependencies.

Show diffs side-by-side

added added

removed removed

Lines of Context:
85
85
         * @epgscanner: #EPGScanner to forward EIT to
86
86
         */
87
87
        public PlayerThread (Device device, EPGScanner? epgscanner) {
88
 
            this.device = device;
 
88
            base (device: device);
89
89
            this.epgscanner = epgscanner;
90
90
        }
91
91
        
107
107
            uint channel_sid = channel.Sid;
108
108
            string channel_sid_str = channel_sid.to_string ();
109
109
            bool create_channel;
110
 
            
111
110
            Element? bin, tee = null;
112
 
            if (this.pipeline == null) {
113
 
                // New channel and new pipeline
114
 
                debug ("Creating new pipeline");
115
 
                lock (this.pipeline) {
 
111
 
 
112
            lock (this.pipeline) {
 
113
                if (this.pipeline == null) {
 
114
                    // New channel and new pipeline
 
115
                    debug ("Creating new pipeline");
 
116
 
116
117
                    // Setup new pipeline
117
118
                    this.pipeline = new Pipeline ("recording");
118
119
                
146
147
                    }
147
148
                    
148
149
                    create_channel = true;
149
 
                }
150
 
            } else {
151
 
                // Use current pipeline and add new sink
152
 
                debug ("Reusing existing pipeline");
153
 
                if (this.dvbbasebin == null) {
154
 
                    critical ("No dvbbasebin element");
155
 
                    return null;
156
 
                }
 
150
                
 
151
                } else {
 
152
                    // Use current pipeline and add new sink
 
153
                    debug ("Reusing existing pipeline");
 
154
                    if (this.dvbbasebin == null) {
 
155
                        critical ("No dvbbasebin element");
 
156
                        return null;
 
157
                    }
157
158
 
158
 
                if (!this.active_channels.contains (channel)) {
159
 
                    // existing pipeline and new channel
160
 
                    lock (this.pipeline) {
 
159
                    if (!this.active_channels.contains (channel)) {
 
160
                        // existing pipeline and new channel
 
161
                        
161
162
                        tee = ElementFactory.make ("tee", null);
162
163
                        this.add_element (tee);
163
164
                        
166
167
                            critical ("Could not link tee and bin");
167
168
                            return null;
168
169
                        }
169
 
                    
 
170
 
170
171
                        this.pipeline.set_state (State.PAUSED);
171
 
                        
 
172
 
172
173
                        string programs;
173
174
                        dvbbasebin.get ("program-numbers", out programs);
174
175
                        
179
180
                        this.dvbbasebin.set ("program-numbers", new_programs);
180
181
                        
181
182
                        create_channel = true;
182
 
                    }
183
 
                } else { // existing pipeline and existing channel
184
 
                    ChannelElements c_element;
185
 
                    lock (this.elements_map) {
186
 
                        c_element = this.elements_map.get (channel_sid);
187
 
                    }
188
 
                    tee = c_element.tee;
189
 
 
190
 
                    lock (this.pipeline) {
191
 
                        this.pipeline.set_state (State.PAUSED);
192
 
                        bin = this.add_sink_bin (sink_element);
193
 
                    }
194
 
 
195
 
                    debug ("Linking %s with %s", tee.get_name (), bin.get_name ());
196
 
                    if (!tee.link (bin)) {
197
 
                        critical ("Could not link tee and bin");
198
 
                        return null;
199
 
                    }
200
 
 
201
 
                    c_element.sinks.add (bin);
202
 
                    create_channel = false;
 
183
 
 
184
                    } else { // existing pipeline and existing channel
 
185
                        ChannelElements c_element;
 
186
                        lock (this.elements_map) {
 
187
                            c_element = this.elements_map.get (channel_sid);
 
188
 
 
189
                            tee = c_element.tee;
 
190
 
 
191
                            bin = this.add_sink_bin (sink_element);                            
 
192
 
 
193
                            debug ("Linking %s with %s", tee.get_name (), bin.get_name ());
 
194
                            if (!tee.link (bin)) {
 
195
                                critical ("Could not link tee and bin");
 
196
                                return null;
 
197
                            }
 
198
 
 
199
                            c_element.sinks.add (bin);
 
200
                        }
 
201
                        create_channel = false;
 
202
                    }
203
203
                }
204
204
            }
205
205
            
233
233
            }
234
234
            
235
235
            var pad = queue.get_static_pad ("sink");
236
 
            bin.add_pad (new Gst.GhostPad ("sink", pad));
 
236
            var ghost = new Gst.GhostPad ("sink", pad);
 
237
            ghost.set_active (true);
 
238
            bin.add_pad (ghost);
 
239
            /* src pad is ghosted by gst-rtsp-server */
237
240
            
238
241
            this.add_element (bin);
239
242
 
254
257
         */
255
258
        public Gst.Element? get_sink_bin (uint sid, Gst.Element sink) {
256
259
            Gst.Element? result = null;
 
260
 
257
261
            debug ("Searching for sink %s (%p) of channel %u", sink.get_name (), sink, sid);
258
262
            lock (this.elements_map) {
259
263
                ChannelElements? celems = this.elements_map.get (sid);
266
270
                            break;
267
271
                        }
268
272
                    }
 
273
                } else {
 
274
                    warning ("Could not find any sinks of channel %u", sid);
269
275
                }
270
276
            }
271
277
            
277
283
         */
278
284
        public bool remove_channel (Channel channel, Gst.Element sink) {
279
285
            uint channel_sid = channel.Sid;
280
 
        
 
286
 
281
287
            if (!this.active_channels.contains (channel)) {
282
288
                critical ("Could not find channel with SID %u", channel_sid);
283
289
                return false;
284
290
            }
285
 
            
286
 
            // Check if that's the only channel in use
287
 
            if (this.active_channels.size > 1) {
288
 
                string channel_sid_string = channel_sid.to_string ();
289
 
                
290
 
                lock (this.pipeline) {
291
 
                    bool stop_channel;
292
 
                    lock (this.elements_map) {
293
 
                        ChannelElements celements = this.elements_map.get (channel_sid);
294
 
                        if (celements.sinks.size == 1) {
295
 
                            // this is the last sink
296
 
                            // (no one watches this channel anymore)
297
 
                            this.elements_map.remove (channel_sid);
298
 
                            stop_channel = true;
299
 
                        } else {
300
 
                            // we still have sinks left
301
 
                            // (others are still watching this channel)
302
 
                            celements.sinks.remove (sink);
303
 
                            stop_channel = false;
304
 
                        }
305
 
                    }
306
 
                   
307
 
                    if (stop_channel) { 
 
291
 
 
292
            ChannelElements celements;
 
293
            bool stop_channel;
 
294
            lock (this.elements_map) {
 
295
                celements = this.elements_map.get (channel_sid);
 
296
                /* check if this is the last sink
 
297
                 * (no one watches this channel anymore)
 
298
                 * or if we still have sinks left
 
299
                 * (others are still watching this channel)
 
300
                 */
 
301
                stop_channel = (celements.sinks.size == 1);
 
302
            }
 
303
 
 
304
            lock (this.pipeline) {
 
305
                // Check if that's the only channel in use
 
306
                if (this.active_channels.size > 1) {
 
307
               
 
308
                    if (stop_channel) {
 
309
                        string channel_sid_string = channel_sid.to_string ();
 
310
                    
308
311
                        string programs;
309
312
                        dvbbasebin.get ("program-numbers", out programs);
310
313
                        string[] programs_arr = programs.split (":");
311
 
                        
 
314
 
312
315
                        // Remove SID of channel from program-numbers
313
 
                        SList<string> new_programs_list = new SList<string> ();
 
316
                        ArrayList<string> new_programs_list = new ArrayList<string> ();
314
317
                        for (int i=0; i<programs_arr.length; i++) {
315
 
                            string val = programs_arr[i];
316
 
                            if (val != channel_sid_string)
317
 
                                new_programs_list.prepend (val);
318
 
                        }
319
 
                        
320
 
                        StringBuilder new_programs = new StringBuilder (new_programs_list.nth_data (0));
321
 
                        for (int i=1; i<new_programs_list.length (); i++) {
322
 
                            new_programs.append (":" + new_programs_list.nth_data (i));
323
 
                        }
324
 
                    
 
318
                            if (programs_arr[i] != channel_sid_string)
 
319
                                new_programs_list.add (programs_arr[i]);
 
320
                        }
 
321
 
 
322
                        StringBuilder new_programs = new StringBuilder (new_programs_list.get (0));
 
323
                        for (int i=1; i<new_programs_list.size; i++) {
 
324
                            new_programs.append (":" + new_programs_list.get (i));
 
325
                        }
 
326
 
325
327
                        debug ("Changing program-numbers from %s to %s", programs,
326
328
                                new_programs.str);
327
329
                        this.pipeline.set_state (State.PAUSED);
328
 
                        
 
330
 
329
331
                        dvbbasebin.set ("program-numbers", new_programs.str);
330
 
                        
 
332
 
331
333
                        this.pipeline.set_state (State.PLAYING);
332
 
                        
333
334
                        this.active_channels.remove (channel);
334
335
                    }
335
336
 
336
337
                    this.remove_sink_bin (channel_sid, sink);
337
 
                }
338
 
            } else {
339
 
                lock (this.elements_map) {
340
 
                    ChannelElements celements = this.elements_map.get (channel_sid);
341
 
                    if (celements.sinks.size == 1) {
 
338
 
 
339
                    if (stop_channel) {            
 
340
                        /* No one watches the channel anymore */
 
341
                        debug ("Removing tee %s from pipeline",
 
342
                            celements.tee.get_name ());
 
343
                        celements.tee.set_state (State.NULL);
 
344
                        ((Bin)this.pipeline).remove (celements.tee);
 
345
                        lock (this.elements_map) {
 
346
                            this.elements_map.remove (channel_sid);
 
347
                        }
 
348
                    }
 
349
 
 
350
                } else { /* More than one channel in use */
 
351
                    if (stop_channel) {
342
352
                        // this is the last sink
343
 
                        // (no one watches this channel anymore)
 
353
                        // (no one watches any channel anymore)
344
354
                        this.destroy ();
345
355
                    } else {
346
356
                        // we still have sinks left
347
357
                        // (others are still watching this channel)
348
358
                        this.remove_sink_bin (channel_sid, sink);
349
 
                        celements.sinks.remove (sink);
350
359
                    }
351
360
                }
352
361
            }
353
 
        
 
362
 
354
363
            return true;
355
364
        }
356
365
        
357
366
        private void remove_sink_bin (uint channel_sid, Gst.Element sink) {
 
367
            debug ("Removing sink bin of sink %s (%p) of channel %u",
 
368
                sink.get_name (), sink, channel_sid);
 
369
        
358
370
            Gst.Element? sink_bin = this.get_sink_bin (channel_sid, sink);
359
371
 
360
372
            if (sink_bin == null) {
361
 
                warning ("Could not find sink bin for channel %u and sink %p",
362
 
                    channel_sid, sink);
 
373
                critical ("Could not find sink bin for channel %u and sink %s (%p)",
 
374
                    channel_sid, sink.get_name (), sink);
363
375
                return;
364
376
            }
365
 
            debug ("Setting state of queue and sink to NULL");
366
 
            sink_bin.set_state (State.NULL);
 
377
 
 
378
            lock (this.elements_map) {
 
379
                ChannelElements celems = this.elements_map.get (channel_sid);
 
380
 
 
381
                debug ("Setting state of queue and sink %s (%p) to NULL", 
 
382
                    sink.get_name (), sink);
 
383
                celems.tee.unlink (sink_bin);
 
384
                sink_bin.set_state (State.NULL);
367
385
            
 
386
                if (!celems.sinks.remove (sink_bin)) {
 
387
                    critical ("Could not find sink bin %s (%p)",
 
388
                        sink_bin.get_name (), sink_bin);
 
389
                }
 
390
            }
 
391
 
368
392
            debug ("Removing queue and sink from pipeline");
369
393
            ((Bin)this.pipeline).remove (sink_bin);
370
394
        }
375
399
        public virtual void destroy (bool forced=false) {
376
400
            if (this.destroyed) return;
377
401
            lock (this.destroyed) {
 
402
                this.destroyed = true;
378
403
                if (forced) {
379
404
                    lock (this.elements_map) {
380
405
                        foreach (ChannelElements celems in this.elements_map.values) {
400
425
                    this.elements_map.clear ();
401
426
                }
402
427
                this.active_channels.clear ();
403
 
                this.destroyed = true;
404
428
            }
405
429
        }
406
430
 
464
488
                            this.epgscanner.on_eit_structure (message.structure);
465
489
                        this.eit_structure (message.structure);
466
490
                    }
467
 
                break;
468
 
                
 
491
                    break;
 
492
                case Gst.MessageType.WARNING:
 
493
                    warning ("%s", message.structure.to_string ());
 
494
                    break;
 
495
                case Gst.MessageType.ERROR:
 
496
                    critical ("%s", message.structure.to_string ());
 
497
                    break;
469
498
                default:
470
499
                break;
471
500
            }
484
513
        private HashSet<PlayerThread> active_players;
485
514
        
486
515
        public ChannelFactory (DeviceGroup devgroup) {
487
 
            this.device_group = devgroup;
 
516
            base (device_group: devgroup);
488
517
            this.active_players = new HashSet<PlayerThread> ();
489
518
        }
490
519
        
552
581
                    free_device = this.device_group.get_next_free_device ();
553
582
                }
554
583
                if (free_device == null) {
555
 
                    critical ("All devices are busy");
 
584
                    message ("All devices are busy");
556
585
                    return null;
557
586
                }
558
587
 
563
592
            lock (this.active_players) {
564
593
                this.active_players.add (player);
565
594
            }
566
 
            
 
595
 
567
596
            return player;
568
597
        }
569
598
        
574
603
         */
575
604
        public bool stop_channel (Channel channel, Gst.Element sink) {
576
605
            debug ("Stopping channel %s (%u)", channel.Name, channel.Sid);
577
 
        
 
606
 
578
607
            bool success = false;
579
608
            PlayerThread? player = null;
580
609
            lock (this.active_players) {
595
624
                    if (epgscanner != null) epgscanner.start ();
596
625
                }
597
626
            }
 
627
 
598
628
            return success;
599
629
        }
600
630