mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 15:32:38 -07:00
Improved synced and optimized version info
This commit is contained in:
parent
0a42cb4135
commit
33acf9402d
9 changed files with 156 additions and 42 deletions
|
@ -162,7 +162,15 @@ DOCUMENTATION :: END
|
||||||
<li class="dashboard-activity-info-item">
|
<li class="dashboard-activity-info-item">
|
||||||
<div class="sub-heading">Optimized</div>
|
<div class="sub-heading">Optimized</div>
|
||||||
<div class="sub-value" id="optimized_version-${sk}">
|
<div class="sub-value" id="optimized_version-${sk}">
|
||||||
${data['optimized_version_profile']}
|
${data['optimized_version_profile']} (${data['optimized_version_title']})
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
% endif
|
||||||
|
% if data['synced_version'] == 1:
|
||||||
|
<li class="dashboard-activity-info-item">
|
||||||
|
<div class="sub-heading">Synced</div>
|
||||||
|
<div class="sub-value" id="synced_version-${sk}">
|
||||||
|
${data['synced_version_profile']}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
% endif
|
% endif
|
||||||
|
@ -185,7 +193,7 @@ DOCUMENTATION :: END
|
||||||
% elif data['transcode_decision'] == 'copy':
|
% elif data['transcode_decision'] == 'copy':
|
||||||
Direct Stream
|
Direct Stream
|
||||||
% else:
|
% else:
|
||||||
Direct Play ${'(Synced)' if data['synced_version'] == 1 else ''}
|
Direct Play
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -250,7 +258,7 @@ DOCUMENTATION :: END
|
||||||
% elif data['stream_subtitle_decision'] == 'burn':
|
% elif data['stream_subtitle_decision'] == 'burn':
|
||||||
Burn (${data['subtitle_codec'].upper()})
|
Burn (${data['subtitle_codec'].upper()})
|
||||||
% else:
|
% else:
|
||||||
Direct Play (${data['subtitle_codec'].upper()})
|
Direct Play (${data['stream_subtitle_codec'].upper() if data['synced_version'] else data['subtitle_codec'].upper()})
|
||||||
% endif
|
% endif
|
||||||
% else:
|
% else:
|
||||||
None
|
None
|
||||||
|
|
|
@ -257,7 +257,7 @@
|
||||||
|
|
||||||
if (!(current_activity)) {
|
if (!(current_activity)) {
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
var msg_settings = ' Verify your server in the <a href="settings#tab_tabs-plex_media_server">settings</a>.';
|
var msg_settings = ' Verify your server connection in the <a href="settings#tab_tabs-plex_media_server">settings</a>.';
|
||||||
% else:
|
% else:
|
||||||
var msg_settings = ''
|
var msg_settings = ''
|
||||||
% endif
|
% endif
|
||||||
|
@ -357,7 +357,7 @@
|
||||||
} else if (s.transcode_decision === 'copy') {
|
} else if (s.transcode_decision === 'copy') {
|
||||||
transcode_decision = 'Direct Stream';
|
transcode_decision = 'Direct Stream';
|
||||||
} else {
|
} else {
|
||||||
transcode_decision = 'Direct Play' + ((s.synced_version == 1) ? ' (Synced)' : '');
|
transcode_decision = 'Direct Play';
|
||||||
}
|
}
|
||||||
$('#transcode_decision-' + key).html(transcode_decision);
|
$('#transcode_decision-' + key).html(transcode_decision);
|
||||||
|
|
||||||
|
@ -434,7 +434,7 @@
|
||||||
} else if (s.stream_subtitle_decision === 'burn') {
|
} else if (s.stream_subtitle_decision === 'burn') {
|
||||||
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
|
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
|
||||||
} else {
|
} else {
|
||||||
subtitle_decision = 'Direct Play (' + s.subtitle_codec.toUpperCase() + ')';
|
subtitle_decision = 'Direct Play (' + ((s.synced_version == '1') ? s.stream_subtitle_codec.toUpperCase() : s.subtitle_codec.toUpperCase()) + ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('#subtitle_decision-' + key).html(subtitle_decision);
|
$('#subtitle_decision-' + key).html(subtitle_decision);
|
||||||
|
@ -453,7 +453,8 @@
|
||||||
} else {
|
} else {
|
||||||
$('#stream_quality-' + key).html(s.quality_profile);
|
$('#stream_quality-' + key).html(s.quality_profile);
|
||||||
}
|
}
|
||||||
$('#optimized_version-' + key).html(s.optimized_version_profile);
|
$('#optimized_version-' + key).html(s.optimized_version_profile + ' (' + s.optimized_version_title + ')');
|
||||||
|
$('#synced_quality_profile-' + key).html(s.synced_quality_profile);
|
||||||
|
|
||||||
if (s.media_type != 'photo' && parseInt(s.bandwidth)) {
|
if (s.media_type != 'photo' && parseInt(s.bandwidth)) {
|
||||||
var bw = parseInt(s.bandwidth);
|
var bw = parseInt(s.bandwidth);
|
||||||
|
|
|
@ -98,14 +98,14 @@ DOCUMENTATION :: END
|
||||||
<tr>
|
<tr>
|
||||||
<td>Optimized Version</td>
|
<td>Optimized Version</td>
|
||||||
<td>-</td>
|
<td>-</td>
|
||||||
<td>${data['optimized_version_profile']}</td>
|
<td>${data['optimized_version_profile']}<br>(${data['optimized_version_title']})</td>
|
||||||
</tr>
|
</tr>
|
||||||
% endif
|
% endif
|
||||||
% if data['synced_version'] == 1:
|
% if data['synced_version'] == 1:
|
||||||
<tr>
|
<tr>
|
||||||
<td>Synced Version</td>
|
<td>Synced Version</td>
|
||||||
<td>-</td>
|
<td>-</td>
|
||||||
<td>yes</td>
|
<td>${data['synced_version_profile']}</td>
|
||||||
</tr>
|
</tr>
|
||||||
% endif
|
% endif
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -450,7 +450,8 @@ def dbcheck():
|
||||||
'transcode_protocol TEXT, transcode_container TEXT, '
|
'transcode_protocol TEXT, transcode_container TEXT, '
|
||||||
'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,'
|
'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,'
|
||||||
'transcode_width INTEGER, transcode_height INTEGER, '
|
'transcode_width INTEGER, transcode_height INTEGER, '
|
||||||
'optimized_version INTEGER, optimized_version_profile TEXT, synced_version INTEGER, '
|
'optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT, '
|
||||||
|
'synced_version INTEGER, synced_version_profile TEXT, '
|
||||||
'buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, write_attempts INTEGER DEFAULT 0, '
|
'buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, write_attempts INTEGER DEFAULT 0, '
|
||||||
'raw_stream_info TEXT)'
|
'raw_stream_info TEXT)'
|
||||||
)
|
)
|
||||||
|
@ -482,7 +483,8 @@ def dbcheck():
|
||||||
'stream_video_framerate TEXT, '
|
'stream_video_framerate TEXT, '
|
||||||
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
||||||
'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, '
|
'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, '
|
||||||
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, optimized_version INTEGER, optimized_version_profile TEXT)'
|
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, synced_version_profile TEXT, '
|
||||||
|
'optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT)'
|
||||||
)
|
)
|
||||||
|
|
||||||
# session_history_metadata table :: This is a table which logs each session's media metadata
|
# session_history_metadata table :: This is a table which logs each session's media metadata
|
||||||
|
@ -892,6 +894,15 @@ def dbcheck():
|
||||||
'ALTER TABLE sessions ADD COLUMN raw_stream_info TEXT'
|
'ALTER TABLE sessions ADD COLUMN raw_stream_info TEXT'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Upgrade sessions table from earlier versions
|
||||||
|
try:
|
||||||
|
c_db.execute('SELECT video_height FROM sessions')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.debug(u"Altering database. Updating database table sessions.")
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE sessions ADD COLUMN video_height INTEGER'
|
||||||
|
)
|
||||||
|
|
||||||
# Upgrade sessions table from earlier versions
|
# Upgrade sessions table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT subtitles FROM sessions')
|
c_db.execute('SELECT subtitles FROM sessions')
|
||||||
|
@ -900,13 +911,17 @@ def dbcheck():
|
||||||
c_db.execute(
|
c_db.execute(
|
||||||
'ALTER TABLE sessions ADD COLUMN subtitles INTEGER'
|
'ALTER TABLE sessions ADD COLUMN subtitles INTEGER'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Upgrade sessions table from earlier versions
|
# Upgrade sessions table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT video_height FROM sessions')
|
c_db.execute('SELECT synced_version_profile FROM sessions')
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError:
|
||||||
logger.debug(u"Altering database. Updating database table sessions.")
|
logger.debug(u"Altering database. Updating database table sessions.")
|
||||||
c_db.execute(
|
c_db.execute(
|
||||||
'ALTER TABLE sessions ADD COLUMN video_height INTEGER'
|
'ALTER TABLE sessions ADD COLUMN synced_version_profile TEXT'
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE sessions ADD COLUMN optimized_version_title TEXT'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Upgrade session_history table from earlier versions
|
# Upgrade session_history table from earlier versions
|
||||||
|
@ -1139,6 +1154,18 @@ def dbcheck():
|
||||||
'ALTER TABLE session_history_media_info ADD COLUMN subtitle_codec TEXT '
|
'ALTER TABLE session_history_media_info ADD COLUMN subtitle_codec TEXT '
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Upgrade session_history_media_info table from earlier versions
|
||||||
|
try:
|
||||||
|
c_db.execute('SELECT synced_version_profile FROM session_history_media_info')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.debug(u"Altering database. Updating database table session_history_media_info.")
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE session_history_media_info ADD COLUMN synced_version_profile TEXT '
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE session_history_media_info ADD COLUMN optimized_version_title TEXT '
|
||||||
|
)
|
||||||
|
|
||||||
# Upgrade users table from earlier versions
|
# Upgrade users table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT do_notify FROM users')
|
c_db.execute('SELECT do_notify FROM users')
|
||||||
|
|
|
@ -90,9 +90,11 @@ class ActivityProcessor(object):
|
||||||
'transcode_audio_channels': session.get('transcode_audio_channels', ''),
|
'transcode_audio_channels': session.get('transcode_audio_channels', ''),
|
||||||
'transcode_width': session.get('stream_video_width', ''),
|
'transcode_width': session.get('stream_video_width', ''),
|
||||||
'transcode_height': session.get('stream_video_height', ''),
|
'transcode_height': session.get('stream_video_height', ''),
|
||||||
|
'synced_version': session.get('synced_version', ''),
|
||||||
|
'synced_version_profile': session.get('synced_version_profile', ''),
|
||||||
'optimized_version': session.get('optimized_version', ''),
|
'optimized_version': session.get('optimized_version', ''),
|
||||||
'optimized_version_profile': session.get('optimized_version_profile', ''),
|
'optimized_version_profile': session.get('optimized_version_profile', ''),
|
||||||
'synced_version': session.get('synced_version', ''),
|
'optimized_version_title': session.get('optimized_version_title', ''),
|
||||||
'stream_bitrate': session.get('stream_bitrate', ''),
|
'stream_bitrate': session.get('stream_bitrate', ''),
|
||||||
'stream_video_resolution': session.get('stream_video_resolution', ''),
|
'stream_video_resolution': session.get('stream_video_resolution', ''),
|
||||||
'quality_profile': session.get('quality_profile', ''),
|
'quality_profile': session.get('quality_profile', ''),
|
||||||
|
@ -110,6 +112,7 @@ class ActivityProcessor(object):
|
||||||
'stream_audio_channels': session.get('stream_audio_channels', ''),
|
'stream_audio_channels': session.get('stream_audio_channels', ''),
|
||||||
'stream_subtitle_decision': session.get('stream_subtitle_decision', ''),
|
'stream_subtitle_decision': session.get('stream_subtitle_decision', ''),
|
||||||
'stream_subtitle_codec': session.get('stream_subtitle_codec', ''),
|
'stream_subtitle_codec': session.get('stream_subtitle_codec', ''),
|
||||||
|
'subtitles': session.get('subtitles', ''),
|
||||||
'raw_stream_info': json.dumps(session),
|
'raw_stream_info': json.dumps(session),
|
||||||
'stopped': int(time.time())
|
'stopped': int(time.time())
|
||||||
}
|
}
|
||||||
|
@ -356,6 +359,8 @@ class ActivityProcessor(object):
|
||||||
'stream_subtitle_forced': session['stream_subtitle_forced'],
|
'stream_subtitle_forced': session['stream_subtitle_forced'],
|
||||||
'subtitles': session['subtitles'],
|
'subtitles': session['subtitles'],
|
||||||
'synced_version': session['synced_version'],
|
'synced_version': session['synced_version'],
|
||||||
|
'synced_version_profile': session['synced_version_profile'],
|
||||||
|
'synced_version_title': session['synced_version_title'],
|
||||||
'optimized_version': session['optimized_version'],
|
'optimized_version': session['optimized_version'],
|
||||||
'optimized_version_profile': session['optimized_version_profile']
|
'optimized_version_profile': session['optimized_version_profile']
|
||||||
}
|
}
|
||||||
|
|
|
@ -872,8 +872,10 @@ class DataFactory(object):
|
||||||
user_cond = 'AND %s.user_id = %s ' % (table, session.get_session_user_id())
|
user_cond = 'AND %s.user_id = %s ' % (table, session.get_session_user_id())
|
||||||
|
|
||||||
if row_id:
|
if row_id:
|
||||||
query = 'SELECT bitrate, video_resolution, optimized_version, optimized_version_profile, synced_version, ' \
|
query = 'SELECT bitrate, video_resolution, ' \
|
||||||
'container, video_codec, video_Bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||||
|
'synced_version, synced_version_profile, ' \
|
||||||
|
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
||||||
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
||||||
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
||||||
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
||||||
|
@ -887,8 +889,10 @@ class DataFactory(object):
|
||||||
'WHERE session_history_media_info.id = ? %s' % user_cond
|
'WHERE session_history_media_info.id = ? %s' % user_cond
|
||||||
result = monitor_db.select(query, args=[row_id])
|
result = monitor_db.select(query, args=[row_id])
|
||||||
elif session_key:
|
elif session_key:
|
||||||
query = 'SELECT bitrate, video_resolution, optimized_version, optimized_version_profile, synced_version, ' \
|
query = 'SELECT bitrate, video_resolution, ' \
|
||||||
'container, video_codec, video_Bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||||
|
'synced_version, synced_version_profile, ' \
|
||||||
|
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
||||||
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
||||||
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
'stream_bitrate, stream_video_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
||||||
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
||||||
|
@ -909,7 +913,9 @@ class DataFactory(object):
|
||||||
'video_resolution': item['video_resolution'],
|
'video_resolution': item['video_resolution'],
|
||||||
'optimized_version': item['optimized_version'],
|
'optimized_version': item['optimized_version'],
|
||||||
'optimized_version_profile': item['optimized_version_profile'],
|
'optimized_version_profile': item['optimized_version_profile'],
|
||||||
|
'optimized_version_title': item['optimized_version_title'],
|
||||||
'synced_version': item['synced_version'],
|
'synced_version': item['synced_version'],
|
||||||
|
'synced_version_profile': item['synced_version_profile'],
|
||||||
'container': item['container'],
|
'container': item['container'],
|
||||||
'video_codec': item['video_codec'],
|
'video_codec': item['video_codec'],
|
||||||
'video_bitrate': item['video_bitrate'],
|
'video_bitrate': item['video_bitrate'],
|
||||||
|
|
|
@ -425,7 +425,7 @@ class PlexTV(object):
|
||||||
|
|
||||||
return users_list
|
return users_list
|
||||||
|
|
||||||
def get_synced_items(self, machine_id=None, user_id=None):
|
def get_synced_items(self, machine_id=None, client_id_filter=None, user_id_filter=None, rating_key_filter=None):
|
||||||
sync_list = self.get_plextv_sync_lists(machine_id)
|
sync_list = self.get_plextv_sync_lists(machine_id)
|
||||||
user_data = users.Users()
|
user_data = users.Users()
|
||||||
|
|
||||||
|
@ -446,9 +446,15 @@ class PlexTV(object):
|
||||||
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_synced_items.")
|
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_synced_items.")
|
||||||
else:
|
else:
|
||||||
for a in xml_head:
|
for a in xml_head:
|
||||||
sync_id = helpers.get_xml_attr(a, 'id')
|
|
||||||
client_id = helpers.get_xml_attr(a, 'clientIdentifier')
|
client_id = helpers.get_xml_attr(a, 'clientIdentifier')
|
||||||
|
|
||||||
|
# Filter by client_id
|
||||||
|
if client_id_filter and client_id_filter != client_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sync_id = helpers.get_xml_attr(a, 'id')
|
||||||
sync_device = a.getElementsByTagName('Device')
|
sync_device = a.getElementsByTagName('Device')
|
||||||
|
|
||||||
for device in sync_device:
|
for device in sync_device:
|
||||||
device_user_id = helpers.get_xml_attr(device, 'userID')
|
device_user_id = helpers.get_xml_attr(device, 'userID')
|
||||||
try:
|
try:
|
||||||
|
@ -467,12 +473,23 @@ class PlexTV(object):
|
||||||
device_last_seen = helpers.get_xml_attr(device, 'lastSeenAt')
|
device_last_seen = helpers.get_xml_attr(device, 'lastSeenAt')
|
||||||
|
|
||||||
# Filter by user_id
|
# Filter by user_id
|
||||||
if user_id and user_id != device_user_id:
|
if user_id_filter and user_id_filter != device_user_id:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for synced in a.getElementsByTagName('SyncItems'):
|
for synced in a.getElementsByTagName('SyncItems'):
|
||||||
sync_item = synced.getElementsByTagName('SyncItem')
|
sync_item = synced.getElementsByTagName('SyncItem')
|
||||||
for item in sync_item:
|
for item in sync_item:
|
||||||
|
|
||||||
|
for location in item.getElementsByTagName('Location'):
|
||||||
|
clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F')
|
||||||
|
|
||||||
|
rating_key = next((clean_uri[(idx + 1) % len(clean_uri)]
|
||||||
|
for idx, item in enumerate(clean_uri) if item == 'metadata'), None)
|
||||||
|
|
||||||
|
# Filter by rating_key
|
||||||
|
if rating_key_filter and rating_key_filter != rating_key:
|
||||||
|
continue
|
||||||
|
|
||||||
sync_id = helpers.get_xml_attr(item, 'id')
|
sync_id = helpers.get_xml_attr(item, 'id')
|
||||||
sync_version = helpers.get_xml_attr(item, 'version')
|
sync_version = helpers.get_xml_attr(item, 'version')
|
||||||
sync_root_title = helpers.get_xml_attr(item, 'rootTitle')
|
sync_root_title = helpers.get_xml_attr(item, 'rootTitle')
|
||||||
|
@ -501,12 +518,6 @@ class PlexTV(object):
|
||||||
settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality')
|
settings_video_quality = helpers.get_xml_attr(settings, 'videoQuality')
|
||||||
settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution')
|
settings_video_resolution = helpers.get_xml_attr(settings, 'videoResolution')
|
||||||
|
|
||||||
for location in item.getElementsByTagName('Location'):
|
|
||||||
clean_uri = helpers.get_xml_attr(location, 'uri').split('%2F')
|
|
||||||
|
|
||||||
rating_key = next((clean_uri[(idx + 1) % len(clean_uri)]
|
|
||||||
for idx, item in enumerate(clean_uri) if item == 'metadata'), None)
|
|
||||||
|
|
||||||
sync_details = {"device_name": helpers.sanitize(device_name),
|
sync_details = {"device_name": helpers.sanitize(device_name),
|
||||||
"platform": helpers.sanitize(device_platform),
|
"platform": helpers.sanitize(device_platform),
|
||||||
"username": helpers.sanitize(device_username),
|
"username": helpers.sanitize(device_username),
|
||||||
|
|
|
@ -24,6 +24,7 @@ import helpers
|
||||||
import http_handler
|
import http_handler
|
||||||
import libraries
|
import libraries
|
||||||
import logger
|
import logger
|
||||||
|
import plextv
|
||||||
import session
|
import session
|
||||||
import users
|
import users
|
||||||
|
|
||||||
|
@ -590,7 +591,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def get_metadata_details(self, rating_key=''):
|
def get_metadata_details(self, rating_key='', sync_id=''):
|
||||||
"""
|
"""
|
||||||
Return processed and validated metadata list for requested item.
|
Return processed and validated metadata list for requested item.
|
||||||
|
|
||||||
|
@ -598,7 +599,10 @@ class PmsConnect(object):
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
metadata = self.get_metadata(str(rating_key), output_format='xml')
|
if rating_key:
|
||||||
|
metadata = self.get_metadata(str(rating_key), output_format='xml')
|
||||||
|
elif sync_id:
|
||||||
|
metadata = self.get_sync_item(str(sync_id), output_format='xml')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||||
|
@ -1322,6 +1326,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
# Get the source media type
|
# Get the source media type
|
||||||
media_type = helpers.get_xml_attr(session, 'type')
|
media_type = helpers.get_xml_attr(session, 'type')
|
||||||
|
rating_key = helpers.get_xml_attr(session, 'ratingKey')
|
||||||
|
|
||||||
# Get the user details
|
# Get the user details
|
||||||
user_info = session.getElementsByTagName('User')[0]
|
user_info = session.getElementsByTagName('User')[0]
|
||||||
|
@ -1348,7 +1353,7 @@ class PmsConnect(object):
|
||||||
'product_version': helpers.get_xml_attr(player_info, 'version'),
|
'product_version': helpers.get_xml_attr(player_info, 'version'),
|
||||||
'profile': helpers.get_xml_attr(player_info, 'profile'),
|
'profile': helpers.get_xml_attr(player_info, 'profile'),
|
||||||
'player': helpers.get_xml_attr(player_info, 'title') or helpers.get_xml_attr(player_info, 'product'),
|
'player': helpers.get_xml_attr(player_info, 'title') or helpers.get_xml_attr(player_info, 'product'),
|
||||||
'machine_id': helpers.get_xml_attr(player_info, 'machineIdentifier').rstrip('_Video').rstrip('_Track'),
|
'machine_id': helpers.get_xml_attr(player_info, 'machineIdentifier'),
|
||||||
'state': helpers.get_xml_attr(player_info, 'state'),
|
'state': helpers.get_xml_attr(player_info, 'state'),
|
||||||
'local': helpers.get_xml_attr(player_info, 'local')
|
'local': helpers.get_xml_attr(player_info, 'local')
|
||||||
}
|
}
|
||||||
|
@ -1431,14 +1436,29 @@ class PmsConnect(object):
|
||||||
# Determine if a synced version is being played
|
# Determine if a synced version is being played
|
||||||
if media_type not in ('photo', 'clip') and not session.getElementsByTagName('Session') \
|
if media_type not in ('photo', 'clip') and not session.getElementsByTagName('Session') \
|
||||||
and helpers.get_xml_attr(session, 'ratingKey').isdigit() and transcode_decision == 'direct play':
|
and helpers.get_xml_attr(session, 'ratingKey').isdigit() and transcode_decision == 'direct play':
|
||||||
synced_version = 1
|
plex_tv = plextv.PlexTV()
|
||||||
|
synced_items = plex_tv.get_synced_items(machine_id=plexpy.CONFIG.PMS_IDENTIFIER,
|
||||||
|
client_id_filter=player_details['machine_id'],
|
||||||
|
rating_key_filter=rating_key)
|
||||||
|
if synced_items:
|
||||||
|
sync_id = synced_items[0]['sync_id']
|
||||||
|
synced_xml = self.get_sync_item(sync_id=sync_id, output_format='xml')
|
||||||
|
synced_xml_head = synced_xml.getElementsByTagName('MediaContainer')
|
||||||
|
if synced_xml_head[0].getElementsByTagName('Track'):
|
||||||
|
synced_session_data = synced_xml_head[0].getElementsByTagName('Track')[0]
|
||||||
|
elif synced_xml_head[0].getElementsByTagName('Video'):
|
||||||
|
synced_session_data = synced_xml_head[0].getElementsByTagName('Video')[0]
|
||||||
else:
|
else:
|
||||||
synced_version = 0
|
sync_id = None
|
||||||
|
|
||||||
# Figure out which version is being played
|
# Figure out which version is being played
|
||||||
media_info_all = session.getElementsByTagName('Media')
|
if sync_id:
|
||||||
|
media_info_all = synced_session_data.getElementsByTagName('Media')
|
||||||
|
else:
|
||||||
|
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])
|
stream_media_info = next((m for m in media_info_all if helpers.get_xml_attr(m, 'selected') == '1'), media_info_all[0])
|
||||||
stream_media_parts_info = stream_media_info.getElementsByTagName('Part')[0]
|
part_info_all = stream_media_info.getElementsByTagName('Part')
|
||||||
|
stream_media_parts_info = next((p for p in part_info_all if helpers.get_xml_attr(p, 'selected') == '1'), part_info_all[0])
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -1495,6 +1515,7 @@ class PmsConnect(object):
|
||||||
|
|
||||||
if subtitle_stream_info:
|
if subtitle_stream_info:
|
||||||
subtitle_id = helpers.get_xml_attr(subtitle_stream_info, 'id')
|
subtitle_id = helpers.get_xml_attr(subtitle_stream_info, 'id')
|
||||||
|
subtitle_selected = helpers.get_xml_attr(subtitle_stream_info, 'selected')
|
||||||
subtitle_details = {'stream_subtitle_codec': helpers.get_xml_attr(subtitle_stream_info, 'codec'),
|
subtitle_details = {'stream_subtitle_codec': helpers.get_xml_attr(subtitle_stream_info, 'codec'),
|
||||||
'stream_subtitle_container': helpers.get_xml_attr(subtitle_stream_info, 'container'),
|
'stream_subtitle_container': helpers.get_xml_attr(subtitle_stream_info, 'container'),
|
||||||
'stream_subtitle_format': helpers.get_xml_attr(subtitle_stream_info, 'format'),
|
'stream_subtitle_format': helpers.get_xml_attr(subtitle_stream_info, 'format'),
|
||||||
|
@ -1544,14 +1565,14 @@ 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') or helpers.get_xml_attr(session, 'duration'),
|
'stream_duration': helpers.get_xml_attr(stream_media_info, 'duration') or helpers.get_xml_attr(session, 'duration'),
|
||||||
'stream_container_decision': helpers.get_xml_attr(stream_media_parts_info, 'decision').replace('directplay', 'direct play'),
|
'stream_container_decision': 'direct play' if sync_id else helpers.get_xml_attr(stream_media_parts_info, 'decision').replace('directplay', 'direct play'),
|
||||||
'transcode_decision': transcode_decision,
|
'transcode_decision': transcode_decision,
|
||||||
'optimized_version': 1 if helpers.get_xml_attr(stream_media_info, 'proxyType') == '42' else 0,
|
'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'),
|
'optimized_version_title': helpers.get_xml_attr(stream_media_info, 'title'),
|
||||||
'synced_version': synced_version,
|
'synced_version': 1 if sync_id else 0,
|
||||||
'indexes': 1 if indexes == 'sd' else 0,
|
'indexes': 1 if indexes == 'sd' else 0,
|
||||||
'bif_thumb': bif_thumb,
|
'bif_thumb': bif_thumb,
|
||||||
'subtitles': 1 if subtitle_id else 0
|
'subtitles': 1 if subtitle_id and subtitle_selected else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the source media info
|
# Get the source media info
|
||||||
|
@ -1617,7 +1638,10 @@ class PmsConnect(object):
|
||||||
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')
|
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'))
|
if sync_id:
|
||||||
|
metadata_details = self.get_metadata_details(sync_id=sync_id)
|
||||||
|
else:
|
||||||
|
metadata_details = self.get_metadata_details(rating_key=rating_key)
|
||||||
|
|
||||||
# Get the media info, fallback to first item if match id is not found
|
# Get the media info, fallback to first item if match id is not found
|
||||||
source_medias = metadata_details.pop('media_info', [])
|
source_medias = metadata_details.pop('media_info', [])
|
||||||
|
@ -1682,7 +1706,22 @@ class PmsConnect(object):
|
||||||
quality_profile = common.VIDEO_QUALITY_PROFILES[quailtiy_bitrate]
|
quality_profile = common.VIDEO_QUALITY_PROFILES[quailtiy_bitrate]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quality_profile = 'Original'
|
quality_profile = 'Original'
|
||||||
|
|
||||||
|
if sync_id:
|
||||||
|
try:
|
||||||
|
synced_bitrate = min(b for b in common.VIDEO_QUALITY_PROFILES if source_bitrate <= b)
|
||||||
|
synced_version_profile = common.VIDEO_QUALITY_PROFILES[synced_bitrate]
|
||||||
|
except ValueError:
|
||||||
|
synced_version_profile = 'Original'
|
||||||
|
else:
|
||||||
|
synced_version_profile = ''
|
||||||
|
|
||||||
|
if stream_details['optimized_version']:
|
||||||
|
optimized_version_profile = '{} Mbps {}'.format(round(source_bitrate / 1000.0, 1),
|
||||||
|
plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(source_media_details['video_resolution'], source_media_details['video_resolution']))
|
||||||
|
else:
|
||||||
|
optimized_version_profile = ''
|
||||||
|
|
||||||
elif media_type == 'track' and 'stream_bitrate' in stream_details:
|
elif media_type == 'track' and 'stream_bitrate' in stream_details:
|
||||||
stream_bitrate = helpers.cast_to_int(stream_details['stream_bitrate'])
|
stream_bitrate = helpers.cast_to_int(stream_details['stream_bitrate'])
|
||||||
source_bitrate = helpers.cast_to_int(source_media_details.get('bitrate'))
|
source_bitrate = helpers.cast_to_int(source_media_details.get('bitrate'))
|
||||||
|
@ -1693,11 +1732,26 @@ class PmsConnect(object):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
quality_profile = 'Original'
|
quality_profile = 'Original'
|
||||||
|
|
||||||
|
if sync_id:
|
||||||
|
try:
|
||||||
|
synced_bitrate = min(b for b in common.AUDIO_QUALITY_PROFILES if source_bitrate <= b)
|
||||||
|
synced_version_profile = common.AUDIO_QUALITY_PROFILES[synced_bitrate]
|
||||||
|
except ValueError:
|
||||||
|
synced_version_profile = 'Original'
|
||||||
|
else:
|
||||||
|
synced_version_profile = ''
|
||||||
|
|
||||||
|
optimized_version_profile = ''
|
||||||
|
|
||||||
elif media_type == 'photo':
|
elif media_type == 'photo':
|
||||||
quality_profile = 'Original'
|
quality_profile = 'Original'
|
||||||
|
synced_version_profile = ''
|
||||||
|
optimized_version_profile = ''
|
||||||
|
|
||||||
else:
|
else:
|
||||||
quality_profile = 'Unknown'
|
quality_profile = 'Unknown'
|
||||||
|
synced_version_profile = ''
|
||||||
|
optimized_version_profile = ''
|
||||||
|
|
||||||
# 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'),
|
||||||
|
@ -1705,6 +1759,8 @@ class PmsConnect(object):
|
||||||
'view_offset': view_offset,
|
'view_offset': view_offset,
|
||||||
'progress_percent': str(helpers.get_percent(view_offset, stream_details['stream_duration'])),
|
'progress_percent': str(helpers.get_percent(view_offset, stream_details['stream_duration'])),
|
||||||
'quality_profile': quality_profile,
|
'quality_profile': quality_profile,
|
||||||
|
'synced_version_profile': synced_version_profile,
|
||||||
|
'optimized_version_profile': optimized_version_profile,
|
||||||
'user': user_details['username'], # Keep for backwards compatibility
|
'user': user_details['username'], # Keep for backwards compatibility
|
||||||
'channel_stream': channel_stream
|
'channel_stream': channel_stream
|
||||||
}
|
}
|
||||||
|
|
|
@ -2195,7 +2195,7 @@ class WebInterface(object):
|
||||||
machine_id = plexpy.CONFIG.PMS_IDENTIFIER
|
machine_id = plexpy.CONFIG.PMS_IDENTIFIER
|
||||||
|
|
||||||
plex_tv = plextv.PlexTV()
|
plex_tv = plextv.PlexTV()
|
||||||
result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
|
result = plex_tv.get_synced_items(machine_id=machine_id, user_id_filter=user_id)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
output = {"data": result}
|
output = {"data": result}
|
||||||
|
@ -4560,7 +4560,7 @@ class WebInterface(object):
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
plex_tv = plextv.PlexTV()
|
plex_tv = plextv.PlexTV()
|
||||||
result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
|
result = plex_tv.get_synced_items(machine_id=machine_id, user_id_filter=user_id)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return result
|
return result
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue