VERY EXPERIMENTAL CHANGES!

History logging is now under the hood. Disabled by default.
Write new database tables and upgrade old ones.
Provide more detail to get_activity.
This commit is contained in:
Tim 2015-07-11 22:10:45 +02:00
parent f5233ffed2
commit 9152fa01af
9 changed files with 596 additions and 89 deletions

View file

@ -233,7 +233,7 @@
<label for="monitoring_interval">Monitoring Interval</label> <label for="monitoring_interval">Monitoring Interval</label>
<input type="text" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required> <input type="text" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required>
<p class="help-block">The interval (in seconds) PlexPy will ping your Plex Server. Min 30 seconds, Recommended 60 seconds. 0 to disable.</p> <p class="help-block">The interval (in seconds) PlexPy will ping your Plex Server. Min 30 seconds, Recommended 60 seconds. 0 to disable.</p>
<p><strong>Disabling monitoring will disable ALL notifications.</strong></p> <p><strong>Disabling monitoring will disable ALL notifications and history logging.</strong></p>
</div> </div>
</fieldset> </fieldset>
<div class="wellheader"> <div class="wellheader">
@ -252,13 +252,33 @@
</fieldset> </fieldset>
</div> </div>
<div class="span4"> <div class="span4">
<div class="wellheader">
<h3>History Logging</h3>
</div>
<fieldset>
<div class="checkbox">
<input type="checkbox" id="video_logging_enable" name="video_logging_enable" value="1" ${config['video_logging_enable']}> Log Movies and TV
<p class="help-block">Keep records of all video items played from your Plex Media Server.</p>
</div>
<div class="form-group">
<label for="monitoring_interval">Ignore Interval</label>
<input type="text" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" required>
<p class="help-block">The interval (in seconds) PlexPy will wait for a video item to be active before logging it. 0 to disable.</p>
</div>
<div class="checkbox">
<input type="checkbox" id="music_logging_enable" name="music_logging_enable" value="1" ${config['music_logging_enable']}> Log Music
<p class="help-block">Keep records of all audio items played from your Plex Media Server. Experimental.</p>
</div>
</fieldset>
<div class="wellheader"> <div class="wellheader">
<h3>IP Logging</h3> <h3>IP Logging</h3>
</div> </div>
<fieldset> <fieldset>
<div class="checkbox"> <div class="checkbox">
<input type="checkbox" id="ip_logging_enable" name="ip_logging_enable" value="1" ${config['ip_logging_enable']}> Enable IP Logging <input type="checkbox" id="ip_logging_enable" name="ip_logging_enable" value="1" ${config['ip_logging_enable']}> Enable IP Logging
<p class="help-block">Enable this to attempt to log the IP address of the user. This currently does nothing useful.</p> <p class="help-block">
Enable this to attempt to log the IP address of the user. Debug logging must be enabled and your log folder must be set in the PlexPy settings.
</p>
</div> </div>
</fieldset> </fieldset>
</div> </div>

View file

@ -15,30 +15,43 @@ data['sessions'] Returns an array containing session data
data[sessions] :: Usable parameters data[sessions] :: Usable parameters
== Global keys == == Global keys ==
session_key Returns a unique session id for the active stream session_key Returns a unique session id for the active stream
rating_key Returns the unique identifier for the media item. rating_key Returns the unique identifier for the media item.
type Returns the type of session. Either 'track', 'episode' or 'movie'. type Returns the type of session. Either 'track', 'episode' or 'movie'.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy. thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
art Returns the location of the item's artwork bif_thumb Returns the location of the item's bif thumbnail. Use with pms_image_proxy.
progress_percent Returns the current progress of the item. 0 to 100. art Returns the location of the item's artwork
user Returns the name of the user owning the session. progress_percent Returns the current progress of the item. 0 to 100.
user_id Returns the Plex user id if available. user Returns the name of the user owning the session.
machine_id Returns the machine id of the players being used. user_id Returns the Plex user id if available.
friendly_name Returns the friendlly name of the user owning the session. machine_id Returns the machine id of the players being used.
state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'. friendly_name Returns the friendlly name of the user owning the session.
title Returns the name of the episode, movie or music track. state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'.
player Returns the name of the platform used to play the stream. title Returns the name of the episode, movie or music track.
platform Returns the type of platform used to play the stream. player Returns the name of the platform used to play the stream.
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'. platform Returns the type of platform used to play the stream.
audio_codec Returns the name of the audio codec. audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
audio_channels Returns the number of audio channels. audio_codec Returns the name of the audio codec.
grandparent_title Returns the title of the item's grandparent. audio_channels Returns the number of audio channels.
parent_title Returns the title of the item's parent. grandparent_title Returns the title of the item's grandparent.
video_decision Returns the video transcode decision. Either 'transcode', 'copy' or 'direct play'. parent_title Returns the title of the item's parent.
video_codec Returns the name of the video codec. video_decision Returns the video transcode decision. Either 'transcode', 'copy' or 'direct play'.
height Returns the value of the video height. video_codec Returns the name of the video codec.
width Returns the value of the video width. height Returns the value of the video height.
indexes Returns true if the media has media indexes and are enabled width Returns the value of the video width.
container Returns the value of the media container.
bitrate Returns the value of the media bitrate.
video_resolution Returns the value of the video resolution.
video_framerate Returns the value of the video framerate.
video_aspect_ratio Returns the value of the video aspect ratio.
transcode_audio_channels Returns the amount of audio channels if there is a transcode session.
transcode_audio_codec Returns the name of the audio codec if there is a transcode session.
transcode_video_codec Returns the name of the video codec if there is a transcode session.
transcode_width Returns the video width if there is a transcode session.
transcode_height Returns the video height if there is a transcode session.
transcode_container Returns the value of media container if there is a transcode session.
transcode_protocol Returns the value of media protocol if there is a transcode session.
indexes Returns true if the media has media indexes and are enabled
DOCUMENTATION :: END DOCUMENTATION :: END
</%doc> </%doc>
@ -54,7 +67,7 @@ DOCUMENTATION :: END
</div> </div>
% elif a['indexes']: % elif a['indexes']:
<div class="dashboard-activity-poster-face"> <div class="dashboard-activity-poster-face">
<img onload="fadeIn(this)" src="pms_image_proxy?img=${a['thumb']}&width=300&height=169" style="display: none;"/> <img onload="fadeIn(this)" src="pms_image_proxy?img=${a['bif_thumb']}&width=300&height=169" style="display: none;"/>
</div> </div>
% else: % else:
<div class="dashboard-activity-poster-face"> <div class="dashboard-activity-poster-face">
@ -114,7 +127,11 @@ DOCUMENTATION :: END
Stream: <strong>Transcoding</strong> Stream: <strong>Transcoding</strong>
% endif % endif
<br/> <br/>
Audio: <strong>${a['audio_codec']} (${a['audio_channels']}ch)</strong> % if a['audio_decision'] != 'direct play':
Audio: <strong>${a['transcode_audio_codec']} (${a['transcode_audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'direct play':
Audio: <strong>${a['audio_codec']} (${a['audio_channels']}ch)</strong>
% endif
% elif a['type'] == 'episode' or a['type'] == 'movie' or a['type'] == 'clip': % elif a['type'] == 'episode' or a['type'] == 'movie' or a['type'] == 'clip':
% if a['video_decision'] == 'direct play': % if a['video_decision'] == 'direct play':
Stream: <strong>Direct Play</strong> Stream: <strong>Direct Play</strong>
@ -122,10 +139,19 @@ DOCUMENTATION :: END
Stream: <strong>Transcoding</strong> Stream: <strong>Transcoding</strong>
% endif % endif
<br/> <br/>
Video: <strong>${a['video_decision']} (${a['video_codec']}) % if a['video_decision'] != 'direct play':
(${a['width']}x${a['height']})</strong> Video: <strong>${a['video_decision']} (${a['transcode_video_codec']})
(${a['transcode_width']}x${a['transcode_height']})</strong>
% elif a['audio_decision'] == 'direct play':
Video: <strong>${a['video_decision']} (${a['video_codec']})
(${a['width']}x${a['height']})</strong>
% endif
<br/> <br/>
Audio: <strong>${a['audio_decision']} (${a['audio_codec']}) (${a['audio_channels']}ch)</strong> % if a['audio_decision'] != 'direct play':
Audio: <strong>${a['audio_decision']} ${a['transcode_audio_codec']} (${a['transcode_audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'direct play':
Audio: <strong>${a['audio_codec']} (${a['audio_channels']}ch)</strong>
% endif
% endif % endif
<br> <br>
</div> </div>

View file

@ -93,7 +93,7 @@ from plexpy import helpers
% endif % endif
</div> </div>
<div class="summary-content-duration"> <div class="summary-content-duration">
Runtime <strong> ${data['duration']} mins</strong> Runtime <strong> <span id="runtime">${data['duration']}</span> mins</strong>
</div> </div>
<div class="summary-content-content-rating"> <div class="summary-content-content-rating">
Rated <strong> ${data['content_rating']} </strong> Rated <strong> ${data['content_rating']} </strong>
@ -287,5 +287,8 @@ from plexpy import helpers
</script> </script>
% endif % endif
<script>
$("#runtime").html(millisecondsToMinutes($("#runtime").html(), true));
</script>
% endif % endif
</%def> </%def>

View file

@ -249,4 +249,28 @@ function humanTime(seconds) {
String.prototype.toProperCase = function () { String.prototype.toProperCase = function () {
return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); return this.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}; };
function millisecondsToMinutes(ms, roundToMinute) {
console.log("Ms: " + ms)
if (ms > 0) {
seconds = ms / 1000;
minutes = seconds / 60;
if (roundToMinute) {
output = Math.round(minutes, 0)
} else {
minutesFloor = Math.floor(minutes);
secondsReal = Math.round((seconds - (minutesFloor * 60)),0);
if (secondsReal < 10) {
secondsReal = '0' + secondsReal;
}
output = minutesFloor + ':' + secondsReal;
}
return output;
} else {
return '0';
}
}

View file

@ -367,11 +367,58 @@ def dbcheck():
conn_db = sqlite3.connect(DB_FILE) conn_db = sqlite3.connect(DB_FILE)
c_db = conn_db.cursor() c_db = conn_db.cursor()
# sessions table :: This is a temp table that logs currently active sessions
c_db.execute( c_db.execute(
'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, ' 'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'session_key INTEGER, rating_key INTEGER, media_type TEXT, started INTEGER, ' 'session_key INTEGER, rating_key INTEGER, media_type TEXT, started INTEGER, '
'paused_counter INTEGER, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, ' 'paused_counter INTEGER, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, ip_address TEXT, '
'machine_id TEXT, player TEXT, title TEXT, parent_title TEXT, grandparent_title TEXT)' 'machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, '
'grandparent_title TEXT, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
'view_offset INTEGER DEFAULT 0, duration INTEGER, video_decision TEXT, audio_decision TEXT, '
'width INTEGER, height INTEGER, container TEXT, video_codec TEXT, audio_codec TEXT, '
'bitrate INTEGER, video_resolution TEXT, video_framerate TEXT, aspect_ratio TEXT, '
'audio_channels INTEGER, transcode_protocol TEXT, transcode_container TEXT, '
'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,'
'transcode_width INTEGER, transcode_height INTEGER)'
)
# session_history table :: This is a history table which logs essential stream details
c_db.execute(
'CREATE TABLE IF NOT EXISTS session_history (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'started INTEGER, stopped INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, '
'ip_address TEXT, paused_counter INTEGER, player TEXT, platform TEXT, machine_id TEXT, '
'parent_rating_key INTEGER, grandparent_rating_key INTEGER, media_type TEXT, view_offset INTEGER)'
)
# session_history_media_info table :: This is a table which logs each session's media info
c_db.execute(
'CREATE TABLE IF NOT EXISTS session_history_media_info (id INTEGER PRIMARY KEY, '
'rating_key INTEGER, video_decision TEXT, audio_decision TEXT, duration INTEGER, width INTEGER, '
'height INTEGER, container TEXT, video_codec TEXT, audio_codec TEXT, bitrate INTEGER, video_resolution TEXT, '
'video_framerate TEXT, aspect_ratio TEXT, audio_channels INTEGER, transcode_protocol TEXT, '
'transcode_container TEXT, transcode_video_codec TEXT, transcode_audio_codec TEXT, '
'transcode_audio_channels INTEGER, transcode_width INTEGER, transcode_height INTEGER)'
)
# session_history_metadata table :: This is a table which logs each session's media metadata
c_db.execute(
'CREATE TABLE IF NOT EXISTS session_history_metadata (id INTEGER PRIMARY KEY, '
'rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
'title TEXT, parent_title TEXT, grandparent_title TEXT, media_index INTEGER, parent_media_index INTEGER, '
'thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, art TEXT, media_type TEXT, '
'year INTEGER, originally_available_at TEXT, added_at INTEGER, updated_at INTEGER, last_viewed_at INTEGER, '
'content_rating TEXT, summary TEXT, rating TEXT, duration INTEGER, guid TEXT, '
'directors TEXT, writers TEXT, actors TEXT, genres TEXT, studio TEXT)'
''
)
# users table :: This table keeps record of the friends list
c_db.execute(
'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL UNIQUE, '
'friendly_name TEXT, thumb TEXT, email TEXT, is_home_user INTEGER DEFAULT NULL, '
'is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL)'
) )
# Upgrade sessions table from earlier versions # Upgrade sessions table from earlier versions
@ -419,6 +466,87 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN user_id INTEGER' 'ALTER TABLE sessions ADD COLUMN user_id INTEGER'
) )
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT ip_address from sessions')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE sessions ADD COLUMN ip_address TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN platform TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN parent_rating_key INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN grandparent_rating_key INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN view_offset INTEGER DEFAULT 0'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN duration INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_decision TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN audio_decision TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN width INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN height INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN container TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_codec TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN audio_codec TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN bitrate INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_resolution TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_framerate TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN aspect_ratio TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN audio_channels INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_protocol TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_container TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_video_codec TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_audio_codec TEXT'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_audio_channels INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_width INTEGER'
)
c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_height INTEGER'
)
conn_db.commit() conn_db.commit()
c_db.close() c_db.close()

View file

@ -73,6 +73,7 @@ _CONFIG_DEFINITIONS = {
'JOURNAL_MODE': (str, 'Advanced', 'wal'), 'JOURNAL_MODE': (str, 'Advanced', 'wal'),
'LAUNCH_BROWSER': (int, 'General', 1), 'LAUNCH_BROWSER': (int, 'General', 1),
'LOG_DIR': (str, 'General', ''), 'LOG_DIR': (str, 'General', ''),
'LOGGING_IGNORE_INTERVAL': (int, 'Monitoring', 120),
'MOVIE_NOTIFY_ENABLE': (int, 'Monitoring', 0), 'MOVIE_NOTIFY_ENABLE': (int, 'Monitoring', 0),
'MOVIE_NOTIFY_ON_START': (int, 'Monitoring', 1), 'MOVIE_NOTIFY_ON_START': (int, 'Monitoring', 1),
'MOVIE_NOTIFY_ON_STOP': (int, 'Monitoring', 0), 'MOVIE_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
@ -81,6 +82,7 @@ _CONFIG_DEFINITIONS = {
'MUSIC_NOTIFY_ON_START': (int, 'Monitoring', 1), 'MUSIC_NOTIFY_ON_START': (int, 'Monitoring', 1),
'MUSIC_NOTIFY_ON_STOP': (int, 'Monitoring', 0), 'MUSIC_NOTIFY_ON_STOP': (int, 'Monitoring', 0),
'MUSIC_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0), 'MUSIC_NOTIFY_ON_PAUSE': (int, 'Monitoring', 0),
'MUSIC_LOGGING_ENABLE': (int, 'Monitoring', 0),
'MONITORING_INTERVAL': (int, 'Monitoring', 60), 'MONITORING_INTERVAL': (int, 'Monitoring', 60),
'NMA_APIKEY': (str, 'NMA', ''), 'NMA_APIKEY': (str, 'NMA', ''),
'NMA_ENABLED': (int, 'NMA', 0), 'NMA_ENABLED': (int, 'NMA', 0),
@ -115,6 +117,7 @@ _CONFIG_DEFINITIONS = {
'TWITTER_USERNAME': (str, 'Twitter', ''), 'TWITTER_USERNAME': (str, 'Twitter', ''),
'UPDATE_DB_INTERVAL': (int, 'General', 24), 'UPDATE_DB_INTERVAL': (int, 'General', 24),
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1), 'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
'VIDEO_LOGGING_ENABLE': (int, 'Monitoring', 0),
'XBMC_ENABLED': (int, 'XBMC', 0), 'XBMC_ENABLED': (int, 'XBMC', 0),
'XBMC_HOST': (str, 'XBMC', ''), 'XBMC_HOST': (str, 'XBMC', ''),
'XBMC_PASSWORD': (str, 'XBMC', ''), 'XBMC_PASSWORD': (str, 'XBMC', ''),

View file

@ -41,21 +41,55 @@ def check_active_sessions():
media_container = session_list['sessions'] media_container = session_list['sessions']
# Check our temp table for what we must do with the new streams # Check our temp table for what we must do with the new streams
db_streams = monitor_db.select('SELECT session_key, rating_key, media_type, title, parent_title, ' db_streams = monitor_db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
'grandparent_title, user, friendly_name, player, state ' 'grandparent_title, user_id, user, friendly_name, ip_address, player, '
'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
'view_offset, duration, video_decision, audio_decision, width, height, '
'container, video_codec, audio_codec, bitrate, video_resolution, '
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
'transcode_container, transcode_video_codec, transcode_audio_codec, '
'transcode_audio_channels, transcode_width, transcode_height '
'FROM sessions') 'FROM sessions')
for result in db_streams: for result in db_streams:
# Build a result dictionary for easier referencing # Build a result dictionary for easier referencing
stream = {'session_key': result[0], stream = {'started': result[0],
'rating_key': result[1], 'session_key': result[1],
'media_type': result[2], 'rating_key': result[2],
'title': result[3], 'media_type': result[3],
'parent_title': result[4], 'title': result[4],
'grandparent_title': result[5], 'parent_title': result[5],
'user': result[6], 'grandparent_title': result[6],
'friendly_name': result[7], 'user_id': result[7],
'player': result[8], 'user': result[8],
'state': result[9] 'friendly_name': result[9],
'ip_address': result[10],
'player': result[11],
'platform': result[12],
'machine_id': result[13],
'parent_rating_key': result[14],
'grandparent_rating_key': result[15],
'state': result[16],
'view_offset': result[17],
'duration': result[18],
'video_decision': result[19],
'audio_decision': result[20],
'width': result[21],
'height': result[22],
'container': result[23],
'video_codec': result[24],
'audio_codec': result[25],
'bitrate': result[26],
'video_resolution': result[27],
'video_framerate': result[28],
'aspect_ratio': result[29],
'audio_channels': result[30],
'transcode_protocol': result[31],
'transcode_container': result[32],
'transcode_video_codec': result[33],
'transcode_audio_codec': result[34],
'transcode_audio_channels': result[35],
'transcode_width': result[36],
'transcode_height': result[37]
} }
if any(d['session_key'] == str(stream['session_key']) for d in media_container): if any(d['session_key'] == str(stream['session_key']) for d in media_container):
@ -70,15 +104,20 @@ def check_active_sessions():
notify(stream_data=stream, notify_action='pause') notify(stream_data=stream, notify_action='pause')
else: else:
# The user has stopped playing a stream # The user has stopped playing a stream
logger.debug(u"Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key']))
monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?', monitor_db.action('DELETE FROM sessions WHERE session_key = ? AND rating_key = ?',
[stream['session_key'], stream['rating_key']]) [stream['session_key'], stream['rating_key']])
# Push any notifications # Push any notifications
notify(stream_data=stream, notify_action='stop') notify(stream_data=stream, notify_action='stop')
monitor_process.write_session_history(session=stream)
else: else:
# The user's session is no longer active # The user's session is no longer active
logger.debug(u"Removing sessionKey %s from session queue" % stream['session_key'])
monitor_db.action('DELETE FROM sessions WHERE session_key = ?', [stream['session_key']]) monitor_db.action('DELETE FROM sessions WHERE session_key = ?', [stream['session_key']])
# Push any notifications # Push any notifications
notify(stream_data=stream, notify_action='stop') notify(stream_data=stream, notify_action='stop')
monitor_process.write_session_history(session=stream)
# Process the newly received session data # Process the newly received session data
for session in media_container: for session in media_container:
@ -151,6 +190,15 @@ class MonitorDatabase(object):
return sql_results return sql_results
def select_single(self, query, args=None):
sql_results = self.action(query, args).fetchone()[0]
if sql_results is None or sql_results == "":
return ""
return sql_results
def upsert(self, table_name, value_dict, key_dict): def upsert(self, table_name, value_dict, key_dict):
trans_type = 'update' trans_type = 'update'
@ -188,33 +236,149 @@ class MonitorProcessing(object):
values = {'rating_key': session['rating_key'], values = {'rating_key': session['rating_key'],
'media_type': session['type'], 'media_type': session['type'],
'state': session['state'], 'state': session['state'],
'user_id': session['user_id'],
'user': session['user'], 'user': session['user'],
'machine_id': session['machine_id'], 'machine_id': session['machine_id'],
'title': session['title'], 'title': session['title'],
'parent_title': session['parent_title'], 'parent_title': session['parent_title'],
'grandparent_title': session['grandparent_title'], 'grandparent_title': session['grandparent_title'],
'friendly_name': session['friendly_name'], 'friendly_name': session['friendly_name'],
'player': session['player'] 'player': session['player'],
'platform': session['platform'],
'parent_rating_key': session['parent_rating_key'],
'grandparent_rating_key': session['grandparent_rating_key'],
'view_offset': session['progress'],
'duration': session['duration'],
'video_decision': session['video_decision'],
'audio_decision': session['audio_decision'],
'width': session['width'],
'height': session['height'],
'container': session['container'],
'video_codec': session['video_codec'],
'audio_codec': session['audio_codec'],
'bitrate': session['bitrate'],
'video_resolution': session['video_resolution'],
'video_framerate': session['video_framerate'],
'aspect_ratio': session['aspect_ratio'],
'audio_channels': session['audio_channels'],
'transcode_protocol': session['transcode_protocol'],
'transcode_container': session['transcode_container'],
'transcode_video_codec': session['transcode_video_codec'],
'transcode_audio_codec': session['transcode_audio_codec'],
'transcode_audio_channels': session['transcode_audio_channels'],
'transcode_width': session['transcode_width'],
'transcode_height': session['transcode_height']
} }
timestamp = {'started': int(time.time())}
keys = {'session_key': session['session_key'], keys = {'session_key': session['session_key'],
'rating_key': session['rating_key']} 'rating_key': session['rating_key']}
result = self.db.upsert('sessions', values, keys) result = self.db.upsert('sessions', values, keys)
if result == 'insert': if result == 'insert':
# If it's our first write then time stamp it.
self.db.upsert('sessions', timestamp, keys)
# Push any notifications # Push any notifications
notify(stream_data=values, notify_action='play') notify(stream_data=values, notify_action='play')
started = int(time.time())
# Try and grab IP address from logs # Try and grab IP address from logs
if plexpy.CONFIG.IP_LOGGING_ENABLE and plexpy.CONFIG.PMS_LOGS_FOLDER: if plexpy.CONFIG.IP_LOGGING_ENABLE and plexpy.CONFIG.PMS_LOGS_FOLDER:
ip_address = self.find_session_ip(rating_key=session['rating_key'], ip_address = self.find_session_ip(rating_key=session['rating_key'],
machine_id=session['machine_id']) machine_id=session['machine_id'])
else:
ip_address = None
timestamp = {'started': started,
'ip_address': ip_address}
# If it's our first write then time stamp it.
self.db.upsert('sessions', timestamp, keys)
def write_session_history(self, session=None):
if session:
logging_enabled = False
if plexpy.CONFIG.VIDEO_LOGGING_ENABLE and \
(session['media_type'] == 'movie' or session['media_type'] == 'episode'):
logging_enabled = True
if plexpy.CONFIG.MUSIC_LOGGING_ENABLE and \
session['media_type'] == 'track':
logging_enabled = True
if plexpy.CONFIG.LOGGING_IGNORE_INTERVAL:
if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \
(int(time.time()) - session['started'] < plexpy.CONFIG.LOGGING_IGNORE_INTERVAL):
logging_enabled = False
logger.debug(u"Item played for %s seconds which is less than %s seconds, so we're not logging it." %
(str(int(time.time()) - session['started']), plexpy.CONFIG.LOGGING_IGNORE_INTERVAL))
if logging_enabled:
logger.debug(u"PlexPy Monitor :: Attempting to write to session_history table...")
query = 'INSERT INTO session_history (started, stopped, rating_key, parent_rating_key, grandparent_rating_key, ' \
'media_type, user_id, user, ip_address, player, platform, machine_id, view_offset) VALUES ' \
'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
args = [session['started'], int(time.time()), session['rating_key'], session['parent_rating_key'],
session['grandparent_rating_key'], session['media_type'], session['user_id'], session['user'],
session['ip_address'], session['player'], session['platform'], session['machine_id'],
session['view_offset']]
logger.debug(u"Writing session_history transaction...")
self.db.action(query=query, args=args)
# Get the id for the last transaction
last_id = self.db.select_single('SELECT max(id) FROM session_history')
logger.debug(u"Successfully written history item, last id for session_history is %s" % last_id)
logger.debug(u"PlexPy Monitor :: Attempting to write to session_history_media_info table...")
query = 'INSERT INTO session_history_media_info (id, rating_key, video_decision, audio_decision, ' \
'duration, width, height, container, video_codec, audio_codec, bitrate, video_resolution, ' \
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, transcode_container, ' \
'transcode_video_codec, transcode_audio_codec, transcode_audio_channels, transcode_width, ' \
'transcode_height) VALUES ' \
'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
args = [last_id, session['rating_key'], session['video_decision'], session['audio_decision'],
session['duration'], session['width'], session['height'], session['container'],
session['video_codec'], session['audio_codec'], session['bitrate'],
session['video_resolution'], session['video_framerate'], session['aspect_ratio'],
session['audio_channels'], session['transcode_protocol'], session['transcode_container'],
session['transcode_video_codec'], session['transcode_audio_codec'],
session['transcode_audio_channels'], session['transcode_width'], session['transcode_height']]
logger.debug(u"Writing session_history_media_info transaction...")
self.db.action(query=query, args=args)
logger.debug(u"PlexPy Monitor :: Fetching metadata for item ratingKey %s" % session['rating_key'])
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_metadata_details(rating_key=str(session['rating_key']))
metadata = result['metadata']
directors = ";".join(metadata['directors'])
writers = ";".join(metadata['writers'])
actors = ";".join(metadata['actors'])
genres = ";".join(metadata['genres'])
logger.debug(u"PlexPy Monitor :: Attempting to write to session_history_metadata table...")
query = 'INSERT INTO session_history_metadata (id, rating_key, parent_rating_key, ' \
'grandparent_rating_key, title, parent_title, grandparent_title, media_index, ' \
'parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, year, ' \
'originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, ' \
'rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \
'(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
args = [last_id, session['rating_key'], session['parent_rating_key'], session['grandparent_rating_key'],
session['title'], session['parent_title'], session['grandparent_title'], metadata['index'],
metadata['parent_index'], metadata['thumb'], metadata['parent_thumb'],
metadata['grandparent_thumb'], metadata['art'], session['media_type'], metadata['year'],
metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['rating'],
metadata['duration'], metadata['guid'], directors, writers, actors, genres, metadata['studio']]
logger.debug(u"Writing session_history_metadata transaction...")
self.db.action(query=query, args=args)
def find_session_ip(self, rating_key=None, machine_id=None): def find_session_ip(self, rating_key=None, machine_id=None):

View file

@ -263,6 +263,9 @@ class PmsConnect(object):
elif a.getElementsByTagName('Video'): elif a.getElementsByTagName('Video'):
metadata_main = a.getElementsByTagName('Video')[0] metadata_main = a.getElementsByTagName('Video')[0]
metadata_type = helpers.get_xml_attr(metadata_main, 'type') metadata_type = helpers.get_xml_attr(metadata_main, 'type')
elif a.getElementsByTagName('Track'):
metadata_main = a.getElementsByTagName('Track')[0]
metadata_type = helpers.get_xml_attr(metadata_main, 'type')
else: else:
logger.debug(u"Metadata failed") logger.debug(u"Metadata failed")
@ -299,12 +302,17 @@ class PmsConnect(object):
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'), 'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'), 'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'), 'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'writers': writers, 'writers': writers,
'directors': directors, 'directors': directors,
'genres': genres, 'genres': genres,
@ -323,12 +331,17 @@ class PmsConnect(object):
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'), 'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'), 'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'), 'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'writers': writers, 'writers': writers,
'directors': directors, 'directors': directors,
'genres': genres, 'genres': genres,
@ -347,12 +360,17 @@ class PmsConnect(object):
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'), 'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'), 'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'), 'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.convert_milliseconds_to_minutes(helpers.get_xml_attr(metadata_main, 'duration')), 'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'), 'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'), 'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'), 'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'genres': genres, 'genres': genres,
'actors': actors, 'actors': actors,
'writers': writers, 'writers': writers,
@ -377,8 +395,42 @@ class PmsConnect(object):
'year': helpers.get_xml_attr(metadata_main, 'year'), 'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'), 'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'), 'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'), 'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'genres': genres,
'actors': actors,
'writers': writers,
'directors': directors
}
metadata_list = {'metadata': metadata}
elif metadata_type == 'track':
metadata = {'type': metadata_type,
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
'grandparent_title': helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
'parent_index': helpers.get_xml_attr(metadata_main, 'parentIndex'),
'parent_title': helpers.get_xml_attr(metadata_main, 'parentTitle'),
'index': helpers.get_xml_attr(metadata_main, 'index'),
'studio': helpers.get_xml_attr(metadata_main, 'studio'),
'title': helpers.get_xml_attr(metadata_main, 'title'),
'content_rating': helpers.get_xml_attr(metadata_main, 'contentRating'),
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
'rating': helpers.get_xml_attr(metadata_main, 'rating'),
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
'year': helpers.get_xml_attr(metadata_main, 'year'),
'thumb': helpers.get_xml_attr(metadata_main, 'thumb'),
'parent_thumb': helpers.get_xml_attr(metadata_main, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(metadata_main, 'grandparentThumb'),
'art': helpers.get_xml_attr(metadata_main, 'art'),
'originally_available_at': helpers.get_xml_attr(metadata_main, 'originallyAvailableAt'),
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
'genres': genres, 'genres': genres,
'actors': actors, 'actors': actors,
'writers': writers, 'writers': writers,
@ -445,20 +497,29 @@ class PmsConnect(object):
session_output = None session_output = None
plex_watch = plexwatch.PlexWatch() plex_watch = plexwatch.PlexWatch()
if stream_type == 'track': if stream_type == 'track':
media_info = session.getElementsByTagName('Media')[0]
audio_decision = 'direct play'
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels')
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec')
container = helpers.get_xml_attr(media_info, 'container')
bitrate = helpers.get_xml_attr(media_info, 'bitrate')
duration = helpers.get_xml_attr(media_info, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
if session.getElementsByTagName('TranscodeSession'): if session.getElementsByTagName('TranscodeSession'):
transcode_session = session.getElementsByTagName('TranscodeSession')[0] transcode_session = session.getElementsByTagName('TranscodeSession')[0]
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision') audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels') transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec') transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
transcode_container = helpers.get_xml_attr(transcode_session, 'container')
transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol')
duration = helpers.get_xml_attr(transcode_session, 'duration') duration = helpers.get_xml_attr(transcode_session, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
else: else:
media_info = session.getElementsByTagName('Media')[0] transcode_audio_channels = ''
audio_decision = 'direct play' transcode_audio_codec = ''
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels') transcode_container = ''
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec') transcode_protocol = ''
duration = helpers.get_xml_attr(media_info, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
user_details = plex_watch.get_user_details( user_details = plex_watch.get_user_details(
user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title')) user=helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'))
@ -471,7 +532,9 @@ class PmsConnect(object):
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'), session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'), 'art': helpers.get_xml_attr(session, 'art'),
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(session, 'grandparentThumb'),
'thumb': helpers.get_xml_attr(session, 'thumb'), 'thumb': helpers.get_xml_attr(session, 'thumb'),
'bif_thumb': '',
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'), 'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'user_id': user_details['user_id'], 'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'], 'friendly_name': user_details['friendly_name'],
@ -483,6 +546,8 @@ class PmsConnect(object):
'parent_title': helpers.get_xml_attr(session, 'parentTitle'), 'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
'title': helpers.get_xml_attr(session, 'title'), 'title': helpers.get_xml_attr(session, 'title'),
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
'audio_decision': audio_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@ -490,6 +555,18 @@ class PmsConnect(object):
'video_codec': '', 'video_codec': '',
'height': '', 'height': '',
'width': '', 'width': '',
'container': container,
'bitrate': bitrate,
'video_resolution': '',
'video_framerate': '',
'aspect_ratio': '',
'transcode_audio_channels': transcode_audio_channels,
'transcode_audio_codec': transcode_audio_codec,
'transcode_video_codec': '',
'transcode_width': '',
'transcode_height': '',
'transcode_container': transcode_container,
'transcode_protocol': transcode_protocol,
'duration': duration, 'duration': duration,
'progress': progress, 'progress': progress,
'progress_percent': str(helpers.get_percent(progress, duration)), 'progress_percent': str(helpers.get_percent(progress, duration)),
@ -497,28 +574,41 @@ class PmsConnect(object):
'indexes': 0 'indexes': 0
} }
elif stream_type == 'video': elif stream_type == 'video':
media_info = session.getElementsByTagName('Media')[0]
audio_decision = 'direct play'
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels')
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec')
video_decision = 'direct play'
video_codec = helpers.get_xml_attr(media_info, 'videoCodec')
container = helpers.get_xml_attr(media_info, 'container')
bitrate = helpers.get_xml_attr(media_info, 'bitrate')
video_resolution = helpers.get_xml_attr(media_info, 'videoResolution')
video_framerate = helpers.get_xml_attr(media_info, 'videoFrameRate')
aspect_ratio = helpers.get_xml_attr(media_info, 'aspectRatio')
width = helpers.get_xml_attr(media_info, 'width')
height = helpers.get_xml_attr(media_info, 'height')
duration = helpers.get_xml_attr(media_info, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
if session.getElementsByTagName('TranscodeSession'): if session.getElementsByTagName('TranscodeSession'):
transcode_session = session.getElementsByTagName('TranscodeSession')[0] transcode_session = session.getElementsByTagName('TranscodeSession')[0]
audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision') audio_decision = helpers.get_xml_attr(transcode_session, 'audioDecision')
audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels') transcode_audio_channels = helpers.get_xml_attr(transcode_session, 'audioChannels')
audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec') transcode_audio_codec = helpers.get_xml_attr(transcode_session, 'audioCodec')
video_decision = helpers.get_xml_attr(transcode_session, 'videoDecision') video_decision = helpers.get_xml_attr(transcode_session, 'videoDecision')
video_codec = helpers.get_xml_attr(transcode_session, 'videoCodec') transcode_video_codec = helpers.get_xml_attr(transcode_session, 'videoCodec')
width = helpers.get_xml_attr(transcode_session, 'width') transcode_width = helpers.get_xml_attr(transcode_session, 'width')
height = helpers.get_xml_attr(transcode_session, 'height') transcode_height = helpers.get_xml_attr(transcode_session, 'height')
duration = helpers.get_xml_attr(session, 'duration') transcode_container = helpers.get_xml_attr(transcode_session, 'container')
progress = helpers.get_xml_attr(session, 'viewOffset') transcode_protocol = helpers.get_xml_attr(transcode_session, 'protocol')
else: else:
media_info = session.getElementsByTagName('Media')[0] transcode_audio_channels = ''
audio_decision = 'direct play' transcode_audio_codec = ''
audio_channels = helpers.get_xml_attr(media_info, 'audioChannels') transcode_video_codec = ''
audio_codec = helpers.get_xml_attr(media_info, 'audioCodec') transcode_width = ''
video_decision = 'direct play' transcode_height = ''
video_codec = helpers.get_xml_attr(media_info, 'videoCodec') transcode_container = ''
width = helpers.get_xml_attr(media_info, 'width') transcode_protocol = ''
height = helpers.get_xml_attr(media_info, 'height')
duration = helpers.get_xml_attr(media_info, 'duration')
progress = helpers.get_xml_attr(session, 'viewOffset')
media_info = session.getElementsByTagName('Media')[0] media_info = session.getElementsByTagName('Media')[0]
if media_info.getElementsByTagName('Part'): if media_info.getElementsByTagName('Part'):
@ -533,10 +623,8 @@ class PmsConnect(object):
bif_thumb = '' bif_thumb = ''
if plexpy.CONFIG.PMS_USE_BIF and indexes == 'sd': if plexpy.CONFIG.PMS_USE_BIF and indexes == 'sd':
thumb = bif_thumb
use_indexes = 1 use_indexes = 1
else: else:
thumb = helpers.get_xml_attr(session, 'thumb')
use_indexes = 0 use_indexes = 0
user_details = plex_watch.get_user_details( user_details = plex_watch.get_user_details(
@ -551,7 +639,9 @@ class PmsConnect(object):
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'), session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'), 'art': helpers.get_xml_attr(session, 'art'),
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'thumb': thumb, 'grandparent_thumb': helpers.get_xml_attr(session, 'grandparentThumb'),
'thumb': helpers.get_xml_attr(session, 'thumb'),
'bif_thumb': bif_thumb,
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'), 'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'user_id': user_details['user_id'], 'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'], 'friendly_name': user_details['friendly_name'],
@ -563,6 +653,8 @@ class PmsConnect(object):
'parent_title': helpers.get_xml_attr(session, 'parentTitle'), 'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
'title': helpers.get_xml_attr(session, 'title'), 'title': helpers.get_xml_attr(session, 'title'),
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
'audio_decision': audio_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@ -570,6 +662,18 @@ class PmsConnect(object):
'video_codec': video_codec, 'video_codec': video_codec,
'height': height, 'height': height,
'width': width, 'width': width,
'container': container,
'bitrate': bitrate,
'video_resolution': video_resolution,
'video_framerate': video_framerate,
'aspect_ratio': aspect_ratio,
'transcode_audio_channels': transcode_audio_channels,
'transcode_audio_codec': transcode_audio_codec,
'transcode_video_codec': transcode_video_codec,
'transcode_width': transcode_width,
'transcode_height': transcode_height,
'transcode_container': transcode_container,
'transcode_protocol': transcode_protocol,
'duration': duration, 'duration': duration,
'progress': progress, 'progress': progress,
'progress_percent': str(helpers.get_percent(progress, duration)), 'progress_percent': str(helpers.get_percent(progress, duration)),
@ -579,8 +683,10 @@ class PmsConnect(object):
elif helpers.get_xml_attr(session, 'type') == 'movie': elif helpers.get_xml_attr(session, 'type') == 'movie':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'), session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'), 'art': helpers.get_xml_attr(session, 'art'),
'thumb': thumb, 'thumb': helpers.get_xml_attr(session, 'thumb'),
'bif_thumb': bif_thumb,
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(session, 'grandparentThumb'),
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'), 'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'user_id': user_details['user_id'], 'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'], 'friendly_name': user_details['friendly_name'],
@ -592,6 +698,8 @@ class PmsConnect(object):
'parent_title': helpers.get_xml_attr(session, 'parentTitle'), 'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
'title': helpers.get_xml_attr(session, 'title'), 'title': helpers.get_xml_attr(session, 'title'),
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
'audio_decision': audio_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@ -599,6 +707,18 @@ class PmsConnect(object):
'video_codec': video_codec, 'video_codec': video_codec,
'height': height, 'height': height,
'width': width, 'width': width,
'container': container,
'bitrate': bitrate,
'video_resolution': video_resolution,
'video_framerate': video_framerate,
'aspect_ratio': aspect_ratio,
'transcode_audio_channels': transcode_audio_channels,
'transcode_audio_codec': transcode_audio_codec,
'transcode_video_codec': transcode_video_codec,
'transcode_width': transcode_width,
'transcode_height': transcode_height,
'transcode_container': transcode_container,
'transcode_protocol': transcode_protocol,
'duration': duration, 'duration': duration,
'progress': progress, 'progress': progress,
'progress_percent': str(helpers.get_percent(progress, duration)), 'progress_percent': str(helpers.get_percent(progress, duration)),
@ -608,8 +728,10 @@ class PmsConnect(object):
elif helpers.get_xml_attr(session, 'type') == 'clip': elif helpers.get_xml_attr(session, 'type') == 'clip':
session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'), session_output = {'session_key': helpers.get_xml_attr(session, 'sessionKey'),
'art': helpers.get_xml_attr(session, 'art'), 'art': helpers.get_xml_attr(session, 'art'),
'thumb': thumb, 'thumb': helpers.get_xml_attr(session, 'thumb'),
'bif_thumb': bif_thumb,
'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'), 'parent_thumb': helpers.get_xml_attr(session, 'parentThumb'),
'grandparent_thumb': helpers.get_xml_attr(session, 'grandparentThumb'),
'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'), 'user': helpers.get_xml_attr(session.getElementsByTagName('User')[0], 'title'),
'user_id': user_details['user_id'], 'user_id': user_details['user_id'],
'friendly_name': user_details['friendly_name'], 'friendly_name': user_details['friendly_name'],
@ -621,6 +743,8 @@ class PmsConnect(object):
'parent_title': helpers.get_xml_attr(session, 'parentTitle'), 'parent_title': helpers.get_xml_attr(session, 'parentTitle'),
'title': helpers.get_xml_attr(session, 'title'), 'title': helpers.get_xml_attr(session, 'title'),
'rating_key': helpers.get_xml_attr(session, 'ratingKey'), 'rating_key': helpers.get_xml_attr(session, 'ratingKey'),
'parent_rating_key': helpers.get_xml_attr(session, 'parentRatingKey'),
'grandparent_rating_key': helpers.get_xml_attr(session, 'grandparentRatingKey'),
'audio_decision': audio_decision, 'audio_decision': audio_decision,
'audio_channels': audio_channels, 'audio_channels': audio_channels,
'audio_codec': audio_codec, 'audio_codec': audio_codec,
@ -628,6 +752,18 @@ class PmsConnect(object):
'video_codec': video_codec, 'video_codec': video_codec,
'height': height, 'height': height,
'width': width, 'width': width,
'container': container,
'bitrate': bitrate,
'video_resolution': video_resolution,
'video_framerate': video_framerate,
'aspect_ratio': aspect_ratio,
'transcode_audio_channels': transcode_audio_channels,
'transcode_audio_codec': transcode_audio_codec,
'transcode_video_codec': transcode_video_codec,
'transcode_width': transcode_width,
'transcode_height': transcode_height,
'transcode_container': transcode_container,
'transcode_protocol': transcode_protocol,
'duration': duration, 'duration': duration,
'progress': progress, 'progress': progress,
'progress_percent': str(helpers.get_percent(progress, duration)), 'progress_percent': str(helpers.get_percent(progress, duration)),

View file

@ -345,7 +345,10 @@ class WebInterface(object):
"monitoring_interval": plexpy.CONFIG.MONITORING_INTERVAL, "monitoring_interval": plexpy.CONFIG.MONITORING_INTERVAL,
"refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL, "refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL,
"refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP), "refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP),
"ip_logging_enable": checked(plexpy.CONFIG.IP_LOGGING_ENABLE) "ip_logging_enable": checked(plexpy.CONFIG.IP_LOGGING_ENABLE),
"video_logging_enable": checked(plexpy.CONFIG.VIDEO_LOGGING_ENABLE),
"music_logging_enable": checked(plexpy.CONFIG.MUSIC_LOGGING_ENABLE),
"logging_ignore_interval": plexpy.CONFIG.LOGGING_IGNORE_INTERVAL
} }
return serve_template(templatename="config.html", title="Settings", config=config) return serve_template(templatename="config.html", title="Settings", config=config)
@ -366,7 +369,7 @@ class WebInterface(object):
"tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start", "tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start",
"tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop", "tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop",
"tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup", "tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup",
"ip_logging_enable" "ip_logging_enable", "video_logging_enable", "music_logging_enable"
] ]
for checked_config in checked_configs: for checked_config in checked_configs:
if checked_config not in kwargs: if checked_config not in kwargs: