Пример #1
0
    def connect(self, src):
        """ Connect a VLC output to a given audio source
    This will create a VLC process based on the given name
    """
        print('connecting {} to {}...'.format(self.name, src))

        if self.mock:
            print('{} connected to {}'.format(self.name, src))
            self.state = 'connected'
            self.src = src
            return

        # Make all of the necessary dir(s)
        config_folder = '/home/pi/config/srcs/{}'.format(src)
        os.system('mkdir -p {}'.format(config_folder))

        # Start audio via runvlc.py
        song_info_path = '/home/pi/config/srcs/{}/currentSong'.format(src)
        inetradio_args = [
            'python3', '/home/pi/config/runvlc.py', '{}'.format(self.url),
            '{}'.format(utils.output_device(src)), '--song-info',
            song_info_path
        ]
        self.proc = subprocess.Popen(args=inetradio_args,
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     preexec_fn=os.setpgrp)

        print('{} (stream: {}) connected to {} via {}'.format(
            self.name, self.url, src, utils.output_device(src)))
        self.state = 'connected'
        self.src = src
Пример #2
0
    def connect(self, src):
        """ Connect a VLC output to a given audio source
    This will create a VLC process based on the given name
    """
        print(f'connecting {self.name} to {src}...')

        if self.mock:
            print(f'{self.name} connected to {src}')
            self.state = 'playing'
            self.src = src
            return

        # Make all of the necessary dir(s)
        src_config_folder = f"{utils.get_folder('config')}/srcs/{src}"
        os.system(f'mkdir -p {src_config_folder}')

        # Start audio via runvlc.py
        song_info_path = f'{src_config_folder}/currentSong'
        log_file_path = f'{src_config_folder}/log'
        inetradio_args = [
            sys.executable, f"{utils.get_folder('streams')}/runvlc.py",
            self.url,
            utils.output_device(src), '--song-info', song_info_path, '--log',
            log_file_path
        ]
        print(f'running: {inetradio_args}')
        self.proc = subprocess.Popen(args=inetradio_args,
                                     preexec_fn=os.setpgrp)

        print(
            f'{self.name} (stream: {self.url}) connected to {src} via {utils.output_device(src)}'
        )
        self.state = 'playing'
        self.src = src
Пример #3
0
    def connect(self, src):
        """ Connect a fmradio.py output to a given audio source """

        if self.mock:
            self._connect(src)
            return

        # Make all of the necessary dir(s)
        src_config_folder = f"{utils.get_folder('config')}/srcs/{src}"
        os.system('mkdir -p {}'.format(src_config_folder))
        song_info_path = f'{src_config_folder}/currentSong'
        log_file_path = f'{src_config_folder}/log'

        fmradio_args = [
            sys.executable, f"{utils.get_folder('streams')}/fmradio.py",
            self.freq,
            utils.output_device(src), '--song-info', song_info_path, '--log',
            log_file_path
        ]
        print(f'running: {fmradio_args}')
        self.proc = subprocess.Popen(args=fmradio_args,
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     preexec_fn=os.setpgrp)
        self._connect(src)
Пример #4
0
    def connect(self, src):
        """ Connect a DLNA device to a given audio source
    This creates a DLNA streaming option based on the configuration
    """
        if self.mock:
            self._connect(src)
            return

        # Generate some of the DLNA_Args
        self.uuid = 0
        self.uuid = uuid_gen()
        portnum = 49494 + int(src)

        src_config_folder = f'{utils.get_folder("config")}/srcs/{src}'
        meta_args = [
            f'{utils.get_folder("streams")}/dlna_metadata.bash',
            f'{src_config_folder}'
        ]
        dlna_args = [
            'gmediarender', '--gstout-audiosink', 'alsasink',
            '--gstout-audiodevice',
            utils.output_device(src), '--gstout-initial-volume-db', '0.0',
            '-p', f'{portnum}', '-u', f'{self.uuid}', '-f', f'{self.name}',
            '--logfile', f'{src_config_folder}/metafifo'
        ]
        self.proc = subprocess.Popen(args=meta_args,
                                     preexec_fn=os.setpgrp,
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
        self.proc2 = subprocess.Popen(args=dlna_args,
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
        self._connect(src)
Пример #5
0
    def connect(self, src):
        """ Connect pandora output to a given audio source
    This will start up pianobar with a configuration specific to @src
    """
        if self.mock:
            self._connect(src)
            return
        # TODO: future work, make pandora and shairport use audio fifos that makes it simple to switch their sinks

        # make a special home/config to launch pianobar in (this allows us to have multiple pianobars)
        src_config_folder = f'{utils.get_folder("config")}/srcs/{src}'
        eventcmd_template = f'{utils.get_folder("streams")}/eventcmd.sh'
        pb_home = src_config_folder
        pb_config_folder = f'{pb_home}/.config/pianobar'
        pb_control_fifo = f'{pb_config_folder}/ctl'
        pb_status_fifo = f'{pb_config_folder}/stat'
        pb_config_file = f'{pb_config_folder}/config'
        pb_output_file = f'{pb_config_folder}/output'
        pb_error_file = f'{pb_config_folder}/error'
        pb_eventcmd_file = f'{pb_config_folder}/eventcmd.sh'
        pb_src_config_file = f'{pb_home}/.libao'
        # make all of the necessary dir(s)
        os.system(f'mkdir -p {pb_config_folder}')
        os.system(f'cp {eventcmd_template} {pb_eventcmd_file}'
                  )  # Copy to retain executable status
        # write pianobar and libao config files
        write_config_file(
            pb_config_file, {
                'user': self.user,
                'password': self.password,
                'autostart_station': self.station,
                'fifo': pb_control_fifo,
                'event_command': pb_eventcmd_file
            })
        write_config_file(pb_src_config_file, {
            'default_driver': 'alsa',
            'dev': utils.output_device(src)
        })
        # create fifos if needed
        if not os.path.exists(pb_control_fifo):
            os.system(f'mkfifo {pb_control_fifo}')
        if not os.path.exists(pb_status_fifo):
            os.system(f'mkfifo {pb_status_fifo}')
        # start pandora process in special home
        print(f'Pianobar config at {pb_config_folder}')
        try:
            self.proc = subprocess.Popen(args='pianobar',
                                         stdin=subprocess.PIPE,
                                         stdout=open(pb_output_file, 'w'),
                                         stderr=open(pb_error_file, 'w'),
                                         env={'HOME': pb_home})
            time.sleep(
                0.1)  # Delay a bit before creating a control pipe to pianobar
            self.ctrl = pb_control_fifo
            self._connect(src)
            self.state = 'playing'
        except Exception as exc:
            print(f'error starting pianobar: {exc}')
Пример #6
0
  def connect(self, src):
    """ Connect pandora output to a given audio source
    This will start up pianobar with a configuration specific to @src
    """
    if self.mock:
      print('{} connected to {}'.format(self.name, src))
      self.state = 'playing' # TODO: only play station based streams
      self.src = src
      return
    # TODO: future work, make pandora and shairport use audio fifos that makes it simple to switch their sinks
    # make a special home, with specific config to launch pianobar in (this allows us to have multiple pianobars)

    eventcmd_template = '/home/pi/config/eventcmd.sh'
    pb_home = '/home/pi/config/srcs/{}'.format(src) # the simulated HOME for an instance of pianobar
    pb_config_folder = '{}/.config/pianobar'.format(pb_home)
    pb_control_fifo = '{}/ctl'.format(pb_config_folder)
    pb_status_fifo = '{}/stat'.format(pb_config_folder)
    pb_config_file = '{}/config'.format(pb_config_folder)
    pb_output_file = '{}/output'.format(pb_config_folder)
    pb_error_file = '{}/error'.format(pb_config_folder)
    pb_eventcmd_file = '{}/eventcmd.sh'.format(pb_config_folder)
    pb_src_config_file = '{}/.libao'.format(pb_home)
    # make all of the necessary dir(s)
    os.system('mkdir -p {}'.format(pb_config_folder))
    os.system('cp {} {}'.format(eventcmd_template, pb_eventcmd_file)) # Copy to retain executable status
    # write pianobar and libao config files
    write_config_file(pb_config_file, {
      'user': self.user,
      'password': self.password,
      'autostart_station': self.station,
      'fifo': pb_control_fifo,
      'event_command': pb_eventcmd_file
    })
    write_config_file(pb_src_config_file, {'default_driver': 'alsa', 'dev': utils.output_device(src)})
    try:
      with open(pb_eventcmd_file) as ect:
        template = ect.read().replace('source_id', str(src))
      with open(pb_eventcmd_file, 'w') as ec:
        ec.write(template)
    except Exception as e:
      print('error creating eventcmd: {}'.format(e))
    # create fifos if needed
    if not os.path.exists(pb_control_fifo):
      os.system('mkfifo {}'.format(pb_control_fifo))
    if not os.path.exists(pb_status_fifo):
      os.system('mkfifo {}'.format(pb_status_fifo))
    # start pandora process in special home
    print('Pianobar config at {}'.format(pb_config_folder))
    try:
      self.proc = subprocess.Popen(args='pianobar', stdin=subprocess.PIPE, stdout=open(pb_output_file, 'w'), stderr=open(pb_error_file, 'w'), env={'HOME' : pb_home})
      time.sleep(0.1) # Delay a bit before creating a control pipe to pianobar
      self.ctrl = Pandora.Control(pb_control_fifo)
      self.src = src
      self.state = 'playing'
      print('{} connected to {}'.format(self.name, src))
    except Exception as e:
      print('error starting pianobar: {}'.format(e))
Пример #7
0
 def connect(self, src):
   """ Connect an Airplay device to a given audio source
   This creates an Airplay streaming option based on the configuration
   """
   if self.mock:
     print('{} connected to {}'.format(self.name, src))
     self.state = 'connected'
     self.src = src
     return
   config = {
     'general': {
       'name': self.name,
       'port': 5100 + 100 * src, # Listen for service requests on this port
       'udp_port_base': 6101 + 100 * src, # start allocating UDP ports from this port number when needed
       'drift': 2000, # allow this number of frames of drift away from exact synchronisation before attempting to correct it
       'resync_threshold': 0, # a synchronisation error greater than this will cause resynchronisation; 0 disables it
       'log_verbosity': 0, # "0" means no debug verbosity, "3" is most verbose.
     },
     'metadata':{
       'enabled': 'yes',
       'include_cover_art': 'yes',
       'pipe_name': '/home/pi/config/srcs/{}/shairport-sync-metadata'.format(src),
       'pipe_timeout': 5000,
     },
     'alsa': {
       'output_device': utils.output_device(src), # alsa output device
       'audio_backend_buffer_desired_length': 11025 # If set too small, buffer underflow occurs on low-powered machines. Too long and the response times with software mixer become annoying.
     },
   }
   config_folder = '/home/pi/config/srcs/{}'.format(src)
   # make all of the necessary dir(s)
   os.system('mkdir -p {}'.format(config_folder))
   config_file = '{}/shairport.conf'.format(config_folder)
   write_sp_config_file(config_file, config)
   shairport_args = 'shairport-sync -c {}'.format(config_file).split(' ')
   # TODO: figure out how to get status from shairport
   self.proc = subprocess.Popen(args=shairport_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   print('{} connected to {}'.format(self.name, src))
   self.state = 'connected'
   self.src = src
Пример #8
0
 def connect(self, src):
     """ Connect an AirPlay device to a given audio source
 This creates an AirPlay streaming option based on the configuration
 """
     if self.mock:
         self._connect(src)
         return
     config = {
         'general': {
             'name': self.name,
             'port':
             5100 + 100 * src,  # Listen for service requests on this port
             'udp_port_base': 6101 + 100 *
             src,  # start allocating UDP ports from this port number when needed
             'drift':
             2000,  # allow this number of frames of drift away from exact synchronisation before attempting to correct it
             'resync_threshold':
             0,  # a synchronisation error greater than this will cause resynchronisation; 0 disables it
             'log_verbosity':
             0,  # "0" means no debug verbosity, "3" is most verbose.
         },
         'metadata': {
             'enabled': 'yes',
             'include_cover_art': 'yes',
             'pipe_name':
             f'{utils.get_folder("config")}/srcs/{src}/shairport-sync-metadata',
             'pipe_timeout': 5000,
         },
         'alsa': {
             'output_device':
             utils.output_device(src),  # alsa output device
             'audio_backend_buffer_desired_length':
             11025  # If set too small, buffer underflow occurs on low-powered machines. Too long and the response times with software mixer become annoying.
         },
     }
     src_config_folder = f'{utils.get_folder("config")}/srcs/{src}'
     os.system(f'rm -f {src_config_folder}/currentSong')
     web_dir = f"{utils.get_folder('web/generated')}/shairport/srcs/{src}"
     # make all of the necessary dir(s)
     os.system(f'rm -r -f {web_dir}')
     os.system(f'mkdir -p {web_dir}')
     os.system(f'mkdir -p {src_config_folder}')
     config_file = f'{src_config_folder}/shairport.conf'
     write_sp_config_file(config_file, config)
     shairport_args = f'shairport-sync -c {config_file}'.split(' ')
     meta_args = [
         f"{utils.get_folder('streams')}/shairport_metadata.bash",
         src_config_folder, web_dir
     ]
     print(f'shairport_args: {shairport_args}')
     print(f'meta_args: {meta_args}')
     # TODO: figure out how to get status from shairport
     self.proc = subprocess.Popen(args=shairport_args,
                                  stdin=subprocess.PIPE,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
     self.proc2 = subprocess.Popen(args=meta_args,
                                   preexec_fn=os.setpgrp,
                                   stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
     self._connect(src)