too much to document, look at the source, updates include, caching, logging, laoding screen, performance enhancements, etc

This commit is contained in:
Erik Kristensen 2010-08-23 14:21:56 -04:00
parent 59df11a25a
commit 74d206d5e0
17 changed files with 839 additions and 184 deletions

View File

@ -1,9 +1,9 @@
<app>
<id>mythboxy</id>
<name>MythBoxy</name>
<version>3.0.beta</version>
<version>4.0.beta</version>
<description>Watch all your MythTV recordings from Boxee.</description>
<thumb>http://erikkristensen.com/project/mythboxee/mythboxee_logo.jpg</thumb>
<thumb>http://erikkristensen.com/boxee/logo4.jpg</thumb>
<media>video</media>
<copyright>Erik Kristensen</copyright>
<email>erik@erikkristensen.com</email>

View File

@ -1,17 +1,13 @@
import mc
import sys
import signal
import mythtv
import mythboxee
from mythboxee import MythBoxee
import time
# DEBUG #
#mc.GetApp().GetLocalConfig().SetValue("dbconn", "")
# DEBUG #
# We'll use this to determine when to reload data.
mc.GetApp().GetLocalConfig().SetValue("LastRunTime", str(time.time()))
mc.GetApp().GetLocalConfig().SetValue("CurrentShowItemID", "0")
# Activate Loading Window
mc.ActivateWindow(14001)
# Lets go ahead and launch the app
MythBoxee()

View File

@ -1,5 +1,8 @@
import mc
import re
import random
import time
import pickle
import mythtv
from mythtv import MythError
from operator import itemgetter, attrgetter
@ -8,13 +11,10 @@ from operator import itemgetter, attrgetter
class MythBoxee:
logLevel = 1
version = "4.0.beta"
userAgent = "MythBoxee v4.0.beta"
tvdb_apikey = "6BEAB4CB5157AAE0"
be = None
db = None
recs = None
titles = []
recordings = []
@ -33,7 +33,7 @@ class MythBoxee:
finally prompt user to enter their credentials manually.
"""
def DiscoverBackend():
self.log("def(DiscoverBackend)")
self.log("def(DiscoverBackend): Start =========================================================")
pin = self.config.GetValue("pin")
dbconn = self.config.GetValue("dbconn")
@ -45,85 +45,138 @@ class MythBoxee:
self.db = mythtv.MythDB(SecurityPin=pin)
except Exception, e:
if e.ename == 'DB_CREDENTIALS' and count < 2:
mc.ActivateWindow(14002)
mc.GetWindow(14002).GetControl(6020).SetVisible(False)
mc.GetWindow(14002).GetControl(6010).SetVisible(True)
mc.GetWindow(14002).GetControl(6011).SetFocus()
## Jump to Settings Window
self.log("def(DiscoverBackend): Error: Database Credentials")
elif e.ename == 'DB_CONNECTION' or e.ename == 'DB_CREDENTIALS' and count > 3:
mc.ActivateWindow(14002)
mc.GetWindow(14002).GetControl(6010).SetVisible(False)
mc.GetWindow(14002).GetControl(6020).SetVisible(True)
mc.GetWindow(14002).GetControl(6021).SetFocus()
## Jump to Settings Window
self.log("def(DiscoverBackend): Error: Database Connection")
self.log("def(DiscoverBackend): End ===========================================================")
return False
else:
# We have a successful connection, save database information
self.config.SetValue("dbconn", str(self.db.dbconn))
self.log("def(DiscoverBackend): End ===========================================================")
return True
"""
Lets make a connection to the backend!
__init__ - Lets make a connection to the backend!
"""
def __init__(self):
self.config = mc.GetApp().GetLocalConfig()
self.log("def(__init__): Start =========================================================")
self.log("def(__init__): Version: " + self.version)
self.log("def(__init__)")
self.config = mc.GetApp().GetLocalConfig()
# If this is the first time the app is being run, lets set some default options.
if not self.config.GetValue("firstrun"):
self.config.SetValue("SortBy", "Original Air Date")
self.config.SetValue("SortDir", "Descending")
self.config.SetValue("Filter", "All")
self.config.SetValue("firstrun", "1")
# If dbconn isn't set, we'll assume we haven't found the backend.
if not self.config.GetValue("dbconn"):
discoverBackend = False
while discoverBackend is False:
print "discover"
discoverBackend = self.DiscoverBackend()
# Parse our DB info
dbconn = self.config.GetValue("dbconn")
dbconf = eval(dbconn)
# Parse our DB info into useable format
dbconf = eval(self.config.GetValue("dbconn"))
self.dbconf = dbconf
# Now that the backend has been discovered, lets connect.
try:
self.db = mythtv.MythDB(**dbconf)
except MythError, e:
print e.message
mc.ShowDialogNotification("Failed to connect to the MythTV Backend")
self.log(e.message)
else:
self.be = mythtv.MythBE(db=self.db)
self.GetRecordings()
self.log("def(__init__): End ===========================================================")
"""
GetRecordings - Pulls all of the recordings out of the backend.
LoadMain - Loader for Main Window
"""
def LoadMain(self):
self.log("def(LoadMain): Start =========================================================")
mc.ShowDialogWait()
## Put focus on last selected item
itemId = int(self.config.GetValue("CurrentShowItemID"))
if itemId and itemId != 0:
mc.GetWindow(14001).GetList(1030).SetFocusedItem(itemId)
mainList = mc.GetWindow(14001).GetList(1030)
mainListitems = mainList.GetItems()
mainLength = len(mainListitems)
lastruntime = self.config.GetValue("LastRunTime")
if mainLength == 0 or lastruntime <= str(time.time() - 3060):
# Lets get the recordings
self.SetShows()
mc.HideDialogWait()
self.log("def(LoadMain): End ===========================================================")
"""
GetRecordings - Pulls all of the recordings out of the backend and prepares them for use in the app.
This function also creates some dictionarys and lists of information
that is used throughout the app for different functions.
"""
def GetRecordings(self):
self.log("def(GetRecordings): Start =========================================================")
# Empty out crucial info
self.titles = []
self.banners = {}
self.series = {}
self.shows = {}
self.log("def(GetRecordings)")
cacheTime = self.config.GetValue("cache.time")
self.recs = self.be.getRecordings()
x=0
for recording in self.recs:
if recording.title not in self.titles:
self.titles.append(str(recording.title))
self.banners[str(recording.title)] = self.GetRecordingArtwork(str(recording.title))
self.series[str(recording.title)] = self.GetRecordingSeriesID(str(recording.title))
self.shows[str(recording.title)] = []
single = [str(recording.title), str(recording.subtitle), str(recording.description), str(recording.chanid), str(recording.airdate), str(recording.starttime), str(recording.endtime), x]
self.shows[str(recording.title)].append(single)
x = x + 1
if not cacheTime or cacheTime <= str(time.time() - 3600):
x=0
for recording in self.recs:
if recording.title not in self.titles:
self.titles.append(str(recording.title))
self.banners[str(recording.title)] = self.GetRecordingArtwork(str(recording.title))
self.series[str(recording.title)] = self.GetRecordingSeriesID(str(recording.title))
self.shows[str(recording.title)] = []
single = [str(recording.title), str(recording.subtitle), str(recording.description), str(recording.chanid), str(recording.airdate), str(recording.starttime), str(recording.endtime), recording.getRecorded().watched, x]
self.shows[str(recording.title)].append(single)
x = x + 1
# Lets cache our findings for now.
self.config.SetValue("cache.time", str(time.time()))
self.config.SetValue("cache.titles", pickle.dumps(self.titles))
self.config.SetValue("cache.banners", pickle.dumps(self.banners))
self.config.SetValue("cache.series", pickle.dumps(self.series))
self.config.SetValue("cache.shows", pickle.dumps(self.shows))
else:
self.titles = pickle.loads(self.config.GetValue("cache.titles"))
self.banners = pickle.loads(self.config.GetValue("cache.banners"))
self.series = pickle.loads(self.config.GetValue("cache.series"))
self.shows = pickle.loads(self.config.GetValue("cache.shows"))
self.titles.sort()
self.log("def(GetRecordings): End ===========================================================")
"""
SetShows - Populate the Shows List on the Main Window
"""
def SetShows(self):
self.log("def(SetShows): Start =========================================================")
items = mc.ListItems()
for title in self.titles:
item = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
@ -132,56 +185,76 @@ class MythBoxee:
item.SetProperty("videos", str(len(self.shows[title])))
item.SetProperty("seriesid", str(self.series[title]))
items.append(item)
mc.GetWindow(14001).GetList(1030).SetItems(items)
self.log("def(SetShows): End ===========================================================")
"""
GetRecordingArtwork - Get the Artwork for a show.
"""
def GetRecordingArtwork(self, title):
self.log("def(GetRecordingArtwork): Start =========================================================")
sg = mc.Http()
sg.SetUserAgent('MythBoxee v4.0.beta')
sg.SetUserAgent(self.userAgent)
html = sg.Get("http://www.thetvdb.com/api/GetSeries.php?seriesname=" + str(title.replace(" ", "%20")))
banners = re.compile("<banner>(.*?)</banner>").findall(html)
## Sometimes we can't find the show, so we have to provide our own artwork
try:
artwork = "http://www.thetvdb.com/banners/" + banners[0]
except:
artwork = "mb_artwork_error.png"
self.log("def(GetRecordingArtwork): " + str(artwork))
self.log("def(GetRecordingArtwork): URL: " + str(artwork))
self.log("def(GetRecordingArtwork): End =========================================================")
return artwork
"""
GetRecordingSeriesID - Get the Series ID of a show.
TODO: rewrite this entire function
"""
def GetRecordingSeriesID(self, title):
self.log("def(GetRecordingSeriesID): Start =========================================================")
sg = mc.Http()
sg.SetUserAgent(self.userAgent)
html = sg.Get("http://www.thetvdb.com/api/GetSeries.php?seriesname=" + title.replace(" ", "%20"))
series = re.compile("<seriesid>(.*?)</seriesid>").findall(html)
## Sometimes we can't determine the series ID
try:
seriesid = series[0]
except:
seriesid = 00000
self.log("def(GetRecordingSeriesID): title[" + title + "] - seriesid[" + str(seriesid) + "]")
self.log("def(GetRecordingSeriesID): Title: " + title)
self.log("def(GetRecordingSeriesID): SeriesID: " + str(seriesid))
self.log("def(GetRecordingSeriesID): End ===========================================================")
return seriesid
"""
DisplayShow
TODO: rewrite this entire function
"""
def DisplayShow(self):
self.log("def(DisplaySingleShow): Start =========================================================")
recordingList = mc.GetWindow(14001).GetList(1030)
item = recordingList.GetItem(recordingList.GetFocusedItem())
itemId = recordingList.GetFocusedItem()
item = recordingList.GetItem(itemId)
title = item.GetLabel()
# Save the Latest Show Title to what was clicked
# this way the show window has a way to load the data.
self.config.SetValue("LatestShowTitle", title)
self.config.SetValue("LatestShowID", item.GetProperty("seriesid"))
self.config.SetValue("CurrentShowItemID", str(itemId))
self.config.SetValue("CurrentShowTitle", title)
self.config.SetValue("CurrentShowID", item.GetProperty("seriesid"))
self.log("def(DisplaySingleShow): Title[" + title + "]")
# Show the Single Show Window
mc.ActivateWindow(14002)
@ -190,21 +263,33 @@ class MythBoxee:
mc.GetWindow(14002).GetList(2070).SetItems(itemList)
self.log("def(DisplaySingleShow): Title[" + title + "]")
self.log("def(DisplaySingleShow): Current Show Title: " + title)
self.log("def(DisplaySingleShow): Current Show Item ID: " + str(itemId))
self.log("def(DisplaySingleShow): Current Show Series ID: " + item.GetProperty("seriesid"))
self.log("def(DisplaySingleShow): End ===========================================================")
"""
LoadShow
Launch function to gather and setup the recordings for a single show.
LoadShow - init function for Show Window
"""
def LoadShow(self):
title = self.config.GetValue("LatestShowTitle")
seriesid = self.config.GetValue("LatestShowID")
self.log("def(LoadShow): Start =========================================================")
mc.ShowDialogWait()
## Get Current Show Information
title = self.config.GetValue("CurrentShowTitle")
seriesid = self.config.GetValue("CurrentShowID")
self.log("def(LoadSingleShow): Title[" + title + "]")
## Setup the Show Window and Populate the Window's Lists
self.SetSortableOptions()
self.SetSeriesDetails(title, seriesid)
self.LoadShowRecordings(title)
mc.HideDialogWait()
self.log("def(LoadShow): End ===========================================================")
"""
@ -214,11 +299,21 @@ class MythBoxee:
Then populate the recording list for the singular show for viewer to watch.
"""
def LoadShowRecordings(self, title):
self.log("def(LoadShowRecordings): Start =========================================================")
## Get current sort and filter settings
sortBy = self.config.GetValue("SortBy")
sortDir = self.config.GetValue("SortDir")
theFilter = self.config.GetValue("Filter")
self.log("def(LoadShowRecordings): Sort By: " + sortBy)
self.log("def(LoadShowRecordings): Sort Dir: " + sortDir)
self.log("def(LoadShowRecordings): Filter: " + theFilter)
## Clear the episodes container
episodes = None
## Sort based on Sorting Criteria
if sortBy == "Original Air Date" and sortDir == "Ascending":
episodes = sorted(self.shows[title], key=itemgetter(4))
elif sortBy == "Original Air Date" and sortDir == "Descending":
@ -234,69 +329,115 @@ class MythBoxee:
else:
episodes = self.shows[title]
## Loop through all our recordings, and add them to the list.
showitems = mc.ListItems()
for title,subtitle,desc,chanid,airdate,starttime,endtime,ref in episodes:
print title
recording = self.recs[ref]
#showitem = mc.ListItem( mc.ListItem.MEDIA_VIDEO_EPISODE )
#showitem = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
showitem = mc.ListItem()
showitem.SetLabel(str(recording.subtitle))
showitem.SetTitle(str(recording.subtitle))
showitem.SetTVShowTitle(str(recording.title))
showitem.SetDescription(str(desc))
showitem.SetProperty("starttime", str(starttime))
showitem.SetProperty("ref", str(ref))
for title,subtitle,desc,chanid,airdate,starttime,endtime,watched,ref in episodes:
#recording = self.recs[ref]
# Filter the Episodes
if theFilter == "Watched" and watched == 0:
continue
elif theFilter == "Unwatched" and watched == 1:
continue
# Create the Item list and populate it
showitem = mc.ListItem( mc.ListItem.MEDIA_VIDEO_EPISODE )
showitem.SetLabel(subtitle)
showitem.SetTitle(subtitle)
showitem.SetTVShowTitle(title)
showitem.SetDescription(desc)
showitem.SetProperty("starttime", starttime)
#showitem.SetProperty("ref", ref)
## Sometimes dates aren't set, so generate one if not.
try:
date = str(airdate).split("-")
date = airdate.split("-")
showitem.SetDate(int(date[0]), int(date[1]), int(date[2]))
except:
showitem.SetDate(2010, 01, 01)
dbconf = eval(self.config.GetValue("dbconn"))
## Set the Thumbnail for the ListItem
#showitem.SetThumbnail("http://192.168.1.210:6544/Myth/GetPreviewImage?ChanId=1050&StartTime=2010-08-05%2021:00:00")
#showitem.SetThumbnail("http://192.168.1.210:6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace("T", "%20"))
showitem.SetThumbnail("http://" + dbconf['DBHostName'] + ":6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace(" ", "%20"))
#showitem.SetThumbnail("http://" + dbconf['DBHostName'] + ":6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace(" ", "%20") + "&random=" + str(random.randrange(1000000, 2000000, 2)))
#showitem.SetThumbnail("mb_artwork_error.png")
#showitem.SetThumbnail("http://192.168.1.210:6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace(" ", "%20") + "&random=" + str(random.randrange(1000000, 2000000, 2)))
#showitem.SetThumbnail("http://192.168.1.210:6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace("T", "%20"))
# Determine Stream Method, Generate Proper Path
streamMethod = self.config.GetValue("StreamMethod")
if streamMethod == "XML":
time = starttime.replace("T", "%20")
path = "http://" + self.dbconf['DBHostName'] + ":6544/Myth/GetRecording?ChanId=" + chanid + "&StartTime=" + time
showitem.SetThumbnail("http://" + self.dbconf['DBHostName'] + ":6544/Myth/GetPreviewImage?ChanId=" + chanid + "&StartTime=" + starttime.replace("T", "%20"))
elif streamMethod == "SMB":
time = starttime.replace("T", "").replace("-", "").replace(":", "").replace(" ","")
path = "smb://" + self.config.GetValue("smb.username") + ":" + self.config.GetValue("smb.password") + "@" + self.dbconf["DBHostName"] + "/" + self.config.GetValue("smb.share") + "/" + chanid + "_" + time + ".mpg"
#showitem.SetPath("http://" + dbconf['DBHostName'] + ":6544/Myth/GetRecording?ChanId=" + chanid + "&StartTime=" + starttime.replace("T", "%20"))
showitem.SetPath("smb://guest:guest@192.168.1.210/recordings/1050_20100709010000.mpg")
## Set the Path for the ListItem
showitem.SetPath(path)
self.log("def(LoadShowRecordings): Thumbnail: " + showitem.GetThumbnail())
self.log("def(LoadShowRecordings): Path: " + showitem.GetPath())
showitems.append(showitem)
mc.GetWindow(14002).GetList(2040).SetItems(mc.ListItems())
mc.GetWindow(14002).GetList(2040).SetItems(showitems)
self.log("def(LoadShowRecordings): End ===========================================================")
"""
SetShowOptions
Setup the show options; sort by, sort direction, watched vs unwatched
SetSortableOptions - Setup the show options; sort by, sort direction, watched vs unwatched
"""
def SetSortableOptions(self):
self.log("def(SetSortableOptions): Start =========================================================")
## Setup Sortable Field Options
sortable = ['Original Air Date', 'Recorded Date', 'Title']
items = mc.ListItems()
for sorttype in sortable:
item = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
item.SetLabel(sorttype)
items.append(item)
mc.GetWindow(14002).GetList(2051).SetItems(mc.ListItems())
mc.GetWindow(14002).GetList(2051).SetItems(items)
mc.GetWindow(14002).GetList(2051).SetSelected(1, True)
## Setup Sortable Direction Options
sortableby = ['Ascending', 'Descending']
items = mc.ListItems()
for sorttype in sortableby:
item = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
item.SetLabel(sorttype)
items.append(item)
mc.GetWindow(14002).GetList(2061).SetItems(mc.ListItems())
mc.GetWindow(14002).GetList(2061).SetItems(items)
mc.GetWindow(14002).GetList(2061).SetSelected(1, True)
## Setup Filter Options
filters = ['All', 'Watched', 'Unwatched']
items = mc.ListItems()
for single_filter in filters:
item = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
item.SetLabel(single_filter)
items.append(item)
mc.GetWindow(14002).GetList(2082).SetItems(mc.ListItems())
mc.GetWindow(14002).GetList(2082).SetItems(items)
## Set the currently selected option in each category
mc.GetWindow(14002).GetList(2051).SetSelected(sortable.index(self.config.GetValue("SortBy")), True)
mc.GetWindow(14002).GetList(2061).SetSelected(sortableby.index(self.config.GetValue("SortDir")), True)
mc.GetWindow(14002).GetList(2082).SetSelected(filters.index(self.config.GetValue("Filter")), True)
self.log("def(SetSortableOptions): End ===========================================================")
"""
SetSeriesDetails - Get Show Series Information
TODO -- rewrite this entire function
"""
def SetSeriesDetails(self, title, seriesid):
self.log("def(SetSeriesDetails): Start =========================================================")
sg = mc.Http()
sg.SetUserAgent(self.userAgent)
html = sg.Get("http://thetvdb.com/api/" + self.tvdb_apikey + "/series/" + seriesid + "/")
@ -321,27 +462,163 @@ class MythBoxee:
items.append(item)
mc.GetWindow(14002).GetList(2070).SetItems(items)
self.log("def(SetSeriesDetails): End ===========================================================")
def PlayRecording(self):
self.log("def(PlayRecording): ")
"""
FilterEpisodes - Filter the list of Episodes (All, Watched, Unwatched)
"""
def FilterEpisodes(self):
self.log("def(FilterEpisodes): Start =========================================================")
## Figure out how we need to filter
FilterItems = FilterItemNumber = mc.GetWindow(14002).GetList(2082).GetSelected()
mc.GetWindow(14002).GetList(2082).UnselectAll()
mc.GetWindow(14002).GetList(2082).SetSelected(mc.GetWindow(14002).GetList(2082).GetFocusedItem(), True)
## Update the Filter Criteria
self.config.SetValue("Filter", mc.GetWindow(14002).GetList(2082).GetItem(mc.GetWindow(14002).GetList(2082).GetFocusedItem()).GetLabel())
## Now that the filter has changed, reload the list of episodes
self.LoadShowRecordings(self.config.GetValue("CurrentShowTitle"))
self.log("def(FilterEpisodes): End ===========================================================")
"""
SortBy - Sort List of Episodes
"""
def SortBy(self):
self.log("def(SortBy): Start =========================================================")
## Figure out how we need to Sort
sortByItems = sortByItemNumber = mc.GetWindow(14002).GetList(2051).GetSelected()
sortDirectionItems = sortDirectionItemNumber = mc.GetWindow(14002).GetList(2061).GetSelected()
mc.GetWindow(14002).GetList(2051).UnselectAll()
mc.GetWindow(14002).GetList(2051).SetSelected(mc.GetWindow(14002).GetList(2051).GetFocusedItem(), True)
## Update the Sort Criteria
self.config.SetValue("SortBy", mc.GetWindow(14002).GetList(2051).GetItem(mc.GetWindow(14002).GetList(2051).GetFocusedItem()).GetLabel())
## Now that we have updated the Sort Criteria, reload the shows
self.LoadShowRecordings(self.config.GetValue("CurrentShowTitle"))
self.log("def(SortBy): End ===========================================================")
"""
LoadSettings - Stuff that needs to be executed when settings window is loaded
"""
def LoadSettings(self):
self.log("def(LoadSettings): Start =========================================================")
## Grab the current StreamMethod
streamMethod = self.config.GetValue("StreamMethod")
self.log("def(LoadSettings): Stream Method: " + streamMethod)
# Grab and Set the Database Information
dbconf = eval(self.config.GetValue("dbconn"))
mc.GetWindow(14004).GetEdit(1042).SetText(dbconf['DBHostName'])
mc.GetWindow(14004).GetEdit(1043).SetText(dbconf['DBUserName'])
mc.GetWindow(14004).GetEdit(1044).SetText(dbconf['DBPassword'])
# Setup Stream Methods for user to choose
methods = ['XML', 'SMB']
items = mc.ListItems()
for method in methods:
item = mc.ListItem( mc.ListItem.MEDIA_UNKNOWN )
item.SetLabel(method)
items.append(item)
mc.GetWindow(14004).GetList(1022).SetItems(items)
mc.GetWindow(14004).GetList(1022).SetSelected(methods.index(streamMethod), True)
# Depending on StreamMethod Enable Options
if not streamMethod or streamMethod == "XML":
mc.GetWindow(14004).GetControl(1032).SetEnabled(False)
mc.GetWindow(14004).GetControl(1033).SetEnabled(False)
mc.GetWindow(14004).GetControl(1034).SetEnabled(False)
else:
if not self.config.GetValue("smb.username"):
self.config.SetValue("smb.username", "guest")
if not self.config.GetValue("smb.password"):
self.config.SetValue("smb.password", "guest")
self.log("def(LoadSettings): smb.share: " + self.config.GetValue("smb.share"))
self.log("def(LoadSettings): smb.username: " + self.config.GetValue("smb.username"))
self.log("def(LoadSettings): smb.password: " + self.config.GetValue("smb.password"))
## Since the Stream Method is SMB enable controls for setting info
mc.GetWindow(14004).GetControl(1032).SetEnabled(True)
mc.GetWindow(14004).GetControl(1033).SetEnabled(True)
mc.GetWindow(14004).GetControl(1034).SetEnabled(True)
mc.GetWindow(14004).GetControl(1032).SetFocus()
## Update the fields with current SMB settings.
mc.GetWindow(14004).GetEdit(1032).SetText(self.config.GetValue("smb.share"))
mc.GetWindow(14004).GetEdit(1033).SetText(self.config.GetValue("smb.username"))
mc.GetWindow(14004).GetEdit(1034).SetText(self.config.GetValue("smb.password"))
sl = mc.GetWindow(14002).GetList(2040)
item = sl.GetItem(sl.GetFocusedItem())
self.log("def(LoadSettings): End ===========================================================")
ref = item.GetProperty("ref")
"""
SetStreamMethod - Change the Streaming Method
"""
def SetStreamMethod(self):
self.log("def(SetStreamMethod): Start =========================================================")
## Figure out what Stream Method the user has selected
streamMethodItems = streamMethodItemNumber = mc.GetWindow(14004).GetList(1022).GetSelected()
mc.GetWindow(14004).GetList(1022).UnselectAll()
mc.GetWindow(14004).GetList(1022).SetSelected(mc.GetWindow(14004).GetList(1022).GetFocusedItem(), True)
streamMethod = mc.GetWindow(14004).GetList(1022).GetItem(mc.GetWindow(14004).GetList(1022).GetFocusedItem()).GetLabel()
## Disabled some UI pieces depending on stream method
if not streamMethod or streamMethod == "XML":
mc.GetWindow(14004).GetControl(1032).SetEnabled(False)
mc.GetWindow(14004).GetControl(1033).SetEnabled(False)
mc.GetWindow(14004).GetControl(1034).SetEnabled(False)
else:
mc.GetWindow(14004).GetControl(1032).SetEnabled(True)
mc.GetWindow(14004).GetControl(1033).SetEnabled(True)
mc.GetWindow(14004).GetControl(1034).SetEnabled(True)
## Save the Stream Method
self.config.SetValue("StreamMethod", streamMethod)
file = self.recs[int(ref)].open('r', self.db)
## Notify the User
mc.ShowDialogNotification("Stream Method Changed to " + streamMethod)
mc.ShowDialogNotification(item.GetProperty("ref"))
mc.ShowDialogNotification("Playing: " + item.GetLabel())
self.log("def(SetStreamMethod): Stream Method Changed to -- " + streamMethod)
self.log("def(SetStreamMethod): End =========================================================")
"""
SaveSMBSettings - Saves the SMB settings the user inputted.
"""
def SaveSMBSettings(self):
self.log("def(SetStreamMethod): Start =========================================================")
## Save SMB settings the user inputted
self.config.SetValue("smb.share", mc.GetWindow(14004).GetEdit(1032).GetText())
self.config.SetValue("smb.username", mc.GetWindow(14004).GetEdit(1033).GetText())
self.config.SetValue("smb.password", mc.GetWindow(14004).GetEdit(1034).GetText())
## Notify the user that the changes have been saved.
mc.ShowDialogNotification("SMB Share Settings Saved")
self.log("def(SetStreamMethod): End ===========================================================")
"""
log - logging function mainly for debugging
"""
def log(self, message):
if self.logLevel >= 3:
mc.LogDebug(">>> MythBoxee: " + message)
if self.logLevel >= 2:
mc.ShowDialogNotification(message)
if self.logLevel >= 1:
mc.LogInfo(">>> MythBoxee (" + self.version + ")\: " + message)
print ">>> MythBoxee (" + self.version + ")\: " + message
if self.logLevel >= 1:
mc.LogInfo(">>> MythBoxee: " + message)
print ">>> MythBoxee: " + message

View File

@ -8,6 +8,6 @@ OWN_VERSION = (0,23,1,0)
SCHEMA_VERSION = 1254
MVSCHEMA_VERSION = 1032
NVSCHEMA_VERSION = 1004
PROTO_VERSION = 23056
PROTO_VERSION = 56
PROGRAM_FIELDS = 47
BACKEND_SEP = '[]:[]'

View File

@ -4,43 +4,67 @@
<allowoverlay>yes</allowoverlay>
<onload lang="python"><![CDATA[
from mythboxee import MythBoxee
mb = MythBoxee()
mb.GetRecordings()
mb.LoadMain()
]]></onload>
<controls>
<control type="group" id="1010">
<control type="image" id="1011">
<width>1280</width>
<height>720</height>
<texture>mb_bg_setup.png</texture>
</control>
<control type="image" id="1012">
<description>logo</description>
<posx>450</posx>
<posy>250</posy>
<width>402</width>
<height>107</height>
<texture flipY="true" flipX="false">logo.png</texture>
<aspectratio>keep</aspectratio>
</control>
</control>
<control type="group" id="1020">
<control type="image" id="1021">
<width>1280</width>
<height>720</height>
<texture>mb_bg.png</texture>
</control>
<control type="image" id="1022">
<posx>10</posx>
<posy>10</posy>
<width>244</width>
<height>65</height>
<texture>logo.png</texture>
</control>
</control>
<control type="grouplist" id="1040">
<posy>28</posy>
<posx>940</posx>
<width>334</width>
<itemgap>10</itemgap>
<orientation>horizontal</orientation>
<ondown>1030</ondown>
<control type="button" id="1041">
<label>Refresh</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>30</height>
<align>center</align>
<onclick lang="python"><![CDATA[mb.RefreshMain()]]></onclick>
</control>
<control type="button" id="1042">
<label>Settings</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>30</height>
<align>center</align>
<onclick lang="python"><![CDATA[mc.ActivateWindow(14004)]]></onclick>
</control>
<!--
780/500
<control type="button" id="1043">
<label>Send Logs</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>29</height>
<align>center</align>
<onclick lang="python"><![CDATA[mb.SendLogs()]]></onclick>
</control>
-->
</control>
<control type="panel" id="1030">
<posx>22</posx>
<posy>82</posy>
<width>1280</width>
<height>592</height>
<height>692</height>
<onleft>-</onleft>
<onright>-</onright>
<onup>-</onup>
<onup>1040</onup>
<ondown>-</ondown>
<itemlayout width="420" height="120">
<control type="image">
@ -154,5 +178,25 @@ mb.GetRecordings()
<onclick lang="python"><![CDATA[mb.DisplayShow()]]></onclick>
</content>
</control>
<control type="group">
<visible>App.HasSetting(loading)</visible>
<animation effect="fade" start="0" end="100" time="150">VisibleChange</animation>
<control type="image">
<width>1280</width>
<height>720</height>
<texture>black.png</texture>
<animation effect="fade" start="80" end="80" time="0" condition="true">Conditional</animation>
</control>
<control type="label">
<posx>530</posx>
<width>1280</width>
<height>720</height>
<align>cetner</align>
<aligny>center</aligny>
<font>sans40b</font>
<label>LOADING...</label>
<textcolor>ffffffff</textcolor>
</control>
</control>
</controls>
</window>

View File

@ -0,0 +1,231 @@
<window type="window" id="14004">
<defaultcontrol always="true">1030</defaultcontrol>
<allowoverlay>yes</allowoverlay>
<onload lang="python"><![CDATA[
import mc
import mythboxee
mb.LoadSettings()
]]></onload>
<controls>
<control type="group" id="1010">
<control type="image" id="1011">
<width>1280</width>
<height>720</height>
<texture>mb_bg_settings.png</texture>
</control>
</control>
<!-- START: BACKEND INFORMATION -->
<control type="group" id="1040">
<control type="label" id="1041">
<posx>820</posx>
<posy>150</posy>
<width>250</width>
<label>Backend Information</label>
<font>font23</font>
</control>
<control type="edit" id="1042">
<posx>820</posx>
<posy>175</posy>
<width>300</width>
<label>Hostname/IP:</label>
<align>left</align>
<font>font18</font>
<ondown>1043</ondown>
</control>
<control type="edit" id="1043">
<posx>820</posx>
<posy>205</posy>
<width>300</width>
<label>Username:</label>
<align>left</align>
<font>font18</font>
<onup>1042</onup>
<ondown>1044</ondown>
</control>
<control type="edit" id="1044">
<posx>820</posx>
<posy>235</posy>
<width>300</width>
<align>left</align>
<label>Password:</label>
<password>true</password>
<font>font18</font>
<onup>1043</onup>
<ondown>1022</ondown>
</control>
</control>
<!-- END: BACKEND INFORMATION -->
<!-- START: STREAM METHOD -->
<control type="group" id="1020">
<control type="label" id="1021">
<posx>820</posx>
<posy>300</posy>
<width>250</width>
<align>left</align>
<label>Stream Method</label>
<font>font23</font>
</control>
<control type="list" id="1022">
<posx>830</posx>
<posy>335</posy>
<width>164</width>
<height>100</height>
<onup>1044</onup>
<ondown>1032</ondown>
<itemlayout width="164" height="27">
<control type="label">
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font18</font>
<textcolor>FF999999</textcolor>
<selectedcolor>FFFFFFFF</selectedcolor>
</control>
</itemlayout>
<focusedlayout width="164" height="27">
<control type="label">
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font18</font>
<textcolor>green</textcolor>
<visible>Control.HasFocus(1022)</visible>
<selectedcolor>green</selectedcolor>
</control>
<control type="label">
<visible>!Control.HasFocus(1022)</visible>
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font18</font>
<textcolor>FF999999</textcolor>
<selectedcolor>FFFFFFFF</selectedcolor>
</control>
</focusedlayout>
<content type="action">
<onclick lang="python"><![CDATA[mb.SetStreamMethod()]]></onclick>
</content>
</control>
</control>
<!-- END: STREAM METHOD -->
<!-- START: SMB SETTINGS -->
<control type="group" id="1030">
<control type="label" id="1031">
<posx>820</posx>
<posy>420</posy>
<width>250</width>
<align>left</align>
<label>SMB Share</label>
<font>font23</font>
</control>
<control type="edit" id="1032">
<posx>820</posx>
<posy>445</posy>
<width>300</width>
<label>Share:</label>
<align>left</align>
<font>font18</font>
<onup>1022</onup>
<ondown>1033</ondown>
<ontextchange lang="python"><![CDATA[mb.SaveSMBSettings()]]></ontextchange>
</control>
<control type="edit" id="1033">
<posx>820</posx>
<posy>475</posy>
<width>300</width>
<label>Username:</label>
<align>left</align>
<font>font18</font>
<onup>1032</onup>
<ondown>1034</ondown>
<ontextchange lang="python"><![CDATA[mb.SaveSMBSettings()]]></ontextchange>
</control>
<control type="edit" id="1034">
<posx>820</posx>
<posy>505</posy>
<width>300</width>
<label>Password:</label>
<align>left</align>
<font>font18</font>
<password>true</password>
<onup>1033</onup>
<ontextchange lang="python"><![CDATA[mb.SaveSMBSettings()]]></ontextchange>
</control>
</control>
<!-- END: SMB SETTINGS -->
<!-- START: CACHE SETTINGS -->
<!--
<control type="group" id="1050">
<control type="label" id="1051">
<posx>820</posx>
<posy>560</posy>
<width>250</width>
<align>left</align>
<label>Cache Settings</label>
<font>font23</font>
</control>
<control type="togglebutton" id="1052">
<posx>820</posx>
<posy>565</posy>
<width>300</width>
<label>Share:</label>
<align>left</align>
<font>font18</font>
<onup>1022</onup>
<ondown>1033</ondown>
<ontextchange lang="python"><![CDATA[mb.SaveCacheSettings()]]></ontextchange>
</control>
<control type="edit" id="1053">
<posx>820</posx>
<posy>590</posy>
<width>300</width>
<label>Username:</label>
<align>left</align>
<font>font18</font>
<onup>1032</onup>
<ondown>1034</ondown>
<ontextchange lang="python"><![CDATA[mb.SaveCacheSettings()]]></ontextchange>
</control>
<control type="edit" id="1054">
<posx>820</posx>
<posy>615</posy>
<width>300</width>
<label>Password:</label>
<align>left</align>
<font>font18</font>
<password>true</password>
<onup>1033</onup>
<ontextchange lang="python"><![CDATA[mb.SaveCacheSettings()]]></ontextchange>
</control>
</control>
-->
<!-- END: CACHE SETTINGS -->
</controls>
</window>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<window type="window" id="14002">
<window type="window" id="14003">
<defaultcontrol always="true">6003</defaultcontrol>
<allowoverlay>yes</allowoverlay>
<controls>

View File

@ -4,50 +4,78 @@
<allowoverlay>true</allowoverlay>
<onload lang="python"><![CDATA[
import mythboxee
mb.LoadShow()
]]></onload>
<controls>
<!--
<control type="group" id="2010">
<control type="image" id="2011">
<width>1280</width>
<height>720</height>
<texture>mb_bg_setup.png</texture>
</control>
<control type="image" id="2012">
<description>logo</description>
<posx>450</posx>
<posy>250</posy>
<width>402</width>
<height>107</height>
<texture flipY="true" flipX="false">logo.png</texture>
<aspectratio>keep</aspectratio>
</control>
</control>
-->
<control type="group" id="2020">
<control type="image" id="202060">
<control type="image" id="2021">
<width>1280</width>
<height>720</height>
<texture>mb_bg.png</texture>
</control>
<control type="image" id="2022">
<posx>10</posx>
<posy>10</posy>
<width>244</width>
<height>65</height>
<texture>logo.png</texture>
</control>
</control>
<!-- START: TOP MENU -->
<control type="grouplist" id="1040">
<posy>28</posy>
<posx>940</posx>
<width>334</width>
<itemgap>10</itemgap>
<orientation>horizontal</orientation>
<ondown>2040</ondown>
<control type="button" id="1041">
<label>Refresh</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>30</height>
<align>center</align>
<onclick lang="python"><![CDATA[mb.RefreshMain()]]></onclick>
</control>
<control type="button" id="1042">
<label>Settings</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>30</height>
<align>center</align>
<onclick lang="python"><![CDATA[mc.ActivateWindow(14004)]]></onclick>
</control>
<!--
780/500
<control type="button" id="1043">
<label>Send Logs</label>
<texturefocus>bg_btn.png</texturefocus>
<texturenofocus></texturenofocus>
<height>29</height>
<align>center</align>
<onclick lang="python"><![CDATA[mb.SendLogs()]]></onclick>
</control>
-->
</control>
<!-- END: TOP MENU -->
<control type="group" id="2030">
<description>details box</description>
<posx>28</posx>
<posy>81</posy>
<onleft>-</onleft>
<onright>2040</onright>
<onup>-</onup>
<onup>1040</onup>
<ondown>-</ondown>
<control type="image">
<description>details box's background</description>
<posx>0</posx>
<posy>0</posy>
<width>283</width>
<height>597</height>
<height>630</height>
<texture>mb_show.png</texture>
</control>
<control type="image">
@ -70,7 +98,7 @@ mb.LoadShow()
<aligny>top</aligny>
<scroll>true</scroll>
<label>$INFO[Container(2070).ListItem.Label]</label>
<font>font16b</font>
<font>font18</font>
<textcolor>FFFEFEFE</textcolor>
<wrapmultiline>true</wrapmultiline>
</control>
@ -79,7 +107,7 @@ mb.LoadShow()
<posx>22</posx>
<posy>395</posy>
<width>228</width>
<height>195</height>
<height>215</height>
<align>left</align>
<aligny>top</aligny>
<scroll>true</scroll>
@ -98,46 +126,41 @@ mb.LoadShow()
<posx>345</posx>
<posy>82</posy>
<width>700</width>
<height>592</height>
<height>630</height>
<onleft>-</onleft>
<onright>2051</onright>
<onup>-</onup>
<onup>1040</onup>
<ondown>-</ondown>
<!--
<animation condition="Control.IsVisible(14)" type="Conditional" reversible="false">
<effect end="100" start="0" time="200" type="fade" />
</animation>
-->
<itemlayout width="700" height="85">
<itemlayout width="700" height="105">
<control type="image">
<description>background</description>
<posx>0</posx>
<posy>0</posy>
<width>700</width>
<height>82</height>
<height>102</height>
<texture border="5">mb_item_big.png</texture>
</control>
<control type="image">
<description>thumbnail</description>
<posx>10</posx>
<posy>10</posy>
<width>106</width>
<height>62</height>
<info>Listitem.Thumb</info>
<width>126</width>
<height>82</height>
<info>ListItem.Thumb</info>
<aspectratio>scale</aspectratio>
<bordersize>3</bordersize>
<bordertexture>mb_thumb_bg.png</bordertexture>
</control>
<control type="label">
<description>episode title</description>
<posx>128</posx>
<posx>148</posx>
<posy>6</posy>
<width>440</width>
<height>30</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font16b</font>
<font>font18</font>
<textcolor>FFFEFEFE</textcolor>
<wrapmultiline>true</wrapmultiline>
</control>
@ -150,30 +173,30 @@ mb.LoadShow()
<align>right</align>
<aligny>top</aligny>
<label>Air Date: $INFO[ListItem.Date]</label>
<font>font12</font>
<font>font16</font>
<textcolor>FFCCCCCC</textcolor>
</control>
<control type="label">
<description>description</description>
<posx>128</posx>
<posx>148</posx>
<posy>31</posy>
<width>560</width>
<height>60</height>
<align>left</align>
<aligny>top</aligny>
<label>$INFO[ListItem.property(description)]</label>
<font>font14</font>
<font>font16</font>
<textcolor>FFCCCCCC</textcolor>
<wrapmultiline>true</wrapmultiline>
</control>
</itemlayout>
<focusedlayout width="700" height="85">
<focusedlayout width="700" height="105">
<control type="togglebutton">
<description>background</description>
<posx>0</posx>
<posy>0</posy>
<width>700</width>
<height>82</height>
<height>102</height>
<texturefocus border="5">mb_item_big_hover.png</texturefocus>
<texturenofocus border="5">mb_item_big_hover.png</texturenofocus>
<alttexturefocus border="5">mb_item_big.png</alttexturefocus>
@ -184,19 +207,20 @@ mb.LoadShow()
<description>thumbnail</description>
<posx>10</posx>
<posy>10</posy>
<width>106</width>
<height>62</height>
<width>126</width>
<height>82</height>
<info>Listitem.Thumb</info>
<aspectratio>scale</aspectratio>
<bordertexture>mb_thumb_bg.png</bordertexture>
<bordersize>3</bordersize>
<visible>!Control.HasFocus(2040)</visible>
</control>
<control type="image">
<description>thumbnail hover</description>
<posx>10</posx>
<posy>10</posy>
<width>106</width>
<height>62</height>
<width>126</width>
<height>82</height>
<info>Listitem.Thumb</info>
<aspectratio>scale</aspectratio>
<bordertexture>mb_thumb_hover_bg.png</bordertexture>
@ -205,14 +229,14 @@ mb.LoadShow()
</control>
<control type="label">
<description>episode title</description>
<posx>128</posx>
<posx>148</posx>
<posy>6</posy>
<width>440</width>
<height>30</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font16b</font>
<font>font18</font>
<textcolor>FFFEFEFE</textcolor>
</control>
<control type="label">
@ -224,28 +248,23 @@ mb.LoadShow()
<align>right</align>
<aligny>top</aligny>
<label>Air Date: $INFO[ListItem.Date]</label>
<font>font12</font>
<font>font16</font>
<textcolor>FFCCCCCC</textcolor>
</control>
<control type="label">
<description>description</description>
<posx>128</posx>
<posx>148</posx>
<posy>31</posy>
<width>560</width>
<height>60</height>
<align>left</align>
<aligny>top</aligny>
<label>$INFO[ListItem.property(description)]</label>
<font>font14</font>
<font>font16</font>
<textcolor>FFCCCCCC</textcolor>
<wrapmultiline>true</wrapmultiline>
</control>
</focusedlayout>
<!--
<content type="action">
<onclick lang="python"><![CDATA[mb.PlayRecording()]]></onclick>
</content>
-->
</control>
<!-- end EPISODES LIST -->
@ -326,7 +345,6 @@ mb.LoadShow()
<!-- end SORT LIST -->
<control type="group" id="2060">
<control type="label">
<posx>1079</posx>
<posy>200</posy>
@ -335,7 +353,6 @@ mb.LoadShow()
<aligny>top</aligny>
<textcolor>FF999999</textcolor>
</control>
<control type="list" id="2061">
<posx>1070</posx>
<posy>225</posy>
@ -344,7 +361,7 @@ mb.LoadShow()
<onleft>2040</onleft>
<onright>-</onright>
<onup>2051</onup>
<ondown>-</ondown>
<ondown>2082</ondown>
<itemlayout width="164" height="27">
<control type="label">
<description>title</description>
@ -394,10 +411,79 @@ mb.LoadShow()
<onclick lang="python"><![CDATA[mythboxee.SortDirSeriesEpisodes()]]></onclick>
</content>
</control>
</control>
<control type="group" id="2080">
<control type="label" id="2081">
<posx>1079</posx>
<posy>300</posy>
<label>FILTERS:</label>
<font>font14b</font>
<aligny>top</aligny>
<textcolor>FF999999</textcolor>
</control>
<control type="list" id="2082">
<posx>1070</posx>
<posy>325</posy>
<width>164</width>
<height>100</height>
<onleft>2040</onleft>
<onright>-</onright>
<onup>2061</onup>
<ondown>-</ondown>
<itemlayout width="164" height="27">
<control type="label">
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font16</font>
<textcolor>FF999999</textcolor>
<selectedcolor>FFFFFFFF</selectedcolor>
</control>
</itemlayout>
<focusedlayout width="164" height="27">
<control type="label">
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font16</font>
<textcolor>FFFFFFFF</textcolor>
<visible>Control.HasFocus(2082)</visible>
<selectedcolor>FFFFFFFF</selectedcolor>
</control>
<control type="label">
<visible>!Control.HasFocus(2082)</visible>
<description>title</description>
<posx>9</posx>
<posy>0</posy>
<width>146</width>
<height>25</height>
<align>left</align>
<aligny>top</aligny>
<info>ListItem.Label</info>
<font>font16</font>
<textcolor>FF999999</textcolor>
<selectedcolor>FFFFFFFF</selectedcolor>
</control>
</focusedlayout>
<content type="action">
<onclick lang="python"><![CDATA[mb.FilterEpisodes()]]></onclick>
</content>
</control>
</control>
<!-- begin SHOW DETAILS CONTAINER -->
<control type="list" id="2070">
@ -413,5 +499,26 @@ mb.LoadShow()
<!-- end SHOW DETAILS CONTAINER -->
<control type="group">
<visible>App.HasSetting(loading)</visible>
<animation effect="fade" start="0" end="100" time="150">VisibleChange</animation>
<control type="image">
<width>1280</width>
<height>720</height>
<texture>black.png</texture>
<animation effect="fade" start="80" end="80" time="0" condition="true">Conditional</animation>
</control>
<control type="label">
<posx>530</posx>
<width>1280</width>
<height>720</height>
<align>cetner</align>
<aligny>center</aligny>
<font>sans40b</font>
<label>LOADING...</label>
<textcolor>ffffffff</textcolor>
</control>
</control>
</controls>
</window>

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.