|
""" |
|
MIT License |
|
|
|
Copyright (C) 2021 ROCKY4546 |
|
https://github.com/rocky4546 |
|
|
|
This file is part of Cabernet |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
|
and associated documentation files (the "Software"), to deal in the Software without restriction, |
|
including without limitation the rights to use, copy, modify, merge, publish, distribute, |
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software |
|
is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included in all copies or |
|
substantial portions of the Software. |
|
""" |
|
|
|
import logging |
|
|
|
from lib.web.pages.templates import web_templates |
|
from lib.clients.web_handler import WebHTTPHandler |
|
import lib.common.utils as utils |
|
|
|
|
|
class Stream: |
|
logger = None |
|
|
|
def __init__(self, _plugins, _hdhr_queue): |
|
self.plugins = _plugins |
|
self.namespace = '' |
|
self.instance = '' |
|
self.config = self.plugins.config_obj.data |
|
self.hdhr_queue = _hdhr_queue |
|
if Stream.logger is None: |
|
Stream.logger = logging.getLogger(__name__) |
|
|
|
def put_hdhr_queue(self, _namespace, _index, _channel, _status): |
|
if not self.config['hdhomerun']['disable_hdhr']: |
|
self.hdhr_queue.put( |
|
{'namespace': _namespace, 'tuner': _index, |
|
'channel': _channel, 'status': _status}) |
|
|
|
def find_tuner(self, _namespace, _instance, _ch_num, _isvod): |
|
|
|
found = -1 |
|
scan_list = WebHTTPHandler.rmg_station_scans[_namespace] |
|
for index, scan_status in enumerate(scan_list): |
|
|
|
if scan_status == 'Idle' and found == -1: |
|
found = index |
|
elif isinstance(scan_status, dict): |
|
if scan_status['instance'] == _instance \ |
|
and scan_status['ch'] == _ch_num \ |
|
and not _isvod \ |
|
and scan_status['mux'] \ |
|
and not scan_status['mux'].terminate_requested: |
|
found = index |
|
break |
|
if found == -1: |
|
return found |
|
if WebHTTPHandler.rmg_station_scans[_namespace][index] != 'Idle': |
|
self.logger.debug('Reusing tuner {} {}:{} ch:{}'.format(found, _namespace, _instance, _ch_num)) |
|
else: |
|
self.logger.debug('Adding new tuner {} for stream {}:{} ch:{}'.format(found, _namespace, _instance, _ch_num)) |
|
WebHTTPHandler.rmg_station_scans[_namespace][found] = { \ |
|
'instance': _instance, |
|
'ch': _ch_num, |
|
'mux': None, |
|
'status': 'Starting'} |
|
self.put_hdhr_queue(_namespace, index, _ch_num, 'Stream') |
|
return found |
|
|
|
def set_service_name(self, _channel_dict): |
|
updated_chnum = utils.wrap_chnum( |
|
str(_channel_dict['display_number']), _channel_dict['namespace'], |
|
_channel_dict['instance'], self.config) |
|
|
|
if self.config['epg']['epg_channel_number']: |
|
service_name = updated_chnum + \ |
|
' ' + _channel_dict['display_name'] |
|
else: |
|
service_name = _channel_dict['display_name'] |
|
return service_name |
|
|
|
def get_stream_uri(self, _channel_dict): |
|
return self.plugins.plugins[_channel_dict['namespace']] \ |
|
.plugin_obj.get_channel_uri_ext(_channel_dict['uid'], _channel_dict['instance']) |
|
|
|
def gen_response(self, _namespace, _instance, _ch_num, _isvod): |
|
""" |
|
Returns dict where the dict is consistent with |
|
the method do_dict_response requires as an argument |
|
A code other than 200 means do not tune |
|
dict also include a "tuner_index" that informs caller what tuner is allocated |
|
""" |
|
self.namespace = _namespace |
|
self.instance = _instance |
|
i = self.find_tuner(_namespace, _instance, _ch_num, _isvod) |
|
if i >= 0: |
|
return { |
|
'tuner': i, |
|
'code': 200, |
|
'headers': {'Content-type': 'video/MP2T;'}, |
|
'text': None} |
|
else: |
|
self.logger.warning( |
|
'All tuners already in use [{}][{}] max tuners: {}' |
|
.format(_namespace, _instance, len(WebHTTPHandler.rmg_station_scans[_namespace]))) |
|
return { |
|
'tuner': i, |
|
'code': 400, |
|
'headers': {'Content-type': 'text/html'}, |
|
'text': web_templates['htmlError'].format('400 - All tuners already in use.')} |
|
|
|
@property |
|
def config_section(self): |
|
return utils.instance_config_section(self.namespace, self.instance) |
|
|