forked from platypush/platypush
Support for casting torrents to Chromecast
This commit is contained in:
parent
3798414f22
commit
dc2a686d23
5 changed files with 134 additions and 71 deletions
|
@ -22,7 +22,7 @@ class MediaPlugin(Plugin):
|
||||||
|
|
||||||
Requires:
|
Requires:
|
||||||
|
|
||||||
* A media player installed (supported so far: mplayer, omxplayer)
|
* A media player installed (supported so far: mplayer, omxplayer, chromecast)
|
||||||
* **python-libtorrent** (``pip install python-libtorrent``), optional for Torrent support
|
* **python-libtorrent** (``pip install python-libtorrent``), optional for Torrent support
|
||||||
* **youtube-dl** installed on your system (see your distro instructions), optional for YouTube support
|
* **youtube-dl** installed on your system (see your distro instructions), optional for YouTube support
|
||||||
"""
|
"""
|
||||||
|
@ -53,7 +53,8 @@ class MediaPlugin(Plugin):
|
||||||
'f4b',
|
'f4b',
|
||||||
}
|
}
|
||||||
|
|
||||||
_supported_media_plugins = { 'media.mplayer', 'media.omxplayer' }
|
_supported_media_plugins = {'media.mplayer', 'media.omxplayer',
|
||||||
|
'media.chromecast'}
|
||||||
|
|
||||||
def __init__(self, media_dirs=[], download_dir=None, env=None,
|
def __init__(self, media_dirs=[], download_dir=None, env=None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
|
@ -75,10 +76,17 @@ class MediaPlugin(Plugin):
|
||||||
|
|
||||||
player = None
|
player = None
|
||||||
player_config = {}
|
player_config = {}
|
||||||
|
|
||||||
|
if self.__class__.__name__ == 'MediaPlugin':
|
||||||
|
# Abstract class, initialize with the default configured player
|
||||||
for plugin in Config.get_plugins().keys():
|
for plugin in Config.get_plugins().keys():
|
||||||
if plugin in self._supported_media_plugins:
|
if plugin in self._supported_media_plugins:
|
||||||
player = plugin
|
player = plugin
|
||||||
|
if get_plugin(player).is_local():
|
||||||
|
# Local players have priority as default if configured
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
player = self # Derived concrete class
|
||||||
|
|
||||||
if not player:
|
if not player:
|
||||||
raise AttributeError('No media plugin configured')
|
raise AttributeError('No media plugin configured')
|
||||||
|
@ -126,6 +134,10 @@ class MediaPlugin(Plugin):
|
||||||
|
|
||||||
if resource.startswith('youtube:') \
|
if resource.startswith('youtube:') \
|
||||||
or resource.startswith('https://www.youtube.com/watch?v='):
|
or resource.startswith('https://www.youtube.com/watch?v='):
|
||||||
|
if self.__class.__.__name__ != 'MediaChromecastPlugin':
|
||||||
|
# The Chromecast has already its way to handle YouTube
|
||||||
|
return resource
|
||||||
|
|
||||||
resource = self._get_youtube_content(resource)
|
resource = self._get_youtube_content(resource)
|
||||||
elif resource.startswith('magnet:?'):
|
elif resource.startswith('magnet:?'):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -3,15 +3,18 @@ import pychromecast
|
||||||
|
|
||||||
from pychromecast.controllers.youtube import YouTubeController
|
from pychromecast.controllers.youtube import YouTubeController
|
||||||
|
|
||||||
|
from platypush.context import get_plugin
|
||||||
from platypush.plugins import Plugin, action
|
from platypush.plugins import Plugin, action
|
||||||
|
from platypush.plugins.media import MediaPlugin
|
||||||
|
|
||||||
|
|
||||||
class MediaChromecastPlugin(Plugin):
|
class MediaChromecastPlugin(MediaPlugin):
|
||||||
"""
|
"""
|
||||||
Plugin to interact with Chromecast devices
|
Plugin to interact with Chromecast devices
|
||||||
|
|
||||||
Supported formats:
|
Supported formats:
|
||||||
|
|
||||||
|
* HTTP media URLs
|
||||||
* YouTube URLs
|
* YouTube URLs
|
||||||
* Plex (through ``media.plex`` plugin, experimental)
|
* Plex (through ``media.plex`` plugin, experimental)
|
||||||
|
|
||||||
|
@ -32,6 +35,7 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self._is_local = False
|
||||||
self.chromecast = chromecast
|
self.chromecast = chromecast
|
||||||
self.chromecasts = {}
|
self.chromecasts = {}
|
||||||
|
|
||||||
|
@ -67,7 +71,10 @@ class MediaChromecastPlugin(Plugin):
|
||||||
} for cc in pychromecast.get_chromecasts() ]
|
} for cc in pychromecast.get_chromecasts() ]
|
||||||
|
|
||||||
|
|
||||||
def get_chromecast(self, chromecast=None):
|
def get_chromecast(self, chromecast=None, n_tries=3):
|
||||||
|
if isinstance(chromecast, pychromecast.Chromecast):
|
||||||
|
return chromecast
|
||||||
|
|
||||||
if not chromecast:
|
if not chromecast:
|
||||||
if not self.chromecast:
|
if not self.chromecast:
|
||||||
raise RuntimeError('No Chromecast specified nor default Chromecast configured')
|
raise RuntimeError('No Chromecast specified nor default Chromecast configured')
|
||||||
|
@ -75,10 +82,17 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
if chromecast not in self.chromecasts:
|
if chromecast not in self.chromecasts:
|
||||||
self.chromecasts = {
|
casts = {}
|
||||||
|
while n_tries > 0:
|
||||||
|
n_tries -= 1
|
||||||
|
casts.update({
|
||||||
cast.device.friendly_name: cast
|
cast.device.friendly_name: cast
|
||||||
for cast in pychromecast.get_chromecasts()
|
for cast in pychromecast.get_chromecasts()
|
||||||
}
|
})
|
||||||
|
|
||||||
|
if chromecast in casts:
|
||||||
|
self.chromecasts.update(casts)
|
||||||
|
break
|
||||||
|
|
||||||
if chromecast not in self.chromecasts:
|
if chromecast not in self.chromecasts:
|
||||||
raise RuntimeError('Device {} not found'.format(chromecast))
|
raise RuntimeError('Device {} not found'.format(chromecast))
|
||||||
|
@ -87,7 +101,7 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def cast_media(self, media, content_type=None, chromecast=None, title=None,
|
def play(self, resource, content_type=None, chromecast=None, title=None,
|
||||||
image_url=None, autoplay=True, current_time=0,
|
image_url=None, autoplay=True, current_time=0,
|
||||||
stream_type=STREAM_TYPE_BUFFERED, subtitles=None,
|
stream_type=STREAM_TYPE_BUFFERED, subtitles=None,
|
||||||
subtitles_lang='en-US', subtitles_mime='text/vtt',
|
subtitles_lang='en-US', subtitles_mime='text/vtt',
|
||||||
|
@ -95,10 +109,10 @@ class MediaChromecastPlugin(Plugin):
|
||||||
"""
|
"""
|
||||||
Cast media to a visible Chromecast
|
Cast media to a visible Chromecast
|
||||||
|
|
||||||
:param media: Media to cast
|
:param resource: Media to cast
|
||||||
:type media: str
|
:type resource: str
|
||||||
|
|
||||||
:param content_type: Content type
|
:param content_type: Content type as a MIME type string
|
||||||
:type content_type: str
|
:type content_type: str
|
||||||
|
|
||||||
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
||||||
|
@ -139,7 +153,7 @@ class MediaChromecastPlugin(Plugin):
|
||||||
cast.wait()
|
cast.wait()
|
||||||
|
|
||||||
mc = cast.media_controller
|
mc = cast.media_controller
|
||||||
yt = self._get_youtube_url(media)
|
yt = self._get_youtube_url(resource)
|
||||||
|
|
||||||
if yt:
|
if yt:
|
||||||
self.logger.info('Playing YouTube video {} on {}'.format(
|
self.logger.info('Playing YouTube video {} on {}'.format(
|
||||||
|
@ -150,13 +164,33 @@ class MediaChromecastPlugin(Plugin):
|
||||||
hndl.update_screen_id()
|
hndl.update_screen_id()
|
||||||
return hndl.play_video(yt)
|
return hndl.play_video(yt)
|
||||||
|
|
||||||
|
resource = self._get_resource(resource)
|
||||||
|
if resource.startswith('magnet:?'):
|
||||||
|
player_args = { 'chromecast': cast }
|
||||||
|
return get_plugin('media.webtorrent').play(resource,
|
||||||
|
player='chromecast',
|
||||||
|
**player_args)
|
||||||
|
|
||||||
|
# Best effort from the extension
|
||||||
|
if not content_type:
|
||||||
|
for ext in self.video_extensions:
|
||||||
|
if ('.' + ext).lower() in resource.lower():
|
||||||
|
content_type = 'video/' + ext
|
||||||
|
break
|
||||||
|
|
||||||
|
if not content_type:
|
||||||
|
for ext in self.audio_extensions:
|
||||||
|
if ('.' + ext).lower() in resource.lower():
|
||||||
|
content_type = 'audio/' + ext
|
||||||
|
break
|
||||||
|
|
||||||
if not content_type:
|
if not content_type:
|
||||||
raise RuntimeError('content_type required to process media {}'.
|
raise RuntimeError('content_type required to process media {}'.
|
||||||
format(media))
|
format(resource))
|
||||||
|
|
||||||
self.logger.info('Playing {} on {}'.format(media, chromecast))
|
self.logger.info('Playing {} on {}'.format(resource, chromecast))
|
||||||
|
|
||||||
mc.play_media(media, content_type, title=title, thumb=image_url,
|
mc.play_media(resource, content_type, title=title, thumb=image_url,
|
||||||
current_time=current_time, autoplay=autoplay,
|
current_time=current_time, autoplay=autoplay,
|
||||||
stream_type=stream_type, subtitles=subtitles,
|
stream_type=stream_type, subtitles=subtitles,
|
||||||
subtitles_lang=subtitles_lang, subtitles_mime=subtitles_mime,
|
subtitles_lang=subtitles_lang, subtitles_mime=subtitles_mime,
|
||||||
|
@ -177,19 +211,12 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def play(self, chromecast=None):
|
def load(self, *args, **kwargs):
|
||||||
return self.get_chromecast(chromecast or self.chromecast).media_controller.play()
|
return self.play(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def pause(self, chromecast=None):
|
def pause(self, chromecast=None):
|
||||||
return self.get_chromecast(chromecast or self.chromecast).media_controller.pause()
|
|
||||||
|
|
||||||
|
|
||||||
@action
|
|
||||||
def toggle_pause(self, chromecast=None):
|
|
||||||
cast = self.get_chromecast(chromecast or self.chromecast)
|
cast = self.get_chromecast(chromecast or self.chromecast)
|
||||||
if cast.media_controller.is_paused:
|
if cast.media_controller.is_paused:
|
||||||
return cast.media_controller.play()
|
return cast.media_controller.play()
|
||||||
|
@ -208,22 +235,25 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def seek(self, location, chromecast=None):
|
def set_position(self, position, chromecast=None):
|
||||||
return self.get_chromecast(chromecast or self.chromecast).media_controller.seek(location)
|
return self.get_chromecast(chromecast or self.chromecast).media_controller.seek(position)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def seek(self, position, chromecast=None):
|
||||||
|
return self.forward(chromecast=chromecast, offset=position)
|
||||||
|
|
||||||
|
@action
|
||||||
|
def back(self, chromecast=None, offset=60):
|
||||||
|
mc = self.get_chromecast(chromecast or self.chromecast).media_controller
|
||||||
|
if mc.status.current_time:
|
||||||
|
return mc.seek(mc.status.current_time-offset)
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def back(self, chromecast=None, delta=30):
|
def forward(self, chromecast=None, offset=60):
|
||||||
mc = self.get_chromecast(chromecast or self.chromecast).media_controller
|
mc = self.get_chromecast(chromecast or self.chromecast).media_controller
|
||||||
if mc.status.current_time:
|
if mc.status.current_time:
|
||||||
return mc.seek(mc.status.current_time-delta)
|
return mc.seek(mc.status.current_time+offset)
|
||||||
|
|
||||||
|
|
||||||
@action
|
|
||||||
def forward(self, chromecast=None, delta=30):
|
|
||||||
mc = self.get_chromecast(chromecast or self.chromecast).media_controller
|
|
||||||
if mc.status.current_time:
|
|
||||||
return mc.seek(mc.status.current_time+delta)
|
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
@ -288,7 +318,7 @@ class MediaChromecastPlugin(Plugin):
|
||||||
cast.join(timeout=timeout, blocking=blocking)
|
cast.join(timeout=timeout, blocking=blocking)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def quit_app(self, chromecast=None):
|
def quit(self, chromecast=None):
|
||||||
"""
|
"""
|
||||||
Exits the current app on the Chromecast
|
Exits the current app on the Chromecast
|
||||||
|
|
||||||
|
@ -327,41 +357,41 @@ class MediaChromecastPlugin(Plugin):
|
||||||
cast.set_volume(volume/100)
|
cast.set_volume(volume/100)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def volume_up(self, chromecast=None, delta=10):
|
def volup(self, chromecast=None, step=10):
|
||||||
"""
|
"""
|
||||||
Turn up the Chromecast volume by 10% or delta.
|
Turn up the Chromecast volume by 10% or step.
|
||||||
|
|
||||||
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
||||||
:type chromecast: str
|
:type chromecast: str
|
||||||
|
|
||||||
:param delta: Volume increment between 0 and 100 (default: 100%)
|
:param step: Volume increment between 0 and 100 (default: 100%)
|
||||||
:type delta: float
|
:type step: float
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cast = self.get_chromecast(chromecast)
|
cast = self.get_chromecast(chromecast)
|
||||||
delta /= 100
|
step /= 100
|
||||||
cast.volume_up(min(delta, 1))
|
cast.volume_up(min(step, 1))
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def volume_down(self, chromecast=None, delta=10):
|
def voldown(self, chromecast=None, step=10):
|
||||||
"""
|
"""
|
||||||
Turn down the Chromecast volume by 10% or delta.
|
Turn down the Chromecast volume by 10% or step.
|
||||||
|
|
||||||
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
:param chromecast: Chromecast to cast to. If none is specified, then the default configured Chromecast will be used.
|
||||||
:type chromecast: str
|
:type chromecast: str
|
||||||
|
|
||||||
:param delta: Volume decrement between 0 and 100 (default: 100%)
|
:param step: Volume decrement between 0 and 100 (default: 100%)
|
||||||
:type delta: float
|
:type step: float
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cast = self.get_chromecast(chromecast)
|
cast = self.get_chromecast(chromecast)
|
||||||
delta /= 100
|
step /= 100
|
||||||
cast.volume_down(max(delta, 0))
|
cast.volume_down(max(step, 0))
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def toggle_mute(self, chromecast=None):
|
def mute(self, chromecast=None):
|
||||||
"""
|
"""
|
||||||
Toggle the mute status on the Chromecast
|
Toggle the mute status on the Chromecast
|
||||||
|
|
||||||
|
@ -374,4 +404,3 @@ class MediaChromecastPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
||||||
|
|
|
@ -330,14 +330,14 @@ class MediaMplayerPlugin(MediaPlugin):
|
||||||
return self._exec('mute')
|
return self._exec('mute')
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def seek(self, relative_position):
|
def seek(self, position):
|
||||||
"""
|
"""
|
||||||
Seek backward/forward by the specified number of seconds
|
Seek backward/forward by the specified number of seconds
|
||||||
|
|
||||||
:param relative_position: Number of seconds relative to the current cursor
|
:param relative_position: Number of seconds relative to the current cursor
|
||||||
:type relative_position: int
|
:type relative_position: int
|
||||||
"""
|
"""
|
||||||
return self.step_property('time_pos', offset)
|
return self.step_property('time_pos', position)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def set_position(self, position):
|
def set_position(self, position):
|
||||||
|
|
|
@ -17,7 +17,7 @@ from platypush.message.event.torrent import TorrentDownloadStartEvent, \
|
||||||
|
|
||||||
from platypush.plugins import action
|
from platypush.plugins import action
|
||||||
from platypush.utils import find_bins_in_path, find_files_by_ext, \
|
from platypush.utils import find_bins_in_path, find_files_by_ext, \
|
||||||
is_process_alive
|
is_process_alive, get_ip_or_hostname
|
||||||
|
|
||||||
|
|
||||||
class TorrentState(enum.Enum):
|
class TorrentState(enum.Enum):
|
||||||
|
@ -26,6 +26,7 @@ class TorrentState(enum.Enum):
|
||||||
DOWNLOADING = 3
|
DOWNLOADING = 3
|
||||||
DOWNLOADED = 4
|
DOWNLOADED = 4
|
||||||
|
|
||||||
|
|
||||||
class MediaWebtorrentPlugin(MediaPlugin):
|
class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
"""
|
"""
|
||||||
Plugin to download and stream videos using webtorrent
|
Plugin to download and stream videos using webtorrent
|
||||||
|
@ -118,7 +119,7 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
return re.sub('\x1b\[((\d+m)|(.{1,2}))', '', line).strip()
|
return re.sub('\x1b\[((\d+m)|(.{1,2}))', '', line).strip()
|
||||||
|
|
||||||
|
|
||||||
def _process_monitor(self, resource, download_dir):
|
def _process_monitor(self, resource, download_dir, player_type, player_args):
|
||||||
def _thread():
|
def _thread():
|
||||||
if not self._webtorrent_process:
|
if not self._webtorrent_process:
|
||||||
return
|
return
|
||||||
|
@ -162,6 +163,9 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
# Streaming started
|
# Streaming started
|
||||||
webtorrent_url = re.search('server running at: (.+?)$',
|
webtorrent_url = re.search('server running at: (.+?)$',
|
||||||
line, flags=re.IGNORECASE).group(1)
|
line, flags=re.IGNORECASE).group(1)
|
||||||
|
webtorrent_url = webtorrent_url.replace(
|
||||||
|
'http://localhost', 'http://' + get_ip_or_hostname())
|
||||||
|
|
||||||
self.logger.info('Torrent stream started on {}'.format(
|
self.logger.info('Torrent stream started on {}'.format(
|
||||||
webtorrent_url))
|
webtorrent_url))
|
||||||
|
|
||||||
|
@ -215,17 +219,19 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
player = get_plugin('media.' + player_type) if player_type \
|
||||||
|
else self._media_plugin
|
||||||
|
|
||||||
|
media = media_file if player.is_local() else webtorrent_url
|
||||||
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'Starting playback of {} to {} through {}'.format(
|
'Starting playback of {} to {} through {}'.format(
|
||||||
media_file, self._media_plugin.__class__.__name__,
|
media_file, player.__class__.__name__,
|
||||||
webtorrent_url))
|
webtorrent_url))
|
||||||
|
|
||||||
media = media_file if self._media_plugin.is_local() \
|
player.play(media, **player_args)
|
||||||
else webtorrent_url
|
|
||||||
|
|
||||||
self._media_plugin.play(media)
|
|
||||||
self.logger.info('Waiting for player to terminate')
|
self.logger.info('Waiting for player to terminate')
|
||||||
self._wait_for_player()
|
self._wait_for_player(player)
|
||||||
self.logger.info('Torrent player terminated')
|
self.logger.info('Torrent player terminated')
|
||||||
bus.post(TorrentDownloadCompletedEvent(resource=resource))
|
bus.post(TorrentDownloadCompletedEvent(resource=resource))
|
||||||
|
|
||||||
|
@ -235,17 +241,17 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
|
|
||||||
return _thread
|
return _thread
|
||||||
|
|
||||||
def _wait_for_player(self):
|
def _wait_for_player(self, player):
|
||||||
media_cls = self._media_plugin.__class__.__name__
|
media_cls = player.__class__.__name__
|
||||||
stop_evt = None
|
stop_evt = None
|
||||||
|
|
||||||
if media_cls == 'MediaMplayerPlugin':
|
if media_cls == 'MediaMplayerPlugin':
|
||||||
stop_evt = self._media_plugin._mplayer_stopped_event
|
stop_evt = player._mplayer_stopped_event
|
||||||
elif media_cls == 'MediaOmxplayerPlugin':
|
elif media_cls == 'MediaOmxplayerPlugin':
|
||||||
stop_evt = threading.Event()
|
stop_evt = threading.Event()
|
||||||
def stop_callback():
|
def stop_callback():
|
||||||
stop_evt.set()
|
stop_evt.set()
|
||||||
self._media_plugin.add_handler('stop', stop_callback)
|
player.add_handler('stop', stop_callback)
|
||||||
|
|
||||||
if stop_evt:
|
if stop_evt:
|
||||||
stop_evt.wait()
|
stop_evt.wait()
|
||||||
|
@ -264,13 +270,22 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def play(self, resource):
|
def play(self, resource, player=None, **player_args):
|
||||||
"""
|
"""
|
||||||
Download and stream a torrent
|
Download and stream a torrent
|
||||||
|
|
||||||
:param resource: Play a resource, as a magnet link, torrent URL or
|
:param resource: Play a resource, as a magnet link, torrent URL or
|
||||||
torrent file path
|
torrent file path
|
||||||
:type resource: str
|
:type resource: str
|
||||||
|
|
||||||
|
:param player: If set, use this plugin type as a player for the
|
||||||
|
torrent. Supported types: 'mplayer', 'omxplayer', 'chromecast'.
|
||||||
|
If not set, then the default configured media plugin will be used.
|
||||||
|
:type player: str
|
||||||
|
|
||||||
|
:param player_args: Any arguments to pass to the player plugin's
|
||||||
|
play() method
|
||||||
|
:type player_args: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self._webtorrent_process:
|
if self._webtorrent_process:
|
||||||
|
@ -291,7 +306,8 @@ class MediaWebtorrentPlugin(MediaPlugin):
|
||||||
stdout=subprocess.PIPE)
|
stdout=subprocess.PIPE)
|
||||||
|
|
||||||
threading.Thread(target=self._process_monitor(
|
threading.Thread(target=self._process_monitor(
|
||||||
resource=resource, download_dir=download_dir)).start()
|
resource=resource, download_dir=download_dir,
|
||||||
|
player_type=player, player_args=player_args)).start()
|
||||||
return { 'resource': resource }
|
return { 'resource': resource }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
|
import socket
|
||||||
import ssl
|
import ssl
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -210,4 +211,9 @@ def is_process_alive(pid):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_ip_or_hostname():
|
||||||
|
ip = socket.gethostbyname(socket.gethostname())
|
||||||
|
return socket.getfqdn() if ip.startswith('127.') else ip
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
Loading…
Reference in a new issue