mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-11 07:46:07 -07:00
Add more source media parameters
This commit is contained in:
parent
c01731ebe9
commit
a46b24213b
7 changed files with 454 additions and 212 deletions
|
@ -93,10 +93,10 @@ DOCUMENTATION :: END
|
||||||
% else:
|
% else:
|
||||||
% if data['art']:
|
% if data['art']:
|
||||||
<!--Hacky solution to escape the image url until I come up with something better-->
|
<!--Hacky solution to escape the image url until I come up with something better-->
|
||||||
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['art'])}&width=500&height=280&fallback=art);"></div>
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['art'])}&width=500&height=280&fallback=art&clip=true);"></div>
|
||||||
% else:
|
% else:
|
||||||
<!--Hacky solution to escape the image url until I come up with something better-->
|
<!--Hacky solution to escape the image url until I come up with something better-->
|
||||||
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['thumb'])}&width=500&height=280&fallback=art);"></div>
|
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['thumb'])}&width=500&height=280&fallback=art&clip=true);"></div>
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
% elif data['media_type'] == 'photo':
|
% elif data['media_type'] == 'photo':
|
||||||
|
|
|
@ -1586,13 +1586,21 @@
|
||||||
<td><strong>{username}</strong></td>
|
<td><strong>{username}</strong></td>
|
||||||
<td>The username of the person streaming.</td>
|
<td>The username of the person streaming.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{device}</strong></td>
|
||||||
|
<td>The type of client device being used for playback.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{platform}</strong></td>
|
<td><strong>{platform}</strong></td>
|
||||||
<td>The type of client being used for playback.</td>
|
<td>The type of client platform being used for playback.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{product}</strong></td>
|
||||||
|
<td>The type of client product being used for playback.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{player}</strong></td>
|
<td><strong>{player}</strong></td>
|
||||||
<td>The name of the device being used for playback.</td>
|
<td>The name of the player being used for playback.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{ip_address}</strong></td>
|
<td><strong>{ip_address}</strong></td>
|
||||||
|
@ -1644,12 +1652,16 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{quality_profile}</strong></td>
|
<td><strong>{quality_profile}</strong></td>
|
||||||
<td>The Plex quality profile of the stream. <span class="small-muted">(e.g. 4 Mbps 720p)</span></td>
|
<td>The Plex quality profile of the stream. <span class="small-muted">(e.g. Original, 4 Mbps 720p, etc.)</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{optimized_version}</strong></td>
|
<td><strong>{optimized_version}</strong></td>
|
||||||
<td>If the stream is an optimized version. <span class="small-muted">(0 or 1)</span></td>
|
<td>If the stream is an optimized version. <span class="small-muted">(0 or 1)</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{optimized_version_profile}</strong></td>
|
||||||
|
<td>The optimized version profile of the stream.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_local}</strong></td>
|
<td><strong>{stream_local}</strong></td>
|
||||||
<td>If the stream is local. <span class="small-muted">(0 or 1)</span></td>
|
<td>If the stream is local. <span class="small-muted">(0 or 1)</span></td>
|
||||||
|
@ -1681,14 +1693,26 @@
|
||||||
<td><strong>{stream_video_codec}</strong></td>
|
<td><strong>{stream_video_codec}</strong></td>
|
||||||
<td>The video codec of the stream.</td>
|
<td>The video codec of the stream.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_video_codec_level}</strong></td>
|
||||||
|
<td>The video codec level of the stream.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_video_bitrate}</strong></td>
|
<td><strong>{stream_video_bitrate}</strong></td>
|
||||||
<td>The video bitrate (in kbps) of the stream.</td>
|
<td>The video bitrate (in kbps) of the stream.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_video_bit_depth}</strong></td>
|
||||||
|
<td>The video bit depth of the stream.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_video_framerate}</strong></td>
|
<td><strong>{stream_video_framerate}</strong></td>
|
||||||
<td>The video framerate of the stream.</td>
|
<td>The video framerate of the stream.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_video_ref_frames}</strong></td>
|
||||||
|
<td>The video reference frames of the stream.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_video_resolution}</strong></td>
|
<td><strong>{stream_video_resolution}</strong></td>
|
||||||
<td>The video resolution of the stream.</td>
|
<td>The video resolution of the stream.</td>
|
||||||
|
@ -1715,7 +1739,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_audio_bitrate_mode}</strong></td>
|
<td><strong>{stream_audio_bitrate_mode}</strong></td>
|
||||||
<td>The audio bitrage mode of the stream. <span class="small-muted">(cbr or vbr)</span></td>
|
<td>The audio bitrate mode of the stream. <span class="small-muted">(cbr or vbr)</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_audio_codec}</strong></td>
|
<td><strong>{stream_audio_codec}</strong></td>
|
||||||
|
@ -1725,6 +1749,14 @@
|
||||||
<td><strong>{stream_audio_channels}</strong></td>
|
<td><strong>{stream_audio_channels}</strong></td>
|
||||||
<td>The audio channels of the stream.</td>
|
<td>The audio channels of the stream.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_audio_channel_layout}</strong></td>
|
||||||
|
<td>The audio channel layout of the stream.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_audio_sample_rate}</strong></td>
|
||||||
|
<td>The audio sample rate (in Hz) of the stream.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_audio_language}</strong></td>
|
<td><strong>{stream_audio_language}</strong></td>
|
||||||
<td>The audio language of the stream.</td>
|
<td>The audio language of the stream.</td>
|
||||||
|
@ -1745,6 +1777,10 @@
|
||||||
<td><strong>{stream_subtitle_format}</strong></td>
|
<td><strong>{stream_subtitle_format}</strong></td>
|
||||||
<td>The subtitle format of the stream.</td>
|
<td>The subtitle format of the stream.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{stream_subtitle_forced}</strong></td>
|
||||||
|
<td>If the subtitles are forced. <span class="small-muted">(0 or 1)</span></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{stream_subtitle_language}</strong></td>
|
<td><strong>{stream_subtitle_language}</strong></td>
|
||||||
<td>The subtitle language of the stream.</td>
|
<td>The subtitle language of the stream.</td>
|
||||||
|
@ -1820,46 +1856,6 @@
|
||||||
<td><strong>{media_type}</strong></td>
|
<td><strong>{media_type}</strong></td>
|
||||||
<td>The type of media. <span class="small-muted">(movie, show, season, episode, artist, album, track)</span></td>
|
<td>The type of media. <span class="small-muted">(movie, show, season, episode, artist, album, track)</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td><strong>{container}</strong></td>
|
|
||||||
<td>The media container of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{aspect_ratio}</strong></td>
|
|
||||||
<td>The aspect ratio of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_codec}</strong></td>
|
|
||||||
<td>The video codec of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_bitrate}</strong></td>
|
|
||||||
<td>The video bitrate of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_framerate}</strong></td>
|
|
||||||
<td>The video framerate of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_resolution}</strong></td>
|
|
||||||
<td>The video resolution of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_width}</strong></td>
|
|
||||||
<td>The video width of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{video_height}</strong></td>
|
|
||||||
<td>The video height of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{audio_codec}</strong></td>
|
|
||||||
<td>The audio codec of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><strong>{audio_channels}</strong></td>
|
|
||||||
<td>The audio channels of the original media.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{title}</strong></td>
|
<td><strong>{title}</strong></td>
|
||||||
<td>The full title of the item.</td>
|
<td>The full title of the item.</td>
|
||||||
|
@ -2037,6 +2033,118 @@
|
||||||
<td><strong>{trakt_url}</strong></td>
|
<td><strong>{trakt_url}</strong></td>
|
||||||
<td>The trakt.tv URL for the movie or TV show.</td>
|
<td>The trakt.tv URL for the movie or TV show.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{container}</strong></td>
|
||||||
|
<td>The media container of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{bitrate}</strong></td>
|
||||||
|
<td>The bitrate of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{aspect_ratio}</strong></td>
|
||||||
|
<td>The aspect ratio of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_codec}</strong></td>
|
||||||
|
<td>The video codec of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_codec_level}</strong></td>
|
||||||
|
<td>The video codec level of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_bitrate}</strong></td>
|
||||||
|
<td>The video bitrate of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_bit_depth}</strong></td>
|
||||||
|
<td>The video bit depth of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_framerate}</strong></td>
|
||||||
|
<td>The video framerate of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_ref_frames}</strong></td>
|
||||||
|
<td>The video reference frames of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_resolution}</strong></td>
|
||||||
|
<td>The video resolution of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_height}</strong></td>
|
||||||
|
<td>The video height of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_width}</strong></td>
|
||||||
|
<td>The video width of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_language}</strong></td>
|
||||||
|
<td>The video language of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{video_language_code}</strong></td>
|
||||||
|
<td>The video language code of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_bitrate}</strong></td>
|
||||||
|
<td>The audio bitrate of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_bitrate_mode}</strong></td>
|
||||||
|
<td>The audio bitrate mode of the original media. <span class="small-muted">(cbr or vbr)</span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_codec}</strong></td>
|
||||||
|
<td>The audio codec of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_channels}</strong></td>
|
||||||
|
<td>The audio channels of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_channel_layout}</strong></td>
|
||||||
|
<td>The audio channel layout of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_language}</strong></td>
|
||||||
|
<td>The audio language of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{audio_language_code}</strong></td>
|
||||||
|
<td>The audio language code of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_codec}</strong></td>
|
||||||
|
<td>The subtitle codec of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_container}</strong></td>
|
||||||
|
<td>The subtitle container of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_format}</strong></td>
|
||||||
|
<td>The subtitle format of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_forced}</strong></td>
|
||||||
|
<td>If the subtitles are forced. <span class="small-muted">(0 or 1)</span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_location}</strong></td>
|
||||||
|
<td>The subtitle location of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_language}</strong></td>
|
||||||
|
<td>The subtitle language of the original media.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>{subtitle_language_code}</strong></td>
|
||||||
|
<td>The subtitle language code of the original media.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>{file}</strong></td>
|
<td><strong>{file}</strong></td>
|
||||||
<td>The file path to the item.</td>
|
<td>The file path to the item.</td>
|
||||||
|
|
|
@ -36,69 +36,69 @@ class ActivityProcessor(object):
|
||||||
|
|
||||||
def write_session(self, session=None, notify=True):
|
def write_session(self, session=None, notify=True):
|
||||||
if session:
|
if session:
|
||||||
values = {'session_key': session['session_key'],
|
values = {'session_key': session.get('session_key', ''),
|
||||||
'transcode_key': session['transcode_key'],
|
'transcode_key': session.get('transcode_key', ''),
|
||||||
'section_id': session['section_id'],
|
'section_id': session.get('section_id', ''),
|
||||||
'rating_key': session['rating_key'],
|
'rating_key': session.get('rating_key', ''),
|
||||||
'media_type': session['media_type'],
|
'media_type': session.get('media_type', ''),
|
||||||
'state': session['state'],
|
'state': session.get('state', ''),
|
||||||
'user_id': session['user_id'],
|
'user_id': session.get('user_id', ''),
|
||||||
'user': session['user'],
|
'user': session.get('user', ''),
|
||||||
'machine_id': session['machine_id'],
|
'machine_id': session.get('machine_id', ''),
|
||||||
'title': session['title'],
|
'title': session.get('title', ''),
|
||||||
'parent_title': session['parent_title'],
|
'parent_title': session.get('parent_title', ''),
|
||||||
'grandparent_title': session['grandparent_title'],
|
'grandparent_title': session.get('grandparent_title', ''),
|
||||||
'full_title': session['full_title'],
|
'full_title': session.get('full_title', ''),
|
||||||
'media_index': session['media_index'],
|
'media_index': session.get('media_index', ''),
|
||||||
'parent_media_index': session['parent_media_index'],
|
'parent_media_index': session.get('parent_media_index', ''),
|
||||||
'thumb': session['thumb'],
|
'thumb': session.get('thumb', ''),
|
||||||
'parent_thumb': session['parent_thumb'],
|
'parent_thumb': session.get('parent_thumb', ''),
|
||||||
'grandparent_thumb': session['grandparent_thumb'],
|
'grandparent_thumb': session.get('grandparent_thumb', ''),
|
||||||
'year': session['year'],
|
'year': session.get('year', ''),
|
||||||
'friendly_name': session['friendly_name'],
|
'friendly_name': session.get('friendly_name', ''),
|
||||||
#'ip_address': session['ip_address'],
|
#'ip_address': session.get('ip_address', ''),
|
||||||
'player': session['player'],
|
'player': session.get('player', ''),
|
||||||
'platform': session['platform'],
|
'platform': session.get('platform', ''),
|
||||||
'parent_rating_key': session['parent_rating_key'],
|
'parent_rating_key': session.get('parent_rating_key', ''),
|
||||||
'grandparent_rating_key': session['grandparent_rating_key'],
|
'grandparent_rating_key': session.get('grandparent_rating_key', ''),
|
||||||
'view_offset': session['view_offset'],
|
'view_offset': session.get('view_offset', ''),
|
||||||
'duration': session['duration'],
|
'duration': session.get('duration', ''),
|
||||||
'video_decision': session['video_decision'],
|
'video_decision': session.get('video_decision', ''),
|
||||||
'audio_decision': session['audio_decision'],
|
'audio_decision': session.get('audio_decision', ''),
|
||||||
'transcode_decision': session['transcode_decision'],
|
'transcode_decision': session.get('transcode_decision', ''),
|
||||||
'width': session['width'],
|
'width': session.get('width', ''),
|
||||||
'height': session['height'],
|
'height': session.get('height', ''),
|
||||||
'container': session['container'],
|
'container': session.get('container', ''),
|
||||||
'video_codec': session['video_codec'],
|
'video_codec': session.get('video_codec', ''),
|
||||||
'audio_codec': session['audio_codec'],
|
'audio_codec': session.get('audio_codec', ''),
|
||||||
'bitrate': session['bitrate'],
|
'bitrate': session.get('bitrate', ''),
|
||||||
'video_resolution': session['video_resolution'],
|
'video_resolution': session.get('video_resolution', ''),
|
||||||
'video_framerate': session['video_framerate'],
|
'video_framerate': session.get('video_framerate', ''),
|
||||||
'aspect_ratio': session['aspect_ratio'],
|
'aspect_ratio': session.get('aspect_ratio', ''),
|
||||||
'audio_channels': session['audio_channels'],
|
'audio_channels': session.get('audio_channels', ''),
|
||||||
'transcode_protocol': session['transcode_protocol'],
|
'transcode_protocol': session.get('transcode_protocol', ''),
|
||||||
'transcode_container': session['transcode_container'],
|
'transcode_container': session.get('transcode_container', ''),
|
||||||
'transcode_video_codec': session['transcode_video_codec'],
|
'transcode_video_codec': session.get('transcode_video_codec', ''),
|
||||||
'transcode_audio_codec': session['transcode_audio_codec'],
|
'transcode_audio_codec': session.get('transcode_audio_codec', ''),
|
||||||
'transcode_audio_channels': session['transcode_audio_channels'],
|
'transcode_audio_channels': session.get('transcode_audio_channels', ''),
|
||||||
'transcode_width': session['transcode_width'],
|
'transcode_width': session.get('transcode_width', ''),
|
||||||
'transcode_height': session['transcode_height'],
|
'transcode_height': session.get('transcode_height', ''),
|
||||||
'stopped': None
|
'stopped': None
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add ip_address back into values
|
# Add ip_address back into values
|
||||||
if session['ip_address']:
|
if session['ip_address']:
|
||||||
values.update({'ip_address': session['ip_address']})
|
values.update({'ip_address': session.get('ip_address', 'N/A')})
|
||||||
|
|
||||||
keys = {'session_key': session['session_key'],
|
keys = {'session_key': session.get('session_key', ''),
|
||||||
'rating_key': session['rating_key']}
|
'rating_key': session.get('rating_key', '')}
|
||||||
|
|
||||||
result = self.db.upsert('sessions', values, keys)
|
result = self.db.upsert('sessions', values, keys)
|
||||||
|
|
||||||
if result == 'insert':
|
if result == 'insert':
|
||||||
# Check if any notification agents have notifications enabled
|
# Check if any notification agents have notifications enabled
|
||||||
if notify:
|
if notify:
|
||||||
values.update({'ip_address': session['ip_address']})
|
values.update({'ip_address': session.get('ip_address', 'N/A')})
|
||||||
plexpy.NOTIFY_QUEUE.put({'stream_data': values, 'notify_action': 'on_play'})
|
plexpy.NOTIFY_QUEUE.put({'stream_data': values, 'notify_action': 'on_play'})
|
||||||
|
|
||||||
# If it's our first write then time stamp it.
|
# If it's our first write then time stamp it.
|
||||||
|
|
|
@ -404,9 +404,10 @@ class Libraries(object):
|
||||||
for item in children_list:
|
for item in children_list:
|
||||||
## TODO: Check list of media info items, currently only grabs first item
|
## TODO: Check list of media info items, currently only grabs first item
|
||||||
media_info = item['media_info'][0] if item['media_info'] else {}
|
media_info = item['media_info'][0] if item['media_info'] else {}
|
||||||
|
media_part_info = media_info['parts'][0] if media_info['parts'] else {}
|
||||||
|
|
||||||
cached_file_size = cached_items.get(item['rating_key'], None)
|
cached_file_size = cached_items.get(item['rating_key'], None)
|
||||||
file_size = cached_file_size if cached_file_size else media_info.get('file_size', '')
|
file_size = cached_file_size if cached_file_size else media_part_info.get('file_size', '')
|
||||||
|
|
||||||
row = {'section_id': library_details['section_id'],
|
row = {'section_id': library_details['section_id'],
|
||||||
'section_type': library_details['section_type'],
|
'section_type': library_details['section_type'],
|
||||||
|
@ -567,6 +568,7 @@ class Libraries(object):
|
||||||
for child_metadata in metadata:
|
for child_metadata in metadata:
|
||||||
## TODO: Check list of media info items, currently only grabs first item
|
## TODO: Check list of media info items, currently only grabs first item
|
||||||
media_info = item['media_info'][0] if item['media_info'] else {}
|
media_info = item['media_info'][0] if item['media_info'] else {}
|
||||||
|
media_part_info = media_info['parts'][0] if media_info['parts'] else {}
|
||||||
|
|
||||||
file_size += helpers.cast_to_int(media_info.get('file_size', 0))
|
file_size += helpers.cast_to_int(media_info.get('file_size', 0))
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,10 @@ def add_notifier_each(notify_action=None, stream_data=None, timeline_data=None,
|
||||||
|
|
||||||
def notify_conditions(notifier=None, notify_action=None, stream_data=None, timeline_data=None):
|
def notify_conditions(notifier=None, notify_action=None, stream_data=None, timeline_data=None):
|
||||||
if stream_data:
|
if stream_data:
|
||||||
|
|
||||||
|
if stream_data['media_type'] == 'clip':
|
||||||
|
return False
|
||||||
|
|
||||||
# Check if notifications enabled for user and library
|
# Check if notifications enabled for user and library
|
||||||
user_data = users.Users()
|
user_data = users.Users()
|
||||||
user_details = user_data.get_details(user_id=stream_data['user_id'])
|
user_details = user_data.get_details(user_id=stream_data['user_id'])
|
||||||
|
@ -283,6 +287,16 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
|
|
||||||
## TODO: Check list of media info items, currently only grabs first item
|
## TODO: Check list of media info items, currently only grabs first item
|
||||||
media_info = metadata['media_info'][0] if metadata['media_info'] else {}
|
media_info = metadata['media_info'][0] if metadata['media_info'] else {}
|
||||||
|
media_part_info = media_info['parts'][0] if media_info['parts'] else {}
|
||||||
|
|
||||||
|
stream_video = stream_audio = stream_subtitle = False
|
||||||
|
for stream in media_part_info['streams']:
|
||||||
|
if not stream_video and stream['type'] == '1':
|
||||||
|
media_part_info.update(stream)
|
||||||
|
if not stream_audio and stream['type'] == '2':
|
||||||
|
media_part_info.update(stream)
|
||||||
|
if not stream_subtitle and stream['type'] == '3':
|
||||||
|
media_part_info.update(stream)
|
||||||
|
|
||||||
child_metadata = grandchild_metadata = []
|
child_metadata = grandchild_metadata = []
|
||||||
for key in kwargs.pop('child_keys', []):
|
for key in kwargs.pop('child_keys', []):
|
||||||
|
@ -414,7 +428,9 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
'user_streams': user_stream_count,
|
'user_streams': user_stream_count,
|
||||||
'user': session.get('friendly_name',''),
|
'user': session.get('friendly_name',''),
|
||||||
'username': session.get('user',''),
|
'username': session.get('user',''),
|
||||||
|
'device': session.get('device',''),
|
||||||
'platform': session.get('platform',''),
|
'platform': session.get('platform',''),
|
||||||
|
'product': session.get('product',''),
|
||||||
'player': session.get('player',''),
|
'player': session.get('player',''),
|
||||||
'ip_address': session.get('ip_address','N/A'),
|
'ip_address': session.get('ip_address','N/A'),
|
||||||
'stream_duration': stream_duration,
|
'stream_duration': stream_duration,
|
||||||
|
@ -430,6 +446,7 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
'subtitle_decision': session.get('subtitle_decision',''),
|
'subtitle_decision': session.get('subtitle_decision',''),
|
||||||
'quality_profile': session.get('quality_profile',''),
|
'quality_profile': session.get('quality_profile',''),
|
||||||
'optimized_version': session.get('optimized_version',''),
|
'optimized_version': session.get('optimized_version',''),
|
||||||
|
'optimized_version_profile': session.get('optimized_version_profile',''),
|
||||||
'stream_local': session.get('local', ''),
|
'stream_local': session.get('local', ''),
|
||||||
'stream_location': session.get('location', ''),
|
'stream_location': session.get('location', ''),
|
||||||
'stream_bandwidth': session.get('bandwidth', ''),
|
'stream_bandwidth': session.get('bandwidth', ''),
|
||||||
|
@ -437,22 +454,28 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
'stream_bitrate': session.get('stream_bitrate', ''),
|
'stream_bitrate': session.get('stream_bitrate', ''),
|
||||||
'stream_aspect_ratio': session.get('stream_aspect_ratio', ''),
|
'stream_aspect_ratio': session.get('stream_aspect_ratio', ''),
|
||||||
'stream_video_codec': session.get('stream_video_codec', ''),
|
'stream_video_codec': session.get('stream_video_codec', ''),
|
||||||
|
'stream_video_codec_level': session.get('stream_video_codec_level', ''),
|
||||||
'stream_video_bitrate': session.get('stream_video_bitrate', ''),
|
'stream_video_bitrate': session.get('stream_video_bitrate', ''),
|
||||||
|
'stream_video_bit_depth': session.get('stream_video_bit_depth', ''),
|
||||||
'stream_video_framerate': session.get('stream_video_framerate', ''),
|
'stream_video_framerate': session.get('stream_video_framerate', ''),
|
||||||
|
'stream_video_ref_frames': session.get('stream_video_ref_frames', ''),
|
||||||
'stream_video_resolution': session.get('stream_video_resolution', ''),
|
'stream_video_resolution': session.get('stream_video_resolution', ''),
|
||||||
'stream_video_height': session.get('stream_height', ''),
|
'stream_video_height': session.get('stream_video_height', ''),
|
||||||
'stream_video_width': session.get('stream_width', ''),
|
'stream_video_width': session.get('stream_video_width', ''),
|
||||||
'stream_video_language': session.get('stream_video_language', ''),
|
'stream_video_language': session.get('stream_video_language', ''),
|
||||||
'stream_video_language_code': session.get('stream_video_language_code', ''),
|
'stream_video_language_code': session.get('stream_video_language_code', ''),
|
||||||
'stream_audio_bitrate': session.get('stream_audio_bitrate', ''),
|
'stream_audio_bitrate': session.get('stream_audio_bitrate', ''),
|
||||||
'stream_audio_bitrate_mode': session.get('stream_audio_bitrate_mode', ''),
|
'stream_audio_bitrate_mode': session.get('stream_audio_bitrate_mode', ''),
|
||||||
'stream_audio_codec': session.get('stream_audio_codec', ''),
|
'stream_audio_codec': session.get('stream_audio_codec', ''),
|
||||||
'stream_audio_channels': session.get('stream_audio_channels', ''),
|
'stream_audio_channels': session.get('stream_audio_channels', ''),
|
||||||
|
'stream_audio_channel_layout': session.get('stream_audio_channel_layout', ''),
|
||||||
|
'stream_audio_sample_rate': session.get('stream_audio_sample_rate', ''),
|
||||||
'stream_audio_language': session.get('stream_audio_language', ''),
|
'stream_audio_language': session.get('stream_audio_language', ''),
|
||||||
'stream_audio_language_code': session.get('stream_audio_language_code', ''),
|
'stream_audio_language_code': session.get('stream_audio_language_code', ''),
|
||||||
'stream_subtitle_codec': session.get('stream_subtitle_codec', ''),
|
'stream_subtitle_codec': session.get('stream_subtitle_codec', ''),
|
||||||
'stream_subtitle_container': session.get('stream_subtitle_container', ''),
|
'stream_subtitle_container': session.get('stream_subtitle_container', ''),
|
||||||
'stream_subtitle_format': session.get('stream_subtitle_format', ''),
|
'stream_subtitle_format': session.get('stream_subtitle_format', ''),
|
||||||
|
'stream_subtitle_forced': session.get('stream_subtitle_forced', ''),
|
||||||
'stream_subtitle_language': session.get('stream_subtitle_language', ''),
|
'stream_subtitle_language': session.get('stream_subtitle_language', ''),
|
||||||
'stream_subtitle_language_code': session.get('stream_subtitle_language_code', ''),
|
'stream_subtitle_language_code': session.get('stream_subtitle_language_code', ''),
|
||||||
'stream_subtitle_location': session.get('stream_subtitle_location', ''),
|
'stream_subtitle_location': session.get('stream_subtitle_location', ''),
|
||||||
|
@ -470,16 +493,6 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
'machine_id': session.get('machine_id',''),
|
'machine_id': session.get('machine_id',''),
|
||||||
# Source metadata parameters
|
# Source metadata parameters
|
||||||
'media_type': metadata['media_type'],
|
'media_type': metadata['media_type'],
|
||||||
'container': session.get('container', media_info.get('container','')),
|
|
||||||
'aspect_ratio': session.get('aspect_ratio', media_info.get('aspect_ratio','')),
|
|
||||||
'video_codec': session.get('video_codec', media_info.get('video_codec','')),
|
|
||||||
'video_bitrate': session.get('bitrate', media_info.get('bitrate','')),
|
|
||||||
'video_framerate': session.get('video_framerate', media_info.get('video_framerate','')),
|
|
||||||
'video_resolution': session.get('video_resolution', media_info.get('video_resolution','')),
|
|
||||||
'video_width': session.get('width', media_info.get('width','')),
|
|
||||||
'video_height': session.get('height', media_info.get('height','')),
|
|
||||||
'audio_codec': session.get('audio_codec', media_info.get('audio_codec','')),
|
|
||||||
'audio_channels': session.get('audio_channels', media_info.get('audio_channels','')),
|
|
||||||
'title': metadata['full_title'],
|
'title': metadata['full_title'],
|
||||||
'library_name': metadata['library_name'],
|
'library_name': metadata['library_name'],
|
||||||
'show_name': show_name,
|
'show_name': show_name,
|
||||||
|
@ -525,8 +538,38 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, *
|
||||||
'themoviedb_url': metadata.get('themoviedb_url',''),
|
'themoviedb_url': metadata.get('themoviedb_url',''),
|
||||||
'lastfm_url': metadata.get('lastfm_url',''),
|
'lastfm_url': metadata.get('lastfm_url',''),
|
||||||
'trakt_url': metadata.get('trakt_url',''),
|
'trakt_url': metadata.get('trakt_url',''),
|
||||||
'file': media_info.get('file',''),
|
'container': session.get('container', media_info.get('container','')),
|
||||||
'file_size': helpers.humanFileSize(media_info.get('file_size','')),
|
'bitrate': session.get('bitrate', media_info.get('bitrate','')),
|
||||||
|
'aspect_ratio': session.get('aspect_ratio', media_info.get('aspect_ratio','')),
|
||||||
|
'video_codec': session.get('video_codec', media_info.get('video_codec','')),
|
||||||
|
'video_codec_level': session.get('video_codec_level', media_info.get('video_codec_level','')),
|
||||||
|
'video_bitrate': session.get('video_bitrate', media_info.get('video_bitrate','')),
|
||||||
|
'video_bit_depth': session.get('video_bit_depth', media_info.get('video_bit_depth','')),
|
||||||
|
'video_framerate': session.get('video_framerate', media_info.get('video_framerate','')),
|
||||||
|
'video_ref_frames': session.get('video_ref_frames', media_info.get('video_ref_frames','')),
|
||||||
|
'video_resolution': session.get('video_resolution', media_info.get('video_resolution','')),
|
||||||
|
'video_height': session.get('height', media_info.get('height','')),
|
||||||
|
'video_width': session.get('width', media_info.get('width','')),
|
||||||
|
'video_language': session.get('video_language', media_info.get('video_language','')),
|
||||||
|
'video_language_code': session.get('video_language_code', media_info.get('video_language_code','')),
|
||||||
|
'audio_bitrate': session.get('audio_bitrate', media_info.get('audio_bitrate','')),
|
||||||
|
'audio_bitrate_mode': session.get('audio_bitrate_mode', media_info.get('audio_bitrate_mode','')),
|
||||||
|
'audio_codec': session.get('audio_codec', media_info.get('audio_codec','')),
|
||||||
|
'audio_channels': session.get('audio_channels', media_info.get('audio_channels','')),
|
||||||
|
'audio_channel_layout': session.get('audio_channel_layout', media_info.get('audio_channel_layout','')),
|
||||||
|
'audio_sample_rate': session.get('audio_sample_rate', media_info.get('audio_sample_rate','')),
|
||||||
|
'audio_language': session.get('audio_language', media_info.get('audio_language','')),
|
||||||
|
'audio_language_code': session.get('audio_language_code', media_info.get('audio_language_code','')),
|
||||||
|
'subtitle_codec': session.get('subtitle_codec', media_info.get('subtitle_codec','')),
|
||||||
|
'subtitle_container': session.get('subtitle_container', media_info.get('subtitle_container','')),
|
||||||
|
'subtitle_format': session.get('subtitle_format', media_info.get('subtitle_format','')),
|
||||||
|
'subtitle_forced': session.get('subtitle_forced', media_info.get('subtitle_forced','')),
|
||||||
|
'subtitle_location': session.get('subtitle_location', media_info.get('subtitle_location','')),
|
||||||
|
'subtitle_language': session.get('subtitle_language', media_info.get('subtitle_language','')),
|
||||||
|
'subtitle_language_code': session.get('subtitle_language_code', media_info.get('subtitle_language_code','')),
|
||||||
|
'file': media_part_info.get('file',''),
|
||||||
|
'file_size': helpers.humanFileSize(media_part_info.get('file_size','')),
|
||||||
|
'indexes': media_part_info.get('indexes',''),
|
||||||
'section_id': metadata['section_id'],
|
'section_id': metadata['section_id'],
|
||||||
'rating_key': metadata['rating_key'],
|
'rating_key': metadata['rating_key'],
|
||||||
'parent_rating_key': metadata['parent_rating_key'],
|
'parent_rating_key': metadata['parent_rating_key'],
|
||||||
|
|
|
@ -573,14 +573,14 @@ class PmsConnect(object):
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata: %s." % e)
|
logger.warn(u"PlexPy Pmsconnect :: Unable to parse XML for get_metadata: %s." % e)
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
metadata_list = []
|
metadata = {}
|
||||||
|
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
if a.getAttribute('size'):
|
if a.getAttribute('size'):
|
||||||
if a.getAttribute('size') != '1':
|
if a.getAttribute('size') != '1':
|
||||||
return metadata_list
|
return metadata
|
||||||
|
|
||||||
if a.getElementsByTagName('Directory'):
|
if a.getElementsByTagName('Directory'):
|
||||||
metadata_main = a.getElementsByTagName('Directory')[0]
|
metadata_main = a.getElementsByTagName('Directory')[0]
|
||||||
|
@ -598,7 +598,7 @@ class PmsConnect(object):
|
||||||
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
|
||||||
else:
|
else:
|
||||||
logger.debug(u"PlexPy Pmsconnect :: Metadata failed")
|
logger.debug(u"PlexPy Pmsconnect :: Metadata failed")
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
section_id = helpers.get_xml_attr(a, 'librarySectionID')
|
section_id = helpers.get_xml_attr(a, 'librarySectionID')
|
||||||
library_name = helpers.get_xml_attr(a, 'librarySectionTitle')
|
library_name = helpers.get_xml_attr(a, 'librarySectionTitle')
|
||||||
|
@ -664,7 +664,6 @@ class PmsConnect(object):
|
||||||
'labels': labels,
|
'labels': labels,
|
||||||
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'show':
|
elif metadata_type == 'show':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
|
@ -701,7 +700,6 @@ class PmsConnect(object):
|
||||||
'labels': labels,
|
'labels': labels,
|
||||||
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'season':
|
elif metadata_type == 'season':
|
||||||
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||||
|
@ -741,7 +739,6 @@ class PmsConnect(object):
|
||||||
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'episode':
|
elif metadata_type == 'episode':
|
||||||
grandparent_rating_key = helpers.get_xml_attr(metadata_main, 'grandparentRatingKey')
|
grandparent_rating_key = helpers.get_xml_attr(metadata_main, 'grandparentRatingKey')
|
||||||
|
@ -781,7 +778,6 @@ class PmsConnect(object):
|
||||||
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'artist':
|
elif metadata_type == 'artist':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
|
@ -818,7 +814,6 @@ class PmsConnect(object):
|
||||||
'labels': labels,
|
'labels': labels,
|
||||||
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'album':
|
elif metadata_type == 'album':
|
||||||
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||||
|
@ -858,7 +853,6 @@ class PmsConnect(object):
|
||||||
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'track':
|
elif metadata_type == 'track':
|
||||||
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||||
|
@ -898,7 +892,6 @@ class PmsConnect(object):
|
||||||
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
|
||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'photo_album':
|
elif metadata_type == 'photo_album':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
|
@ -935,7 +928,6 @@ class PmsConnect(object):
|
||||||
'labels': labels,
|
'labels': labels,
|
||||||
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
'full_title': helpers.get_xml_attr(metadata_main, 'title')
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
elif metadata_type == 'photo':
|
elif metadata_type == 'photo':
|
||||||
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
parent_rating_key = helpers.get_xml_attr(metadata_main, 'parentRatingKey')
|
||||||
|
@ -975,36 +967,84 @@ class PmsConnect(object):
|
||||||
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
|
||||||
helpers.get_xml_attr(metadata_main, 'title'))
|
helpers.get_xml_attr(metadata_main, 'title'))
|
||||||
}
|
}
|
||||||
metadata_list.append(metadata)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
media_info_list = []
|
if metadata:
|
||||||
|
medias = []
|
||||||
media_items = metadata_main.getElementsByTagName('Media')
|
media_items = metadata_main.getElementsByTagName('Media')
|
||||||
for item in media_items:
|
for media in media_items:
|
||||||
media_info = {'id': helpers.get_xml_attr(item, 'id'),
|
|
||||||
'container': helpers.get_xml_attr(item, 'container'),
|
|
||||||
'bitrate': helpers.get_xml_attr(item, 'bitrate'),
|
|
||||||
'height': helpers.get_xml_attr(item, 'height'),
|
|
||||||
'width': helpers.get_xml_attr(item, 'width'),
|
|
||||||
'aspect_ratio': helpers.get_xml_attr(item, 'aspectRatio'),
|
|
||||||
'video_codec': helpers.get_xml_attr(item, 'videoCodec'),
|
|
||||||
'video_resolution': helpers.get_xml_attr(item, 'videoResolution'),
|
|
||||||
'video_framerate': helpers.get_xml_attr(item, 'videoFrameRate'),
|
|
||||||
'audio_codec': helpers.get_xml_attr(item, 'audioCodec'),
|
|
||||||
'audio_channels': helpers.get_xml_attr(item, 'audioChannels'),
|
|
||||||
'file': helpers.get_xml_attr(item.getElementsByTagName('Part')[0], 'file'),
|
|
||||||
'file_size': helpers.get_xml_attr(item.getElementsByTagName('Part')[0], 'size')
|
|
||||||
}
|
|
||||||
media_info_list.append(media_info)
|
|
||||||
|
|
||||||
metadata['media_info'] = media_info_list
|
parts = []
|
||||||
|
part_items = media.getElementsByTagName('Part')
|
||||||
|
for part in part_items:
|
||||||
|
|
||||||
if metadata_list:
|
streams = []
|
||||||
return metadata_list[0]
|
stream_items = part.getElementsByTagName('Stream')
|
||||||
|
for stream in stream_items:
|
||||||
|
if helpers.get_xml_attr(stream, 'streamType') == '1':
|
||||||
|
streams.append({'id': helpers.get_xml_attr(stream, 'id'),
|
||||||
|
'type': helpers.get_xml_attr(stream, 'streamType'),
|
||||||
|
'video_bitrate': helpers.get_xml_attr(stream, 'bitrate'),
|
||||||
|
'video_bit_depth': helpers.get_xml_attr(stream, 'bitDepth'),
|
||||||
|
'video_codec_level': helpers.get_xml_attr(stream, 'level'),
|
||||||
|
'video_ref_frames': helpers.get_xml_attr(stream, 'refFrames'),
|
||||||
|
'video_language': helpers.get_xml_attr(stream, 'language'),
|
||||||
|
'video_language_code': helpers.get_xml_attr(stream, 'languageCode')
|
||||||
|
})
|
||||||
|
|
||||||
|
elif helpers.get_xml_attr(stream, 'streamType') == '2':
|
||||||
|
streams.append({'id': helpers.get_xml_attr(stream, 'id'),
|
||||||
|
'type': helpers.get_xml_attr(stream, 'streamType'),
|
||||||
|
'audio_bitrate': helpers.get_xml_attr(stream, 'bitrate'),
|
||||||
|
'audio_bitrate_mode': helpers.get_xml_attr(stream, 'bitrateMode'),
|
||||||
|
'audio_channel_layout': helpers.get_xml_attr(stream, 'audioChannelLayout'),
|
||||||
|
'audio_sample_rate': helpers.get_xml_attr(stream, 'samplingRate'),
|
||||||
|
'audio_language': helpers.get_xml_attr(stream, 'language'),
|
||||||
|
'audio_language_code': helpers.get_xml_attr(stream, 'languageCode'),
|
||||||
|
})
|
||||||
|
|
||||||
|
elif helpers.get_xml_attr(stream, 'streamType') == '3':
|
||||||
|
streams.append({'id': helpers.get_xml_attr(stream, 'id'),
|
||||||
|
'type': helpers.get_xml_attr(stream, 'streamType'),
|
||||||
|
'subtitle_codec': helpers.get_xml_attr(stream, 'codec'),
|
||||||
|
'subtitle_container': helpers.get_xml_attr(stream, 'container'),
|
||||||
|
'subtitle_format': helpers.get_xml_attr(stream, 'format'),
|
||||||
|
'subtitle_forced': 1 if helpers.get_xml_attr(stream, 'forced') == '1' else 0,
|
||||||
|
'subtitle_location': 'external' if helpers.get_xml_attr(stream, 'key') else 'embedded',
|
||||||
|
'subtitle_language': helpers.get_xml_attr(stream, 'language'),
|
||||||
|
'subtitle_language_code': helpers.get_xml_attr(stream, 'languageCode')
|
||||||
|
})
|
||||||
|
|
||||||
|
parts.append({'id': helpers.get_xml_attr(part, 'id'),
|
||||||
|
'file': helpers.get_xml_attr(part, 'file'),
|
||||||
|
'file_size': helpers.get_xml_attr(part, 'size'),
|
||||||
|
'indexes': 1 if helpers.get_xml_attr(part, 'indexes') == 'sd' else 0,
|
||||||
|
'streams': streams
|
||||||
|
})
|
||||||
|
|
||||||
|
medias.append({'id': helpers.get_xml_attr(media, 'id'),
|
||||||
|
'container': helpers.get_xml_attr(media, 'container'),
|
||||||
|
'bitrate': helpers.get_xml_attr(media, 'bitrate'),
|
||||||
|
'height': helpers.get_xml_attr(media, 'height'),
|
||||||
|
'width': helpers.get_xml_attr(media, 'width'),
|
||||||
|
'aspect_ratio': helpers.get_xml_attr(media, 'aspectRatio'),
|
||||||
|
'video_codec': helpers.get_xml_attr(media, 'videoCodec'),
|
||||||
|
'video_resolution': helpers.get_xml_attr(media, 'videoResolution'),
|
||||||
|
'video_framerate': helpers.get_xml_attr(media, 'videoFrameRate'),
|
||||||
|
'audio_codec': helpers.get_xml_attr(media, 'audioCodec'),
|
||||||
|
'audio_channels': helpers.get_xml_attr(media, 'audioChannels'),
|
||||||
|
'optimized_version': 1 if helpers.get_xml_attr(media, 'optimizedForStreaming') else 0,
|
||||||
|
'parts': parts
|
||||||
|
})
|
||||||
|
|
||||||
|
metadata['media_info'] = medias
|
||||||
|
|
||||||
|
if metadata:
|
||||||
|
return metadata
|
||||||
else:
|
else:
|
||||||
return []
|
return {}
|
||||||
|
|
||||||
def get_metadata_children_details(self, rating_key='', get_children=False):
|
def get_metadata_children_details(self, rating_key='', get_children=False):
|
||||||
"""
|
"""
|
||||||
|
@ -1257,11 +1297,16 @@ class PmsConnect(object):
|
||||||
media_parts_stream_info = []
|
media_parts_stream_info = []
|
||||||
|
|
||||||
for stream_media_info in media_info_all:
|
for stream_media_info in media_info_all:
|
||||||
stream_media_parts_info = stream_media_info.getElementsByTagName('Part')[0]
|
media_part_info_all = stream_media_info.getElementsByTagName('Part')
|
||||||
|
|
||||||
|
for stream_media_parts_info in media_part_info_all:
|
||||||
if stream_media_parts_info.getElementsByTagName('Stream'):
|
if stream_media_parts_info.getElementsByTagName('Stream'):
|
||||||
media_parts_stream_info = stream_media_parts_info.getElementsByTagName('Stream')
|
media_parts_stream_info = stream_media_parts_info.getElementsByTagName('Stream')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if media_parts_stream_info:
|
||||||
|
break
|
||||||
|
|
||||||
# Get the stream details
|
# Get the stream details
|
||||||
video_stream_info = audio_stream_info = subtitle_stream_info = None
|
video_stream_info = audio_stream_info = subtitle_stream_info = None
|
||||||
for stream in media_parts_stream_info:
|
for stream in media_parts_stream_info:
|
||||||
|
@ -1274,30 +1319,40 @@ class PmsConnect(object):
|
||||||
elif helpers.get_xml_attr(stream, 'streamType') == '3':
|
elif helpers.get_xml_attr(stream, 'streamType') == '3':
|
||||||
subtitle_stream_info = stream
|
subtitle_stream_info = stream
|
||||||
|
|
||||||
|
video_id = audio_id = subtitle_id = None
|
||||||
video_details = audio_details = subtitle_details = {}
|
video_details = audio_details = subtitle_details = {}
|
||||||
if video_stream_info:
|
if video_stream_info:
|
||||||
|
video_id = helpers.get_xml_attr(video_stream_info, 'id')
|
||||||
video_details = {'stream_video_bitrate': helpers.get_xml_attr(video_stream_info, 'bitrate'),
|
video_details = {'stream_video_bitrate': helpers.get_xml_attr(video_stream_info, 'bitrate'),
|
||||||
|
'stream_video_bit_depth': helpers.get_xml_attr(video_stream_info, 'bitDepth'),
|
||||||
|
'stream_video_codec_level': helpers.get_xml_attr(video_stream_info, 'level'),
|
||||||
|
'stream_video_ref_frames': helpers.get_xml_attr(video_stream_info, 'refFrames'),
|
||||||
'stream_video_language': helpers.get_xml_attr(video_stream_info, 'language'),
|
'stream_video_language': helpers.get_xml_attr(video_stream_info, 'language'),
|
||||||
'stream_video_language_code': helpers.get_xml_attr(video_stream_info, 'languageCode'),
|
'stream_video_language_code': helpers.get_xml_attr(video_stream_info, 'languageCode'),
|
||||||
'stream_video_decision': helpers.get_xml_attr(video_stream_info, 'decision') or 'direct play'
|
'stream_video_decision': helpers.get_xml_attr(video_stream_info, 'decision') or 'direct play'
|
||||||
}
|
}
|
||||||
|
|
||||||
if audio_stream_info:
|
if audio_stream_info:
|
||||||
|
audio_id = helpers.get_xml_attr(audio_stream_info, 'id')
|
||||||
audio_details = {'stream_audio_bitrate': helpers.get_xml_attr(audio_stream_info, 'bitrate'),
|
audio_details = {'stream_audio_bitrate': helpers.get_xml_attr(audio_stream_info, 'bitrate'),
|
||||||
'stream_audio_bitrate_mode': helpers.get_xml_attr(audio_stream_info, 'bitrateMode'),
|
'stream_audio_bitrate_mode': helpers.get_xml_attr(audio_stream_info, 'bitrateMode'),
|
||||||
|
'stream_audio_channel_layout': helpers.get_xml_attr(audio_stream_info, 'audioChannelLayout'),
|
||||||
|
'stream_audio_sample_rate': helpers.get_xml_attr(audio_stream_info, 'samplingRate'),
|
||||||
'stream_audio_language': helpers.get_xml_attr(audio_stream_info, 'language'),
|
'stream_audio_language': helpers.get_xml_attr(audio_stream_info, 'language'),
|
||||||
'stream_audio_language_code': helpers.get_xml_attr(audio_stream_info, 'languageCode'),
|
'stream_audio_language_code': helpers.get_xml_attr(audio_stream_info, 'languageCode'),
|
||||||
'stream_audio_decision': helpers.get_xml_attr(audio_stream_info, 'decision') or 'direct play'
|
'stream_audio_decision': helpers.get_xml_attr(audio_stream_info, 'decision') or 'direct play'
|
||||||
}
|
}
|
||||||
|
|
||||||
if subtitle_stream_info:
|
if subtitle_stream_info:
|
||||||
subtitle_details = {'stream_subtitle_codec': helpers.get_xml_attr(audio_stream_info, 'codec'),
|
subtitle_id = helpers.get_xml_attr(subtitle_stream_info, 'id')
|
||||||
'stream_subtitle_container': helpers.get_xml_attr(audio_stream_info, 'container'),
|
subtitle_details = {'stream_subtitle_codec': helpers.get_xml_attr(subtitle_stream_info, 'codec'),
|
||||||
'stream_subtitle_format': helpers.get_xml_attr(audio_stream_info, 'format'),
|
'stream_subtitle_container': helpers.get_xml_attr(subtitle_stream_info, 'container'),
|
||||||
'stream_subtitle_language': helpers.get_xml_attr(audio_stream_info, 'language'),
|
'stream_subtitle_format': helpers.get_xml_attr(subtitle_stream_info, 'format'),
|
||||||
'stream_subtitle_language_code': helpers.get_xml_attr(audio_stream_info, 'languageCode'),
|
'stream_subtitle_forced': 1 if helpers.get_xml_attr(subtitle_stream_info, 'forced') == '1' else 0,
|
||||||
'stream_subtitle_location': helpers.get_xml_attr(audio_stream_info, 'location'),
|
'stream_subtitle_location': helpers.get_xml_attr(subtitle_stream_info, 'location'),
|
||||||
'stream_subtitle_decision': helpers.get_xml_attr(audio_stream_info, 'decision')
|
'stream_subtitle_language': helpers.get_xml_attr(subtitle_stream_info, 'language'),
|
||||||
|
'stream_subtitle_language_code': helpers.get_xml_attr(subtitle_stream_info, 'languageCode'),
|
||||||
|
'stream_subtitle_decision': helpers.get_xml_attr(subtitle_stream_info, 'decision')
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the bif thumbnail
|
# Get the bif thumbnail
|
||||||
|
@ -1309,22 +1364,12 @@ class PmsConnect(object):
|
||||||
else:
|
else:
|
||||||
bif_thumb = ''
|
bif_thumb = ''
|
||||||
|
|
||||||
# Check if it is an optimized version
|
|
||||||
if helpers.get_xml_attr(stream_media_parts_info, 'optimizedForStreaming'):
|
|
||||||
optimized_version = 1
|
|
||||||
else:
|
|
||||||
optimized_version = 0
|
|
||||||
|
|
||||||
# Get the quality profile
|
# Get the quality profile
|
||||||
if video_details:
|
if video_details:
|
||||||
quality_profile = common.QUALITY_PROFILES.get(video_details['stream_video_bitrate'], 'Original')
|
quality_profile = common.QUALITY_PROFILES.get(video_details['stream_video_bitrate'], 'Original')
|
||||||
else:
|
else:
|
||||||
quality_profile = ''
|
quality_profile = ''
|
||||||
|
|
||||||
transcode_decision = helpers.get_xml_attr(stream_media_parts_info, 'decision')
|
|
||||||
if transcode_decision == 'directplay':
|
|
||||||
transcode_decision = 'direct play'
|
|
||||||
|
|
||||||
# Check if it is an optimized version
|
# Check if it is an optimized version
|
||||||
stream_details = {'stream_container': helpers.get_xml_attr(stream_media_info, 'container'),
|
stream_details = {'stream_container': helpers.get_xml_attr(stream_media_info, 'container'),
|
||||||
'stream_bitrate': helpers.get_xml_attr(stream_media_info, 'bitrate'),
|
'stream_bitrate': helpers.get_xml_attr(stream_media_info, 'bitrate'),
|
||||||
|
@ -1337,8 +1382,9 @@ class PmsConnect(object):
|
||||||
'stream_video_height': helpers.get_xml_attr(stream_media_info, 'height'),
|
'stream_video_height': helpers.get_xml_attr(stream_media_info, 'height'),
|
||||||
'stream_video_width': helpers.get_xml_attr(stream_media_info, 'width'),
|
'stream_video_width': helpers.get_xml_attr(stream_media_info, 'width'),
|
||||||
'stream_duration': helpers.get_xml_attr(stream_media_info, 'duration'),
|
'stream_duration': helpers.get_xml_attr(stream_media_info, 'duration'),
|
||||||
'transcode_decision': transcode_decision,
|
'transcode_decision': helpers.get_xml_attr(stream_media_parts_info, 'decision').replace('directplay', 'direct play'),
|
||||||
'optimized_version': optimized_version,
|
'optimized_version': 1 if helpers.get_xml_attr(stream_media_info, 'optimizedForStreaming') else 0,
|
||||||
|
'optimized_version_profile': helpers.get_xml_attr(stream_media_info, 'title'),
|
||||||
'quality_profile': quality_profile,
|
'quality_profile': quality_profile,
|
||||||
'indexes': 1 if indexes == 'sd' else 0,
|
'indexes': 1 if indexes == 'sd' else 0,
|
||||||
'bif_thumb': bif_thumb,
|
'bif_thumb': bif_thumb,
|
||||||
|
@ -1346,23 +1392,62 @@ class PmsConnect(object):
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the source media info
|
# Get the source media info
|
||||||
|
media_type = helpers.get_xml_attr(session, 'type')
|
||||||
|
|
||||||
|
source_media_details = source_media_part_details = \
|
||||||
|
source_video_details = source_audio_details = source_subtitle_details = {}
|
||||||
|
|
||||||
|
if media_type == 'clip':
|
||||||
|
clip_media = session.getElementsByTagName('Media')[0]
|
||||||
|
metadata_details = {'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
|
||||||
|
'title': helpers.get_xml_attr(session, 'title'),
|
||||||
|
'summary': helpers.get_xml_attr(session, 'summary'),
|
||||||
|
'duration': helpers.get_xml_attr(session, 'duration'),
|
||||||
|
'year': helpers.get_xml_attr(session, 'year'),
|
||||||
|
'thumb': helpers.get_xml_attr(session, 'thumb'),
|
||||||
|
'art': helpers.get_xml_attr(session, 'art'),
|
||||||
|
'full_title': helpers.get_xml_attr(session, 'title'),
|
||||||
|
'container': helpers.get_xml_attr(clip_media, 'container'),
|
||||||
|
'height': helpers.get_xml_attr(clip_media, 'height'),
|
||||||
|
'width': helpers.get_xml_attr(clip_media, 'width'),
|
||||||
|
'video_codec': helpers.get_xml_attr(clip_media, 'videoCodec'),
|
||||||
|
'video_resolution': helpers.get_xml_attr(clip_media, 'videoResolution'),
|
||||||
|
'audio_codec': helpers.get_xml_attr(clip_media, 'audioCodec'),
|
||||||
|
'audio_channels': helpers.get_xml_attr(clip_media, 'audioChannels'),
|
||||||
|
}
|
||||||
|
else:
|
||||||
media_id = helpers.get_xml_attr(stream_media_info, 'id')
|
media_id = helpers.get_xml_attr(stream_media_info, 'id')
|
||||||
|
part_id = helpers.get_xml_attr(stream_media_parts_info, 'id')
|
||||||
|
|
||||||
metadata_details = self.get_metadata_details(rating_key=helpers.get_xml_attr(session, 'ratingKey'))
|
metadata_details = self.get_metadata_details(rating_key=helpers.get_xml_attr(session, 'ratingKey'))
|
||||||
source_media_details = next((m for m in metadata_details.pop('media_info') if m['id'] == media_id), {})
|
source_media_details = next((m for m in metadata_details.pop('media_info', []) if m['id'] == media_id), {})
|
||||||
|
source_media_part_details = next((p for p in source_media_details.pop('parts', []) if p['id'] == part_id), {})
|
||||||
|
source_media_part_streams = source_media_part_details.pop('streams', [])
|
||||||
|
|
||||||
|
if video_id:
|
||||||
|
source_video_details = next((p for p in source_media_part_streams if p['id'] == video_id), {})
|
||||||
|
if audio_id:
|
||||||
|
source_audio_details = next((p for p in source_media_part_streams if p['id'] == audio_id), {})
|
||||||
|
if subtitle_id:
|
||||||
|
source_subtitle_details = next((p for p in source_media_part_streams if p['id'] == subtitle_id), {})
|
||||||
|
|
||||||
# Entire session output (single dict for backwards compatibility)
|
# Entire session output (single dict for backwards compatibility)
|
||||||
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
|
||||||
|
'media_type': media_type,
|
||||||
'view_offset': progress,
|
'view_offset': progress,
|
||||||
'progress_percent': str(helpers.get_percent(progress, stream_details['stream_duration'])),
|
'progress_percent': str(helpers.get_percent(progress, stream_details['stream_duration'])),
|
||||||
'user': user_details['username'] # Keep for backwards compatibility
|
'user': user_details['username'] # Keep for backwards compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
if helpers.get_xml_attr(session, 'ratingKey').isdigit():
|
if 'rating_key' not in session_output:
|
||||||
session_output['media_type'] = helpers.get_xml_attr(session, 'type')
|
session_output['rating_key'] = helpers.get_xml_attr(session, 'ratingKey')
|
||||||
else:
|
|
||||||
session_output['media_type'] = 'clip'
|
|
||||||
|
|
||||||
|
session_output.update(metadata_details)
|
||||||
|
session_output.update(source_media_details)
|
||||||
|
session_output.update(source_media_part_details)
|
||||||
|
session_output.update(source_video_details)
|
||||||
|
session_output.update(source_audio_details)
|
||||||
|
session_output.update(source_subtitle_details)
|
||||||
session_output.update(user_details)
|
session_output.update(user_details)
|
||||||
session_output.update(player_details)
|
session_output.update(player_details)
|
||||||
session_output.update(session_details)
|
session_output.update(session_details)
|
||||||
|
@ -1371,8 +1456,6 @@ class PmsConnect(object):
|
||||||
session_output.update(video_details)
|
session_output.update(video_details)
|
||||||
session_output.update(audio_details)
|
session_output.update(audio_details)
|
||||||
session_output.update(subtitle_details)
|
session_output.update(subtitle_details)
|
||||||
session_output.update(metadata_details)
|
|
||||||
session_output.update(source_media_details)
|
|
||||||
|
|
||||||
return session_output
|
return session_output
|
||||||
|
|
||||||
|
@ -1776,7 +1859,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return labels_list
|
return labels_list
|
||||||
|
|
||||||
def get_image(self, img=None, width='1000', height='1500'):
|
def get_image(self, img=None, width='1000', height='1500', clip=False):
|
||||||
"""
|
"""
|
||||||
Return image data as array.
|
Return image data as array.
|
||||||
Array contains the image content type and image binary
|
Array contains the image content type and image binary
|
||||||
|
@ -1788,7 +1871,11 @@ class PmsConnect(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if img:
|
if img:
|
||||||
|
if clip:
|
||||||
|
params = {'url': '%s&%s' % (img, urllib.urlencode({'X-Plex-Token': self.token}))}
|
||||||
|
else:
|
||||||
params = {'url': 'http://127.0.0.1:32400%s?%s' % (img, urllib.urlencode({'X-Plex-Token': self.token}))}
|
params = {'url': 'http://127.0.0.1:32400%s?%s' % (img, urllib.urlencode({'X-Plex-Token': self.token}))}
|
||||||
|
|
||||||
if width.isdigit() and height.isdigit():
|
if width.isdigit() and height.isdigit():
|
||||||
params['width'] = width
|
params['width'] = width
|
||||||
params['height'] = height
|
params['height'] = height
|
||||||
|
|
|
@ -3509,7 +3509,7 @@ class WebInterface(object):
|
||||||
|
|
||||||
@addtoapi('pms_image_proxy')
|
@addtoapi('pms_image_proxy')
|
||||||
def real_pms_image_proxy(self, img='', rating_key=None, width='0', height='0',
|
def real_pms_image_proxy(self, img='', rating_key=None, width='0', height='0',
|
||||||
fallback=None, refresh=False, **kwargs):
|
fallback=None, refresh=False, clip=False, **kwargs):
|
||||||
""" Gets an image from the PMS and saves it to the image cache directory.
|
""" Gets an image from the PMS and saves it to the image cache directory.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -3545,6 +3545,8 @@ class WebInterface(object):
|
||||||
if not os.path.exists(c_dir):
|
if not os.path.exists(c_dir):
|
||||||
os.mkdir(c_dir)
|
os.mkdir(c_dir)
|
||||||
|
|
||||||
|
clip = True if clip == 'true' else False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not plexpy.CONFIG.CACHE_IMAGES or refresh or 'indexes' in img:
|
if not plexpy.CONFIG.CACHE_IMAGES or refresh or 'indexes' in img:
|
||||||
raise NotFound
|
raise NotFound
|
||||||
|
@ -3555,7 +3557,7 @@ class WebInterface(object):
|
||||||
# the image does not exist, download it from pms
|
# the image does not exist, download it from pms
|
||||||
try:
|
try:
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_image(img, width, height)
|
result = pms_connect.get_image(img, width, height, clip=clip)
|
||||||
|
|
||||||
if result and result[0]:
|
if result and result[0]:
|
||||||
cherrypy.response.headers['Content-type'] = result[1]
|
cherrypy.response.headers['Content-type'] = result[1]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue