+ <%
+ if not _session['user_group'] == 'admin' or data['synced_version'] == '1':
+ no_terminate = '-no-terminate'
+ else:
+ no_terminate = ''
+ %>
+
@@ -133,9 +143,9 @@ DOCUMENTATION :: END
br = helpers.cast_to_int(data['stream_bitrate']) or ''
if br:
if br > 1000:
- br = '(' + str(round(br / 1000.0, 1)) + 'Mbps)'
+ br = '(' + str(round(br / 1000.0, 1)) + ' Mbps)'
else:
- br = '(' + str(br) + 'kbps)'
+ br = '(' + str(br) + ' kbps)'
%>
${data['quality_profile']} ${br}
% else:
@@ -170,7 +180,7 @@ DOCUMENTATION :: END
% elif data['transcode_decision'] == 'copy':
Direct Stream
% else:
- Direct Play
+ Direct Play ${'(Synced)' if data['synced_version'] else ''}
% endif
@@ -214,11 +224,11 @@ DOCUMENTATION :: END
Audio
% if data['stream_audio_decision'] == 'transcode':
- Transcode (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0]} → ${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout']})
+ Transcode (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()} → ${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
% elif data['stream_audio_decision'] == 'copy':
- Direct Stream (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout']})
+ Direct Stream (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
% else:
- Direct Play (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0]})
+ Direct Play (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()})
% endif
@@ -268,17 +278,21 @@ DOCUMENTATION :: END
Bandwidth
- % if data['media_type'] != 'photo' and 'location' in data:
+ % if data['media_type'] != 'photo' and data['bandwidth']:
<%
bw = helpers.cast_to_int(data['bandwidth']) or "Unknown"
if bw != "Unknown":
if bw > 1000:
- bw = str(round(bw / 1000.0, 1)) + 'Mbps'
+ bw = str(round(bw / 1000.0, 1)) + ' Mbps'
else:
- bw = str(bw) + 'kbps'
+ bw = str(bw) + ' kbps'
%>
${bw}
+ % elif data['synced_version'] == '1':
+ None
+ % else:
+ Unknown
% endif
diff --git a/data/interfaces/default/index.html b/data/interfaces/default/index.html
index e8320a2a..fc3555b1 100644
--- a/data/interfaces/default/index.html
+++ b/data/interfaces/default/index.html
@@ -324,7 +324,7 @@
} else if (s.transcode_decision === 'copy') {
transcode_decision = 'Direct Stream';
} else {
- transcode_decision = 'Direct Play';
+ transcode_decision = 'Direct Play' + ((s.synced_version == 1) ? ' (Synced)' : '');
}
$('#transcode_decision-' + key).html(transcode_decision);
@@ -383,11 +383,11 @@
var a_codec = (s.audio_codec === 'truehd') ? 'TrueHD' : s.audio_codec.toUpperCase();
var sa_codec = (s.stream_audio_codec === 'truehd') ? 'TrueHD' : s.stream_audio_codec.toUpperCase();
if (s.stream_audio_decision === 'transcode') {
- audio_decision = 'Transcode (' + a_codec + ' ' + s.audio_channel_layout.split('(')[0] + ' → ' + sa_codec + ' ' + s.stream_audio_channel_layout + ')';
+ audio_decision = 'Transcode (' + a_codec + ' ' + capitalizeFirstLetter(s.audio_channel_layout.split('(')[0]) + ' → ' + sa_codec + ' ' + capitalizeFirstLetter(s.stream_audio_channel_layout.split('(')[0]) + ')';
} else if (s.stream_audio_decision === 'copy') {
- audio_decision = 'Direct Stream (' + sa_codec + ' ' + s.stream_audio_channel_layout + ')';
+ audio_decision = 'Direct Stream (' + sa_codec + ' ' + capitalizeFirstLetter(s.stream_audio_channel_layout.split('(')[0]) + ')';
} else {
- audio_decision = 'Direct Play (' + a_codec + ' ' + s.audio_channel_layout.split('(')[0] + ')';
+ audio_decision = 'Direct Play (' + a_codec + ' ' + capitalizeFirstLetter(s.audio_channel_layout.split('(')[0]) + ')';
}
}
$('#audio_decision-' + key).html(audio_decision);
@@ -411,9 +411,9 @@
var br = parseInt(s.stream_bitrate) || '';
if (br) {
if (br > 1000) {
- br = ' (' + (br / 1000).toFixed(1) + 'Mbps)';
+ br = ' (' + (br / 1000).toFixed(1) + ' Mbps)';
} else {
- br = ' (' + br + 'kbps)';
+ br = ' (' + br + ' kbps)';
}
}
$('#stream_quality-' + key).html(s.quality_profile + br);
@@ -422,15 +422,17 @@
}
$('#optimized_version-' + key).html(s.optimized_version_profile);
- var bw = parseInt(s.bandwidth) || 'Unknown';
- if (bw != "Unknown") {
- if (bw > 1000) {
- bw = (bw / 1000).toFixed(1) + 'Mbps';
- } else {
- bw = bw + ' kbps'
+ if (s.media_type != 'photo' && s.bandwidth) {
+ var bw = parseInt(s.bandwidth) || 'Unknown';
+ if (bw != "Unknown") {
+ if (bw > 1000) {
+ bw = (bw / 1000).toFixed(1) + ' Mbps';
+ } else {
+ bw = bw + ' kbps'
+ }
}
+ $('#stream-bandwidth-' + key).html(bw);
}
- $('#stream-bandwidth-' + key).html(bw );
// Update the stream progress times
$('#stream-eta-' + key).html(moment().add(parseInt(s.duration) - parseInt(s.view_offset), 'milliseconds').format(time_format));
diff --git a/plexpy/common.py b/plexpy/common.py
index 9963b3c4..97317a83 100644
--- a/plexpy/common.py
+++ b/plexpy/common.py
@@ -231,6 +231,7 @@ NOTIFICATION_PARAMETERS = [
{'name': 'Quality Profile', 'type': 'str', 'value': 'quality_profile', 'description': 'The Plex quality profile of the stream.', 'example': 'e.g. Original, 4 Mbps 720p, etc.'},
{'name': 'Optimized Version', 'type': 'int', 'value': 'optimized_version', 'description': 'If the stream is an optimized version.', 'example': '0 or 1'},
{'name': 'Optimized Version Profile', 'type': 'str', 'value': 'optimized_version_profile', 'description': 'The optimized version profile of the stream.'},
+ {'name': 'Synced Version', 'type': 'int', 'value': 'synced_version', 'description': 'If the stream is an synced version.', 'example': '0 or 1'},
{'name': 'Stream Local', 'type': 'int', 'value': 'stream_local', 'description': 'If the stream is local.', 'example': '0 or 1'},
{'name': 'Stream Location', 'type': 'str', 'value': 'stream_location', 'description': 'The network location of the stream.', 'example': 'lan or wan'},
{'name': 'Stream Bandwidth', 'type': 'int', 'value': 'stream_bandwidth', 'description': 'The required bandwidth (in kbps) of the stream.', 'help_text': 'not the used bandwidth'},
diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py
index 42d2af57..5ab6b398 100644
--- a/plexpy/pmsconnect.py
+++ b/plexpy/pmsconnect.py
@@ -1312,6 +1312,9 @@ class PmsConnect(object):
Output: dict
"""
+ # Get the source media type
+ media_type = helpers.get_xml_attr(session, 'type')
+
# Get the user details
user_info = session.getElementsByTagName('User')[0]
user_details = users.Users().get_details(user=helpers.get_xml_attr(user_info, 'title'))
@@ -1406,6 +1409,20 @@ class PmsConnect(object):
'throttled': '0' # Keep for backwards compatibility
}
+ # Generate a combined transcode decision value
+ if transcode_details['video_decision'] == 'transcode' or transcode_details['audio_decision'] == 'transcode':
+ transcode_decision = 'transcode'
+ elif transcode_details['video_decision'] == 'copy' or transcode_details['audio_decision'] == 'copy':
+ transcode_decision = 'copy'
+ else:
+ transcode_decision = 'direct play'
+
+ # Determine if a synced version is being played
+ if media_type not in ('photo', 'clip') and not session.getElementsByTagName('Session') and transcode_decision == 'direct play':
+ synced_version = 1
+ else:
+ synced_version = 0
+
# Figure out which version is being played
media_info_all = session.getElementsByTagName('Media')
stream_media_info = next((m for m in media_info_all if helpers.get_xml_attr(m, 'selected') == '1'), media_info_all[0])
@@ -1441,6 +1458,7 @@ class PmsConnect(object):
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_sample_rate': helpers.get_xml_attr(audio_stream_info, 'samplingRate'),
+ 'stream_audio_channel_layout_': helpers.get_xml_attr(audio_stream_info, 'audioChannelLayout'),
'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_decision': helpers.get_xml_attr(audio_stream_info, 'decision') or 'direct play'
@@ -1467,14 +1485,6 @@ class PmsConnect(object):
else:
bif_thumb = ''
- # Generate a combined transcode decision value
- if transcode_details['video_decision'] == 'transcode' or transcode_details['audio_decision'] == 'transcode':
- transcode_decision = 'transcode'
- elif transcode_details['video_decision'] == 'copy' or transcode_details['audio_decision'] == 'copy':
- transcode_decision = 'copy'
- else:
- transcode_decision = 'direct play'
-
stream_video_width = helpers.get_xml_attr(stream_media_info, 'width')
if helpers.cast_to_int(stream_video_width) >= 3840:
stream_video_resolution = '4k'
@@ -1488,7 +1498,7 @@ class PmsConnect(object):
'stream_aspect_ratio': helpers.get_xml_attr(stream_media_info, 'aspectRatio'),
'stream_audio_codec': helpers.get_xml_attr(stream_media_info, 'audioCodec'),
'stream_audio_channels': stream_audio_channels,
- 'stream_audio_channel_layout': common.AUDIO_CHANNELS.get(stream_audio_channels, stream_audio_channels),
+ 'stream_audio_channel_layout': audio_details['stream_audio_channel_layout_'] or common.AUDIO_CHANNELS.get(stream_audio_channels, stream_audio_channels),
'stream_video_codec': helpers.get_xml_attr(stream_media_info, 'videoCodec'),
'stream_video_framerate': helpers.get_xml_attr(stream_media_info, 'videoFrameRate'),
'stream_video_resolution': stream_video_resolution,
@@ -1499,14 +1509,13 @@ class PmsConnect(object):
'transcode_decision': transcode_decision,
'optimized_version': 1 if helpers.get_xml_attr(stream_media_info, 'proxyType') == '42' else 0,
'optimized_version_profile': helpers.get_xml_attr(stream_media_info, 'title'),
+ 'synced_version': synced_version,
'indexes': 1 if indexes == 'sd' else 0,
'bif_thumb': bif_thumb,
'subtitles': 1 if subtitle_details else 0
}
# 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 = {}