def __init__(self, dispatcher, repo, worker, conf, logger, autorecover=False, recorderklass=Recorder): """ Initialize the recorder service. :param dispacher service. :param repo service. :param worker service. :param conf service. :param logger service. :param recorderklass (only to test) """ self.repo = repo self.dispatcher = dispatcher self.worker = worker self.logger = logger self.conf = conf self.overlap = conf.get_permission("overlap") self.mute = True self.__set_status(INIT_STATUS) self.current_mediapackage = None self.last_mediapackage = None self.error_msg = None self.recorder = None self.__recorderklass = recorderklass self.__create_drawing_areas_func = None self.__handle_recover_id = None self.autorecover = autorecover self.logger.info("Autorecover mode: {}".format(self.autorecover)) self.dispatcher.connect("init", WeakMethod(self, '_handle_init')) self.dispatcher.connect_ui("action-reload-profile", WeakMethod(self, '_handle_reload_profile')) self.dispatcher.connect("recorder-error", WeakMethod(self, '_handle_error'))
def __init__(self, bins, players={}): """ Initialize the recorder. This class is event-based and needs a mainloop to work properly. :param bins: a ``list`` of ``dict`` with name, klass, device and file to record :param players: a ``dict`` a gtk.DrawingArea list to use as player. """ #FIXME check the values are dict with the next keys: name, klass/type, dev* and filesink. if not isinstance(bins, list): raise TypeError('%s: need a %r; got a %r: %r' % ('bins', list, type(bins), bins)) #FIXME check the values are gtk.DrawingArea if not isinstance(players, dict): raise TypeError('%s: need a %r; got a %r: %r' % ('players', dict, type(players), players)) self.dispatcher = context.get_dispatcher() self.players = players self.restart = False self.mute = False self.error = False self.__on_start_only_preview = True self.__start_record_time = 0 self.__duration = 0 self.pipeline = gst.Pipeline("galicaster_recorder") self.bus = self.pipeline.get_bus() self.bins = dict() self.callback = None self.bus.add_signal_watch() self.bus.enable_sync_message_emission() #self.bus.connect('message', WeakMethod(self, '_debug')) # TO DEBUG self.bus.connect('message::eos', WeakMethod(self, '_on_eos')) self.bus.connect('message::error', WeakMethod(self, '_on_error')) self.bus.connect('message::element', WeakMethod(self, '_on_message_element')) self.bus.connect('message::state-changed', WeakMethod(self, '_on_state_changed')) self.bus.connect('sync-message::element', WeakMethod(self, '_on_sync_message')) for bin in bins: name = bin['name'] try: mod_name = 'galicaster.recorder.bins.' + bin['device'] __import__(mod_name) mod = sys.modules[mod_name] Klass = getattr(mod, "GC" + bin['device']) except: raise NameError('Invalid track type %s for %s track' % (mod_name, name)) logger.debug("Init bin %s %s", name, mod_name) self.bins[name] = Klass(bin) self.pipeline.add(self.bins[name])
def create_pipeline(self): self.pipeline = Gst.Pipeline.new("galicaster_player") bus = self.pipeline.get_bus() # Create bus and connect several handlers bus.add_signal_watch() bus.enable_sync_message_emission() bus.connect('message::eos', WeakMethod(self, '_on_eos')) bus.connect('message::error', WeakMethod(self, '_on_error')) bus.connect('message::element', WeakMethod(self, '_on_message_element')) bus.connect('message::state-changed', WeakMethod(self, '_on_state_changed')) bus.connect('sync-message::element', WeakMethod(self, '_on_sync_message')) # Create elements for name, location in self.files.iteritems(): logger.info('playing %r', location) src = Gst.ElementFactory.make('filesrc', 'src-' + name) src.set_property('location', location) dec = Gst.ElementFactory.make('decodebin', 'decode-' + name) # Connect handler for 'pad-added' signal dec.connect('pad-added', WeakMethod(self, '_on_new_decoded_pad')) # Link elements self.pipeline.add(src) self.pipeline.add(dec) src.link(dec) self.error = None return None
def _handle_error(self, origin, error_msg): self.logger.error("Handle error ({})". format(error_msg)) # self.current_mediapackage = None if self.recorder: self.recorder.stop(True) if self.status == RECORDING_STATUS: self.repo.recover_recording() self.current_mediapackage = None self.error_msg = error_msg self.__set_status(ERROR_STATUS) if self.autorecover and not self.__handle_recover_id: self.logger.info("Connecting recover recorder callback") self.__handle_recover_id = self.dispatcher.connect("timer-long", WeakMethod(self, '_handle_recover'))
def __init__(self, bins, players={}): """ Initialize the recorder. :param bins: ``list`` of ``dict`` with bin name, device, path, and optional parameters. :param players: (optional) ```Gtk.DrawingArea``` ```list``` to use as player. """ if not isinstance(bins, list) or len(bins) == 0: raise TypeError('{}: need a {}; got a {}: {}'.format( 'bins', list, type(bins), bins)) if not isinstance(players, dict): raise TypeError('{}: need a {}; got a {}: {}'.format( 'players', dict, type(players), players)) self.dispatcher = context.get_dispatcher() self.players = players self.restart = False # self.mute = False self.mute_status = {"input": {}, "preview": {}} self.error = False self.is_recording = False self.__start_record_time = -1 self.__pause_timestamp = 0 self.__paused_time = 0 self.__valves_status = False self.__duration = 0 self.pipeline = Gst.Pipeline.new("galicaster_recorder") self.bus = self.pipeline.get_bus() self.bins = dict() self.callback = None self.bus.add_signal_watch() # self.bus.connect('message', WeakMethod(self, '_debug')) # TO DEBUG self.bus.connect('message::error', WeakMethod(self, '_on_error')) self.bus.connect('message::element', WeakMethod(self, '_on_message_element')) try: for bin in bins: name = bin['name'] mod_name = 'galicaster.recorder.bins.' + bin['device'] __import__(mod_name) mod = sys.modules[mod_name] Klass = getattr(mod, "GC" + bin['device']) logger.debug("Init bin {} {}".format(name, mod_name)) self.bins[name] = Klass(bin) self.pipeline.add(self.bins[name]) self.bins[name].prepare(self.bus) # self.enable_input() self.enable_preview() except Exception as exc: logger.info("Removing loaded bins due to an error...") for bin_name in self.bins: self.pipeline.remove(self.bins[bin_name]) self.bins.clear() self.error = str(exc) name = name if 'name' in locals() else 'Unknown' message = 'Invalid track type "{}" for "{}" track: {}'.format( bin.get('device'), name, exc) raise NameError(message)