diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 857c1f0c..cb65ff41 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -424,35 +424,57 @@ def dbcheck(): 'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, session_key INTEGER, ' 'transcode_key TEXT, rating_key INTEGER, section_id INTEGER, media_type TEXT, started INTEGER, stopped INTEGER, ' 'paused_counter INTEGER DEFAULT 0, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, ' - 'ip_address TEXT, machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, ' + 'ip_address TEXT, machine_id TEXT, player TEXT, product TEXT, platform TEXT, title TEXT, parent_title TEXT, ' 'grandparent_title TEXT, full_title TEXT, media_index INTEGER, parent_media_index INTEGER, ' 'thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, year INTEGER, ' 'parent_rating_key INTEGER, grandparent_rating_key INTEGER, ' 'view_offset INTEGER DEFAULT 0, duration INTEGER, video_decision TEXT, audio_decision TEXT, ' - 'transcode_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_decision TEXT, container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, ' + 'video_codec TEXT, video_bitrate INTEGER, video_resolution TEXT, video_width INTEGER, video_width INTEGER, ' + 'video_framerate TEXT, aspect_ratio TEXT, ' + 'audio_codec TEXT, audio_bitrate INTEGER, audio_channels INTEGER, subtitle_codec TEXT, ' + 'stream_bitrate INTEGER, stream_video_resolution TEXT, quality_profile TEXT, ' + 'stream_container_decision TEXT, stream_container TEXT, ' + 'stream_video_decision TEXT, stream_video_codec TEXT, stream_video_bitrate INTEGER, stream_video_width INTEGER, ' + 'stream_video_height INTEGER, stream_video_framerate TEXT, ' + 'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, ' + 'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, ' + 'transcode_protocol TEXT, transcode_container TEXT, ' 'transcode_video_codec TEXT, transcode_audio_codec TEXT, transcode_audio_channels INTEGER,' - 'transcode_width INTEGER, transcode_height INTEGER, buffer_count INTEGER DEFAULT 0, ' - 'buffer_last_triggered INTEGER, last_paused INTEGER, write_attempts INTEGER DEFAULT 0)' + 'transcode_width INTEGER, transcode_height INTEGER, ' + 'optimized_version INTEGER, optimized_version_profile TEXT, synced_version INTEGER, ' + 'buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, write_attempts INTEGER DEFAULT 0, ' + 'raw_stream_info TEXT)' ) # 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, reference_id INTEGER, ' 'started INTEGER, stopped INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, ' - 'ip_address TEXT, paused_counter INTEGER DEFAULT 0, player TEXT, platform TEXT, machine_id TEXT, ' + 'ip_address TEXT, paused_counter INTEGER DEFAULT 0, player TEXT, product TEXT, product_version TEXT, platform TEXT, platform_version TEXT, profile TEXT, machine_id TEXT, ' + 'bandwidth INTEGER, location TEXT, quality_profile TEXT, ' 'parent_rating_key INTEGER, grandparent_rating_key INTEGER, media_type TEXT, view_offset INTEGER DEFAULT 0)' ) # 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, transcode_decision TEXT, duration INTEGER DEFAULT 0, 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, ' + 'video_decision TEXT, audio_decision TEXT, transcode_decision TEXT, duration INTEGER DEFAULT 0, ' + 'container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, video_bitrate INTEGER, video_bit_depth INTEGER, ' + 'video_codec TEXT, video_codec_level TEXT, video_width INTEGER, video_height INTEGER, video_resolution TEXT, ' + 'video_framerate TEXT, aspect_ratio TEXT, ' + 'audio_bitrate INTEGER, audio_codec 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)' + 'transcode_audio_channels INTEGER, transcode_width INTEGER, transcode_height INTEGER, ' + 'transcode_hw_requested INTEGER, transcode_hw_full_pipeline INTEGER, transcode_hw_decode TEXT, ' + 'transcode_hw_decode_title TEXT, transcode_hw_encode TEXT, transcode_hw_encode_title TEXT, ' + 'stream_container TEXT, stream_container_decision TEXT, stream_bitrate INTEGER, ' + 'stream_video_decision TEXT, stream_video_bitrate INTEGER, stream_video_codec TEXT, stream_video_codec_level TEXT, ' + 'stream_video_bit_depth INTEGER, stream_video_height INTEGER, stream_video_width INTEGER, stream_video_resolution TEXT, ' + 'stream_video_framerate TEXT, ' + '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, ' + 'subtitles INTEGER, synced_version INTEGER, optimized_version INTEGER, optimized_version_profile TEXT)' ) # session_history_metadata table :: This is a table which logs each session's media metadata @@ -772,6 +794,96 @@ def dbcheck(): 'ALTER TABLE sessions ADD COLUMN year INTEGER' ) + # Upgrade sessions table from earlier versions + try: + c_db.execute('SELECT raw_stream_info FROM sessions') + except sqlite3.OperationalError: + logger.debug(u"Altering database. Updating database table sessions.") + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN product INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN optimized_version INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN optimized_version_profile TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN synced_version INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN video_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN video_width INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN video_height INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN audio_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN subtitle_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_resolution TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN quality_profile TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_container_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_container TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_width INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_height INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_video_framerate TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_audio_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_audio_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_audio_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_audio_channels INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN subtitles INTEGER' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_subtitle_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN stream_subtitle_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE sessions ADD COLUMN raw_stream_info TEXT' + ) + # Upgrade session_history table from earlier versions try: c_db.execute('SELECT reference_id FROM session_history') @@ -795,6 +907,33 @@ def dbcheck(): 'WHERE t1.id = session_history.id) ' ) + # Upgrade session_history table from earlier versions + try: + c_db.execute('SELECT bandwidth FROM session_history') + except sqlite3.OperationalError: + logger.debug(u"Altering database. Updating database table session_history.") + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN platform_version TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN product TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN product_version TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN profile TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN bandwidth INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN location TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history ADD COLUMN quality_profile TEXT' + ) + # Upgrade session_history_metadata table from earlier versions try: c_db.execute('SELECT full_title FROM session_history_metadata') @@ -846,6 +985,126 @@ def dbcheck(): 'WHEN video_decision = "direct play" OR audio_decision = "direct play" THEN "direct play" END)' ) + # Upgrade session_history_media_info table from earlier versions + try: + c_db.execute('SELECT subtitles 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 video_bit_depth INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN video_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN video_codec_level TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN video_width INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN video_height INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN audio_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_requested INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_full_pipeline INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_decode TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_encode TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_decode_title TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_encode_title TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_container TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_container_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_codec_level TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_bit_depth INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_height INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_width INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_resolution TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_video_framerate TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_audio_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_audio_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_audio_bitrate INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_audio_channels INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_subtitle_decision TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_subtitle_codec TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_subtitle_container TEXT' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN stream_subtitle_forced INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN subtitles INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN synced_version INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN optimized_version INTEGER' + ) + c_db.execute( + 'ALTER TABLE session_history_media_info ADD COLUMN optimized_version_profile TEXT' + ) + c_db.execute( + 'UPDATE session_history_media_info SET video_resolution=REPLACE(video_resolution, "p", "")' + ) + c_db.execute( + 'UPDATE session_history_media_info SET video_resolution=REPLACE(video_resolution, "SD", "sd")' + ) + # Upgrade users table from earlier versions try: c_db.execute('SELECT do_notify FROM users') diff --git a/plexpy/activity_processor.py b/plexpy/activity_processor.py index 978fc301..b451b44a 100644 --- a/plexpy/activity_processor.py +++ b/plexpy/activity_processor.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU General Public License # along with PlexPy. If not, see . +import json import threading import time import re @@ -69,13 +70,18 @@ class ActivityProcessor(object): 'width': session.get('width', ''), 'height': session.get('height', ''), 'container': session.get('container', ''), - 'video_codec': session.get('video_codec', ''), - 'audio_codec': session.get('audio_codec', ''), 'bitrate': session.get('bitrate', ''), + 'video_codec': session.get('video_codec', ''), + 'video_bitrate': session.get('video_bitrate', ''), + 'video_width': session.get('video_width', ''), + 'video_height': session.get('video_height', ''), 'video_resolution': session.get('video_resolution', ''), 'video_framerate': session.get('video_framerate', ''), 'aspect_ratio': session.get('aspect_ratio', ''), + 'audio_codec': session.get('audio_codec', ''), + 'audio_bitrate': session.get('audio_bitrate', ''), 'audio_channels': session.get('audio_channels', ''), + 'subtitle_codec': session.get('subtitle_codec', ''), 'transcode_protocol': session.get('transcode_protocol', ''), 'transcode_container': session.get('transcode_container', ''), 'transcode_video_codec': session.get('transcode_video_codec', ''), @@ -83,6 +89,27 @@ class ActivityProcessor(object): 'transcode_audio_channels': session.get('transcode_audio_channels', ''), 'transcode_width': session.get('stream_video_width', ''), 'transcode_height': session.get('stream_video_height', ''), + 'optimized_version': session.get('optimized_version', ''), + 'optimized_version_profile': session.get('optimized_version_profile', ''), + 'synced_version': session.get('synced_version', ''), + 'stream_bitrate': session.get('stream_bitrate', ''), + 'stream_video_resolution': session.get('stream_video_resolution', ''), + 'quality_profile': session.get('quality_profile', ''), + 'stream_container_decision': session.get('stream_container_decision', ''), + 'stream_container': session.get('stream_container', ''), + 'stream_video_decision': session.get('stream_video_decision', ''), + 'stream_video_codec': session.get('stream_video_codec', ''), + 'stream_video_bitrate': session.get('stream_video_bitrate', ''), + 'stream_video_width': session.get('stream_video_width', ''), + 'stream_video_height': session.get('stream_video_height', ''), + 'stream_video_framerate': session.get('stream_video_framerate', ''), + 'stream_audio_decision': session.get('stream_audio_decision', ''), + 'stream_audio_codec': session.get('stream_audio_codec', ''), + 'stream_audio_bitrate': session.get('stream_audio_bitrate', ''), + 'stream_audio_channels': session.get('stream_audio_channels', ''), + 'stream_subtitle_decision': session.get('stream_subtitle_decision', ''), + 'stream_subtitle_codec': session.get('stream_subtitle_codec', ''), + 'raw_stream_info': json.dumps(session), 'stopped': int(time.time()) } @@ -125,6 +152,10 @@ class ActivityProcessor(object): if session: logging_enabled = False + # Reload json from raw stream info + if 'raw_stream_info' in session: + session.update(json.loads(session['raw_stream_info'])) + if is_import: if str(session['stopped']).isdigit(): stopped = int(session['stopped']) @@ -196,18 +227,32 @@ class ActivityProcessor(object): media_info = session # logger.debug(u"PlexPy ActivityProcessor :: 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, paused_counter, player, ' \ - 'platform, machine_id, view_offset) VALUES ' \ - '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' - - args = [session['started'], stopped, session['rating_key'], session['parent_rating_key'], - session['grandparent_rating_key'], session['media_type'], session['user_id'], session['user'], - session['ip_address'], session['paused_counter'], session['player'], session['platform'], - session['machine_id'], session['view_offset']] + keys = {'id': None} + values = {'started': session['started'], + 'stopped': stopped, + 'rating_key': session['rating_key'], + 'parent_rating_key': session['parent_rating_key'], + 'grandparent_rating_key': session['grandparent_rating_key'], + 'media_type': session['media_type'], + 'user_id': session['user_id'], + 'user': session['user'], + 'ip_address': session['ip_address'], + 'paused_counter': session['paused_counter'], + 'player': session['player'], + 'product': session['product'], + 'product_version': session['product_version'], + 'platform': session['platform'], + 'platform_version': session['platform_version'], + 'profile': session['profile'], + 'machine_id': session['machine_id'], + 'bandwidth': session['bandwidth'], + 'location': session['location'], + 'quality_profile': session['quality_profile'], + 'view_offset': session['view_offset'] + } # logger.debug(u"PlexPy ActivityProcessor :: Writing session_history transaction...") - self.db.action(query=query, args=args) + self.db.upsert(table_name='session_history', key_dict=keys, value_dict=values) # Check if we should group the session, select the last two rows from the user query = 'SELECT id, rating_key, view_offset, user_id, reference_id FROM session_history \ @@ -217,7 +262,10 @@ class ActivityProcessor(object): result = self.db.select(query=query, args=args) - new_session = prev_session = last_id = None + new_session = prev_session = None + # Get the last insert row id + last_id = self.db.last_insert_id() + if len(result) > 1: new_session = {'id': result[0]['id'], 'rating_key': result[0]['rating_key'], @@ -230,9 +278,6 @@ class ActivityProcessor(object): 'view_offset': result[1]['view_offset'], 'user_id': result[1]['user_id'], 'reference_id': result[1]['reference_id']} - else: - # Get the last insert row id - last_id = self.db.last_insert_id() query = 'UPDATE session_history SET reference_id = ? WHERE id = ? ' # If rating_key is the same in the previous session, then set the reference_id to the previous row, else set the reference_id to the new id @@ -251,24 +296,69 @@ class ActivityProcessor(object): # Write the session_history_media_info table # logger.debug(u"PlexPy ActivityProcessor :: 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, transcode_decision) VALUES ' \ - '(last_insert_rowid(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' - - args = [session['rating_key'], session['video_decision'], session['audio_decision'], - metadata['duration'], media_info.get('width',''), media_info.get('height',''), media_info.get('container',''), - media_info.get('video_codec',''), media_info.get('audio_codec',''), media_info.get('bitrate',''), - media_info.get('video_resolution',''), media_info.get('video_framerate',''), media_info.get('aspect_ratio',''), - media_info.get('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'], - session['transcode_decision']] + keys = {'id': last_id} + values = {'rating_key': session['rating_key'], + 'video_decision': session['video_decision'], + 'audio_decision': session['audio_decision'], + 'transcode_decision': session['transcode_decision'], + 'duration': session['duration'], + 'container': session['container'], + 'bitrate': session['bitrate'], + 'width': session['width'], + 'height': session['height'], + 'video_bit_depth': session['video_bit_depth'], + 'video_bitrate': session['video_bitrate'], + 'video_codec': session['video_codec'], + 'video_codec_level': session['video_codec_level'], + 'video_width': session['video_width'], + 'video_height': session['video_height'], + 'video_resolution': session['video_resolution'], + 'video_framerate': session['video_framerate'], + 'aspect_ratio': session['aspect_ratio'], + 'audio_codec': session['audio_codec'], + 'audio_bitrate': session['audio_bitrate'], + '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'], + 'transcode_hw_requested': session['transcode_hw_requested'], + 'transcode_hw_full_pipeline': session['transcode_hw_full_pipeline'], + 'transcode_hw_decode': session['transcode_hw_decode'], + 'transcode_hw_encode': session['transcode_hw_encode'], + 'transcode_hw_decode_title': session['transcode_hw_decode_title'], + 'transcode_hw_encode_title': session['transcode_hw_encode_title'], + 'stream_container': session['stream_container'], + 'stream_container_decision': session['stream_container_decision'], + 'stream_bitrate': session['stream_bitrate'], + 'stream_video_decision': session['stream_video_decision'], + 'stream_video_bitrate': session['stream_video_bitrate'], + 'stream_video_codec': session['stream_video_codec'], + 'stream_video_codec_level': session['stream_video_codec_level'], + 'stream_video_bit_depth': session['stream_video_bit_depth'], + 'stream_video_height': session['stream_video_height'], + 'stream_video_width': session['stream_video_width'], + 'stream_video_resolution': session['stream_video_resolution'], + 'stream_video_framerate': session['stream_video_framerate'], + 'stream_audio_decision': session['stream_audio_decision'], + 'stream_audio_codec': session['stream_audio_codec'], + 'stream_audio_bitrate': session['stream_audio_bitrate'], + 'stream_audio_channels': session['stream_audio_channels'], + 'stream_subtitle_decision': session['stream_subtitle_decision'], + 'stream_subtitle_codec': session['stream_subtitle_codec'], + 'stream_subtitle_container': session['stream_subtitle_container'], + 'stream_subtitle_forced': session['stream_subtitle_forced'], + 'subtitles': session['subtitles'], + 'synced_version': session['synced_version'], + 'optimized_version': session['optimized_version'], + 'optimized_version_profile': session['optimized_version_profile'] + } # logger.debug(u"PlexPy ActivityProcessor :: Writing session_history_media_info transaction...") - self.db.action(query=query, args=args) + self.db.upsert(table_name='session_history_media_info', key_dict=keys, value_dict=values) # Write the session_history_metadata table directors = ";".join(metadata['directors']) @@ -278,25 +368,43 @@ class ActivityProcessor(object): labels = ";".join(metadata['labels']) # logger.debug(u"PlexPy ActivityProcessor :: 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, full_title, media_index, ' \ - 'parent_media_index, section_id, thumb, parent_thumb, grandparent_thumb, art, media_type, ' \ - 'year, originally_available_at, added_at, updated_at, last_viewed_at, content_rating, ' \ - 'summary, tagline, rating, duration, guid, directors, writers, actors, genres, studio, labels) ' \ - 'VALUES (last_insert_rowid(), ' \ - '?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' - - args = [session['rating_key'], session['parent_rating_key'], session['grandparent_rating_key'], - session['title'], session['parent_title'], session['grandparent_title'], session['full_title'], - metadata['media_index'], metadata['parent_media_index'], metadata['section_id'], 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['tagline'], - metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres, - metadata['studio'], labels] + keys = {'id': last_id} + values = {'rating_key': session['rating_key'], + 'parent_rating_key': session['parent_rating_key'], + 'grandparent_rating_key': session['grandparent_rating_key'], + 'title': session['title'], + 'parent_title': session['parent_title'], + 'grandparent_title': session['grandparent_title'], + 'full_title': session['full_title'], + 'media_index': metadata['media_index'], + 'parent_media_index': metadata['parent_media_index'], + 'section_id': metadata['section_id'], + 'thumb': metadata['thumb'], + 'parent_thumb': metadata['parent_thumb'], + 'grandparent_thumb': metadata['grandparent_thumb'], + 'art': metadata['art'], + 'media_type': session['media_type'], + 'year': metadata['year'], + 'originally_available_at': metadata['originally_available_at'], + 'added_at': metadata['added_at'], + 'updated_at': metadata['updated_at'], + 'last_viewed_at': metadata['last_viewed_at'], + 'content_rating': metadata['content_rating'], + 'summary': metadata['summary'], + 'tagline': metadata['tagline'], + 'rating': metadata['rating'], + 'duration': metadata['duration'], + 'guid': metadata['guid'], + 'directors': directors, + 'writers': writers, + 'actors': actors, + 'genres': genres, + 'studio': metadata['studio'], + 'labels': labels + } # logger.debug(u"PlexPy ActivityProcessor :: Writing session_history_metadata transaction...") - self.db.action(query=query, args=args) + self.db.upsert(table_name='session_history_metadata', key_dict=keys, value_dict=values) # Return true when the session is successfully written to the database return True diff --git a/plexpy/common.py b/plexpy/common.py index 4732377e..09bb702e 100644 --- a/plexpy/common.py +++ b/plexpy/common.py @@ -128,6 +128,7 @@ VIDEO_QUALITY_PROFILES = {20000: '20 Mbps 1080p', 96: '0.096 Mbps', 64: '0.064 Mbps' } +VIDEO_QUALITY_PROFILES = OrderedDict(sorted(VIDEO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True)) AUDIO_QUALITY_PROFILES = {512: '512 kbps', 320: '320 kbps', @@ -136,6 +137,7 @@ AUDIO_QUALITY_PROFILES = {512: '512 kbps', 128: '128 kbps', 96: '96 kbps' } +AUDIO_QUALITY_PROFILES = OrderedDict(sorted(AUDIO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True)) SCHEDULER_LIST = ['Check GitHub for updates', 'Check for active sessions', diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index 4b86d86e..7c951db0 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -1441,7 +1441,6 @@ class PmsConnect(object): subtitle_stream_info = stream video_id = audio_id = subtitle_id = None - video_details = audio_details = subtitle_details = {} if video_stream_info: video_id = helpers.get_xml_attr(video_stream_info, 'id') video_details = {'stream_video_bitrate': helpers.get_xml_attr(video_stream_info, 'bitrate'), @@ -1452,6 +1451,15 @@ class PmsConnect(object): 'stream_video_language_code': helpers.get_xml_attr(video_stream_info, 'languageCode'), 'stream_video_decision': helpers.get_xml_attr(video_stream_info, 'decision') or 'direct play' } + else: + video_details = {'stream_video_bitrate': '', + 'stream_video_bit_depth': '', + 'stream_video_codec_level': '', + 'stream_video_ref_frames': '', + 'stream_video_language': '', + 'stream_video_language_code': '', + 'stream_video_decision': '' + } if audio_stream_info: audio_id = helpers.get_xml_attr(audio_stream_info, 'id') @@ -1463,6 +1471,15 @@ class PmsConnect(object): 'stream_audio_language_code': helpers.get_xml_attr(audio_stream_info, 'languageCode'), 'stream_audio_decision': helpers.get_xml_attr(audio_stream_info, 'decision') or 'direct play' } + else: + audio_details = {'stream_audio_bitrate': '', + 'stream_audio_bitrate_mode': '', + 'stream_audio_sample_rate': '', + 'stream_audio_channel_layout_': '', + 'stream_audio_language': '', + 'stream_audio_language_code': '', + 'stream_audio_decision': '' + } if subtitle_stream_info: subtitle_id = helpers.get_xml_attr(subtitle_stream_info, 'id') @@ -1475,6 +1492,16 @@ class PmsConnect(object): 'stream_subtitle_language_code': helpers.get_xml_attr(subtitle_stream_info, 'languageCode'), 'stream_subtitle_decision': helpers.get_xml_attr(subtitle_stream_info, 'decision') } + else: + subtitle_details = {'stream_subtitle_codec': '', + 'stream_subtitle_container': '', + 'stream_subtitle_format': '', + 'stream_subtitle_forced': 0, + 'stream_subtitle_location': '', + 'stream_subtitle_language': '', + 'stream_subtitle_language_code': '', + 'stream_subtitle_decision': '' + } # Get the bif thumbnail indexes = helpers.get_xml_attr(stream_media_parts_info, 'indexes') @@ -1586,15 +1613,51 @@ class PmsConnect(object): source_media_part_details = next((p for p in source_media_parts if p['id'] == part_id), next((p for p in source_media_parts), {})) source_media_part_streams = source_media_part_details.pop('streams', []) + source_video_details = {'id': '', + 'type': '', + 'video_codec': '', + 'video_codec_level': '', + 'video_bitrate': '', + 'video_bit_depth': '', + 'video_frame_rate': '', + 'video_ref_frames': '', + 'video_height': '', + 'video_width': '', + 'video_language': '', + 'video_language_code': '', + 'video_profile': '' + } + source_audio_details = {'id': '', + 'type': '', + 'audio_codec': '', + 'audio_bitrate': '', + 'audio_bitrate_mode': '', + 'audio_channels': '', + 'audio_channel_layout': '', + 'audio_sample_rate': '', + 'audio_language': '', + 'audio_language_code': '', + 'audio_profile': '' + } + source_subtitle_details = {'id': '', + 'type': '', + 'subtitle_codec': '', + 'subtitle_container': '', + 'subtitle_format': '', + 'subtitle_forced': 0, + 'subtitle_location': '', + 'subtitle_language': '', + 'subtitle_language_code': '' + } if video_id: source_video_details = next((p for p in source_media_part_streams if p['id'] == video_id), - next((p for p in source_media_part_streams if p['type'] == '1'), {})) + next((p for p in source_media_part_streams if p['type'] == '1'), source_video_details)) if audio_id: source_audio_details = next((p for p in source_media_part_streams if p['id'] == audio_id), - next((p for p in source_media_part_streams if p['type'] == '2'), {})) + next((p for p in source_media_part_streams if p['type'] == '2'), source_audio_details)) if subtitle_id: source_subtitle_details = next((p for p in source_media_part_streams if p['id'] == subtitle_id), - next((p for p in source_media_part_streams if p['type'] == '3'), {})) + next((p for p in source_media_part_streams if p['type'] == '3'), source_subtitle_details)) # Get the quality profile if media_type in ('movie', 'episode', 'clip') and 'stream_bitrate' in stream_details: