def step_property(self, property, value, args=None): """ Step a player property (e.g. volume, time_pos etc.). See https://www.mplayerhq.hu/DOCS/tech/slave.txt for a full list of the available steppable properties """ args = args or [] response = Response(output={}) result = self._exec('step_property', property, value, prefix='pausing_keep_force', wait_for_response=True, *args) or {} for k, v in result.items(): if k == 'ERROR' and v not in response.errors: response.errors.append('{} {}{}: {}'.format( property, value, args, v)) else: response.output[k] = v return response
def search(self, query, types=None, queue_results=False, autoplay=False): results = [] if types is None: types = {'youtube', 'file', 'torrent'} if 'file' in types: file_results = self.file_search(query).output results.extend(file_results) if 'torrent' in types: torrent_results = self.torrent_search(query).output results.extend(torrent_results) if 'youtube' in types: yt_results = self.youtube_search(query).output results.extend(yt_results) if results: if queue_results: self.videos_queue = [_['url'] for _ in results] if autoplay: self.play(self.videos_queue.pop(0)) elif autoplay: self.play(results[0]['url']) return Response(output=results)
def stop(self): http = urllib3.PoolManager() request = http.request('POST', 'http://{}:{}/stop/'.format(self.server, self.port)) self.state = PlayerState.STOP.value return Response(output=request.read())
def file_search(self, query): results = [] query_tokens = [_.lower() for _ in re.split('\s+', query.strip())] for media_dir in self.media_dirs: logging.info('Scanning {} for "{}"'.format(media_dir, query)) for path, dirs, files in os.walk(media_dir): for f in files: if not self._is_video_file(f): continue matches_query = True for token in query_tokens: if token not in f.lower(): matches_query = False break if not matches_query: continue results.append({ 'url': 'file://' + path + os.sep + f, 'title': f, }) return Response(output=results)
def _exec(self, attr, *args, **kwargs): try: self.connect() except Exception as e: # Reset bridge connection self.bridge = None raise e lights = [] groups = [] if 'lights' in kwargs and kwargs['lights']: lights = kwargs['lights'].split(',') \ if isinstance(lights, str) else kwargs['lights'] elif 'groups' in kwargs and kwargs['groups']: groups = kwargs['groups'].split(',') \ if isinstance(groups, str) else kwargs['groups'] else: lights = self.lights groups = self.groups try: if attr == 'scene': self.bridge.run_scene(groups[0], kwargs['name']) elif groups: self.bridge.set_group(groups, attr, *args) elif lights: self.bridge.set_light(lights, attr, *args) except Exception as e: # Reset bridge connection self.bridge = None raise e return Response(output='ok')
def update_now_playing(self, artist, title, album=None, **kwargs): self.lastfm.update_now_playing( artist=artist, title=title, album=album, ) return Response()
def next(self): if self.player: self.player.stop() if self.videos_queue: video = self.videos_queue.pop(0) return self.play(video) return Response(output={'status': 'no media'}, errors=[])
def scrobble(self, artist, title, album=None, **kwargs): self.lastfm.scrobble( artist=artist, title=title, album=album, timestamp=int(time.time()), ) return Response()
def download_torrent(self, magnet): import libtorrent as lt if not self.download_dir: raise RuntimeError( 'No download_dir specified in video.omxplayer configuration') ses = lt.session() ses.listen_on(*self.torrent_ports) info = lt.parse_magnet_uri(magnet) logging.info('Downloading "{}" to "{}" from [{}]'.format( info['name'], self.download_dir, magnet)) params = { 'save_path': self.download_dir, 'storage_mode': lt.storage_mode_t.storage_mode_sparse, } transfer = lt.add_magnet_uri(ses, magnet, params) status = transfer.status() files = [] self.torrent_state = { 'url': magnet, 'title': info['name'], } while (not status.is_seeding): status = transfer.status() torrent_file = transfer.torrent_file() if torrent_file: files = [ os.path.join(self.download_dir, torrent_file.files().file_path(i)) for i in range(0, torrent_file.files().num_files()) if self._is_video_file(torrent_file.files().file_name(i)) ] self.torrent_state['progress'] = 100 * status.progress self.torrent_state['download_rate'] = status.download_rate self.torrent_state['upload_rate'] = status.upload_rate self.torrent_state['num_peers'] = status.num_peers self.torrent_state['state'] = status.state logging.info( ('Torrent download: {:.2f}% complete (down: {:.1f} kb/s ' + 'up: {:.1f} kB/s peers: {} state: {})').format( status.progress * 100, status.download_rate / 1000, status.upload_rate / 1000, status.num_peers, status.state)) time.sleep(5) return Response(output=files)
def stop(self): self._can_run = False if self._drive_thread and threading.get_ident( ) != self._drive_thread.ident: self._drive_thread.join() self.zb.MotorsOff() self.zb.ResetEpo() return Response(output={'status': 'stopped'})
def get_data(self): ser = serial.Serial(self.device, self.baud_rate) try: data = ser.readline().decode('utf-8').strip() finally: ser.close() try: data = json.loads(data) except: pass return Response(output=data)
def write(self, pin, val): gpio.setmode(gpio.BCM) gpio.setup(pin, gpio.OUT) gpio.output(pin, val) return Response(output={ 'pin': pin, 'val': val, 'method': 'write', })
def play(self, url): request = urllib.request.urlopen( 'http://{}:{}/play/'.format(self.server, self.port), data=urllib.parse.urlencode({ 'url': url }).encode() ) self.state = PlayerState.PLAY.value return Response(output=request.read())
def read(self, pin, val): gpio.setmode(gpio.BCM) gpio.setup(pin, gpio.IN) val = gpio.input(pin) return Response(output={ 'pin': pin, 'val': val, 'method': 'read', })
def exec(self, cmd): output = None errors = [] try: output = subprocess.check_output( cmd, stderr=subprocess.STDOUT, shell=True).decode('utf-8') except subprocess.CalledProcessError as e: errors = [e.output.decode('utf-8')] return Response(output=output, errors=errors)
def _exec(self, method, url, output='text', **kwargs): """ Available output types: text (default), json, binary """ method = getattr(requests, method) response = method(url, **kwargs) response.raise_for_status() output = response.text if output == 'json': output = response.json() if output == 'binary': output = response.content return Response(output=output, errors=[])
def drive(self, direction): prev_direction = self._direction self._can_run = True self._direction = direction.lower() logging.info('Received ZeroBorg drive command: {}'.format(direction)) def _run(): while self._can_run and self._direction: left = 0.0 right = 0.0 if self._direction == Direction.DIR_AUTO_TOGGLE.value: if self.auto_mode: self._direction = None self.auto_mode = False else: self._direction = Direction.DIR_AUTO self.auto_mode = True if self._direction == Direction.DIR_AUTO.value: self.auto_mode = True if self.auto_mode: self._direction = self._get_direction_from_sensors() time.sleep(0.1) motor_1_power = motor_2_power = motor_3_power = motor_4_power = 0.0 if self._direction in self.directions: motor_1_power = self.directions[ self._direction]['motor_1_power'] motor_2_power = self.directions[ self._direction]['motor_2_power'] motor_3_power = self.directions[ self._direction]['motor_3_power'] motor_4_power = self.directions[ self._direction]['motor_4_power'] elif self._direction: logging.warning( 'Invalid direction {}, stopping motors'.format( self._direction)) self.zb.SetMotor1(motor_1_power) self.zb.SetMotor2(motor_2_power) self.zb.SetMotor3(motor_3_power) self.zb.SetMotor4(motor_4_power) self.auto_mode = False self._drive_thread = threading.Thread(target=_run) self._drive_thread.start() return Response(output={'status': 'running', 'direction': direction})
def search_and_play(self, query): response = self.search(query) if not response.output['MovieList']: logging.info('No torrent results found for {}'.format(query)) return Response() item = response.output['MovieList'][0] magnet = item['items'][0]['torrent_magnet'] logging.info('Playing torrent "{}" from {}' .format(item['title'], magnet)) return self.play(magnet)
def status(self): state = PlayerState.STOP.value if self.player: state = self.player.playback_status().lower() if state == 'playing': state = PlayerState.PLAY.value elif state == 'stopped': state = PlayerState.STOP.value elif state == 'paused': state = PlayerState.PAUSE.value return Response( output=json.dumps({ 'source': self.player.get_source(), 'state': state, 'volume': self.player.volume(), 'elapsed': self.player.position(), 'duration': self.player.duration(), 'width': self.player.width(), 'height': self.player.height(), })) else: return Response( output=json.dumps({'state': PlayerState.STOP.value}))
def _exec(self, method, device, *args, **kwargs): if device not in self.devices: self.refresh_devices() if device not in self.devices: raise RuntimeError('Device {} not found'.format(device)) logging.info('{} -> {}'.format(device, method)) dev = self.devices[device] getattr(dev, method)(*args, **kwargs) resp = {'device': device, 'state': dev.get_state()} return Response(output=json.dumps(resp))
def _send_response(self, response): response = Response.build(response) response.id = self.id response.target = self.origin response.origin = Config.get('device_id') if self.backend and self.origin: self.backend.send_response(response=response, request=self) else: redis = get_plugin('redis') if redis: queue_name = get_redis_queue_name_by_message(self) redis.send_message(queue_name, response) redis.expire(queue_name, 60)
def search(self, query): request = urllib.request.urlopen(urllib.request.Request( 'https://api.apidomain.info/list?' + urllib.parse.urlencode({ 'sort': 'relevance', 'quality': '720p,1080p,3d', 'page': 1, 'keywords': query, }), headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' }) ) results = json.loads(request.read()) return Response(output=results)
def compose(self, sender, to, subject, body, files=None): message = MIMEMultipart() if files else MIMEText(body) message['to'] = to message['from'] = sender message['subject'] = subject if files: for file in files: msg = MIMEText(body) message.attach(msg) content_type, encoding = mimetypes.guess_type(file) if content_type is None or encoding is not None: content_type = 'application/octet-stream' main_type, sub_type = content_type.split('/', 1) with open(file, 'rb') as fp: content = fp.read() if main_type == 'text': msg = mimetypes.MIMEText(content, _subtype=sub_type) elif main_type == 'image': msg = MIMEImage(content, _subtype=sub_type) elif main_type == 'audio': msg = MIMEAudio(content, _subtype=sub_type) elif main_type == 'application': msg = MIMEApplication(content, _subtype=sub_type, _encoder=encode_base64) else: msg = MIMEBase(main_type, sub_type) msg.set_payload(content) filename = os.path.basename(file) msg.add_header('Content-Disposition', 'attachment', filename=filename) message.attach(msg) service = self._get_service() body = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()} message = (service.users().messages().send(userId='me', body=body).execute()) return Response(output=message)
def _thread_func(_n_tries, errors=None): response = None if self.action.startswith('procedure.'): context['n_tries'] = _n_tries response = self._execute_procedure(**context) if response is not None: self._send_response(response) return response else: action = self.expand_value_from_context(self.action, **context) (module_name, method_name) = get_module_and_method_from_action(action) plugin = get_plugin(module_name) try: # Run the action args = self._expand_context(**context) args = self.expand_value_from_context(args, **context) response = plugin.run(method=method_name, **args) if response and response.is_error(): logger.warning(('Response processed with errors from ' + 'action {}: {}').format( action, str(response))) elif not response.disable_logging: logger.info('Processed response from action {}: {}'. format(action, str(response))) except Exception as e: # Retry mechanism plugin.logger.exception(e) logger.warning(('Uncaught exception while processing response ' + 'from action [{}]: {}').format(action, str(e))) errors = errors or [] if str(e) not in errors: errors.append(str(e)) response = Response(output=None, errors=errors) if _n_tries-1 > 0: logger.info('Reloading plugin {} and retrying'.format(module_name)) get_plugin(module_name, reload=True) response = _thread_func(_n_tries=_n_tries - 1, errors=errors) finally: self._send_response(response) return response
def current_track(self, **kwargs) -> dict: """ Get the track currently playing. :return: .. schema:: spotify.SpotifyTrackSchema """ status = self.spotify_user_call('/v1/me/player') empty_response = Response(output={}) if not status: # noinspection PyTypeChecker return empty_response track = status.get('item', {}) if not track: # noinspection PyTypeChecker return empty_response return SpotifyTrackSchema().dump(track)
def status(self, device_id=None): """ Returns the status of the specified device_id or all the device in a ``{ device_id => device_info }`` map format. Device info includes ``video_file``, ``image_file``, ``frames_dir`` and additional video info """ resp = Response(output={ id: { 'image_file': self._get_stored_frames_files(info['frames_dir'])[-2] if 'frames_dir' in info and len(self._get_stored_frames_files(info['frames_dir'])) > 1 and 'image_file' not in info else info.get('image_file'), **info } for id, info in self._recording_info.items() if device_id is None or id == device_id }, disable_logging=True) return resp
def send_response(self, response, request, **kwargs): """ Send a response message on the backend Params: response -- The response, either a dict, a string/bytes UTF-8 JSON, or a platypush.message.response.Response object request -- Associated request, used to set the response parameters that will link them """ response = Response.build(response) assert isinstance(response, Response) assert isinstance(request, Request) response.id = request.id response.target = request.origin response.origin = self.device_id self.send_message(response, **kwargs)
def get_measurement(self): mcp = self._get_mcp() values = {} for i in range(self.N_CHANNELS): value = self._convert_to_voltage(mcp.read_adc(i)) if self.channels: if i in self.channels: channel = self.channels[i] if 'conv_function' in channel: x = value value = eval(channel['conv_function']) values[channel['name']] = value else: values[i] = value return Response(output=values)
def say(self, phrase, lang=None): if lang is None: lang=self.lang output = None errors = [] cmd = ['mplayer -ao alsa -really-quiet -noconsolecontrols ' + '"http://translate.google.com/translate_tts?{}"' .format(urllib.parse.urlencode({ 'ie' : 'UTF-8', 'client' : 'tw-ob', 'tl' : lang, 'q' : phrase, }))] try: output = subprocess.check_output( cmd, stderr=subprocess.STDOUT, shell=True).decode('utf-8') except subprocess.CalledProcessError as e: errors = [e.output.decode('utf-8')] return Response(output=output, errors=errors)
def _execute_action(*args, **kwargs): response = Response() result = f(*args, **kwargs) if result and isinstance(result, Response): result.errors = result.errors \ if isinstance(result.errors, list) else [result.errors] response = result elif isinstance(result, tuple) and len(result) == 2: response.errors = result[1] \ if isinstance(result[1], list) else [result[1]] if len(response.errors) == 1 and response.errors[0] is None: response.errors = [] response.output = result[0] else: response = Response(output=result, errors=[]) return response