123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938 |
- # -*- coding: UTF-8 -*-
- #################################################################################
- #
- # SubsSupport 1.2.0 for Enigma2
- # Coded by mx3L (c) 2014
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- #################################################################################
-
- from Queue import Queue
- from datetime import datetime
- import json
- from os import path as os_path, listdir
- import os
- from re import compile as re_compile
- import re
- import sys
- from threading import Thread
- import traceback
- from twisted.internet.defer import Deferred
- from twisted.web import client
-
- from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
- from Components.ConfigList import ConfigListScreen
- from Components.GUIComponent import GUIComponent
- from Components.Harddisk import harddiskmanager
- from Components.Label import Label
- from Components.Language import language
- from Components.MenuList import MenuList
- from Components.MultiContent import MultiContentEntryText, \
- MultiContentEntryPixmapAlphaTest
- from Components.Renderer.Renderer import Renderer
- from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
- from Components.Sources.Boolean import Boolean
- from Components.Sources.List import List
- from Components.Sources.StaticText import StaticText
- from Components.config import ConfigSubsection, ConfigSelection, ConfigYesNo, \
- configfile, getConfigListEntry, config, ConfigText, ConfigDirectory, ConfigOnOff, \
- ConfigNothing, ConfigInteger, NoSave, KEY_DELETE, KEY_BACKSPACE, \
- KEY_TIMEOUT, KEY_ASCII
- from Screens.ChoiceBox import ChoiceBox
- from Screens.HelpMenu import HelpableScreen
- from Screens.InfoBarGenerics import InfoBarSeek, InfoBarNotifications
- from Screens.LocationBox import LocationBox
- from Screens.MessageBox import MessageBox
- from Screens.Screen import Screen
- from Tools import Notifications
- from Tools.Directories import SCOPE_SKIN_IMAGE, SCOPE_SKIN, resolveFilename, \
- fileExists
- from Tools.ISO639 import LanguageCodes
- from Tools.LoadPixmap import LoadPixmap
-
- from compat import eTimer, FileList
- from e2_utils import messageCB, E2SettingsProvider, MyLanguageSelection, unrar, \
- ConfigFinalText, Captcha, DelayMessageBox, MyConfigList, getFps, fps_float, \
- getFonts, BaseMenuScreen
- from enigma import RT_HALIGN_RIGHT, RT_VALIGN_TOP, eSize, ePoint, RT_HALIGN_LEFT, \
- RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, eListboxPythonMultiContent, \
- gFont, getDesktop, eServiceCenter, iServiceInformation, eServiceReference, \
- iSeekableService, iPlayableService, iPlayableServicePtr, addFont, gFont, \
- gRGB, loadPNG, ePythonMessagePump, eConsoleAppContainer, eLabel
- from parsers import SubRipParser, MicroDVDParser
- from process import SubsLoader, DecodeError, ParseError, ParserNotFoundError, \
- LoadError
- from searchsubs import Messages
- from seek import SubsSeeker, SubtitlesDownloadError, SubtitlesErrors
- from seekers.utilities import detectSearchParams, languageTranslate
- from skin import parseColor, parsePosition, parseFont
- from utils import toString, SimpleLogger, toUnicode
-
- from . import _, __author__, __version__, __email__
-
-
- try:
- from xml.etree.cElementTree import parse as parse_xml
- except ImportError:
- from xml.etree.ElementTree import parse as parse_xml
-
-
- try:
- from Screens.AudioSelection import QuickSubtitlesConfigMenu
- except ImportError:
- QuickSubtitlesConfigMenu = None
-
-
-
- # localization function
-
- def warningMessage(session, text):
- session.open(MessageBox, text, type=MessageBox.TYPE_WARNING, timeout=5)
-
- def debug(text, *args):
- if DEBUG:
- if len(args) == 1 and isinstance(args[0], tuple):
- text = text % args[0]
- else:
- text = text % (args)
- print "[SubsSupport]", toString('utf-8')
-
-
- # set the name of plugin in which this library belongs
- # PLUGIN_NAME = 'mediaplayer2'
-
- # set debug mode
- DEBUG = False
-
- # set supported encodings, you have to make sure, that you have corresponding python
- # libraries in %PYTHON_PATH%/encodings/ (ie. iso-8859-2 requires iso_8859_2.searchsubs library)
-
- # to choose encodings for region you want, visit:
- # http://docs.python.org/release/2.4.4/lib/standard-encodings.html
-
- # Common encodings for all languages
- ALL_LANGUAGES_ENCODINGS = ['utf-8', 'utf-16']
-
- # other encodings, sorted according usage
- CENTRAL_EASTERN_EUROPE_ENCODINGS = ['windows-1250', 'iso-8859-2', 'maclatin2', 'IBM852']
- WESTERN_EUROPE_ENCODINGS = ['windows-1252', 'iso-8859-15', 'macroman', 'ibm1140', 'IBM850']
- RUSSIAN_ENCODINGS = ['windows-1251', 'cyrillic', 'maccyrillic', 'koi8_r', 'IBM866']
- ARABIC_ENCODINGS = ['windows-1256', 'iso-8859-6', 'IBM864']
- TURKISH_ENCODINGS = ['windows-1254', 'iso-8859-9', 'latin5', 'macturkish', 'ibm1026', 'IBM857']
- GREEK_ENCODINGS = ['windows-1253', 'iso-8859-7', 'macgreek']
-
- ENCODINGS = {("Central and Eastern Europe") : CENTRAL_EASTERN_EUROPE_ENCODINGS,
- ("Western Europe"):WESTERN_EUROPE_ENCODINGS,
- ("Russia"):RUSSIAN_ENCODINGS,
- ("Arabic"): ARABIC_ENCODINGS,
- ("Turkish"):TURKISH_ENCODINGS,
- ("Greek"):GREEK_ENCODINGS}
-
- # initializing parsers
- PARSERS = [SubRipParser, MicroDVDParser]
-
- def getDefaultFont(fontType):
- ubuntu = None
- openpli = None
- for f in getFonts():
- if fontType == "regular":
- if f == "Subs":
- openpli = f
- elif f== "Ubuntu-M":
- ubuntu = f
- elif fontType == "italic":
- if f == "Subsi":
- openpli = f
- elif f=="Ubuntu-MI":
- ubuntu = f
- elif fontType == "bold":
- if f == "Subsb":
- openpli = f
- elif f =="Ubuntu-B":
- ubuntu = f
- if ubuntu:
- return ubuntu
- if openpli:
- return openpli
- return "Regular"
-
- def getEmbeddedFontSizeCfg(defaultFontSizeCfg):
- CONFIG_SUBTITLES_OPENPLI = "subtitles"
- CONFIG_FONTSIZE_OPENPLI = "subtitle_fontsize"
- CONFIG_SUBTITLES_VTI = "subtitle"
- CONFIG_FONTSIZE_VTI = "subtitlefontsize"
-
- try:
- subtitles_pli_cfg = getattr(config, CONFIG_SUBTITLES_OPENPLI)
- except KeyError:
- subtitles_pli_cfg = None
- if subtitles_pli_cfg is not None:
- try:
- return getattr(subtitles_pli_cfg, CONFIG_FONTSIZE_OPENPLI)
- except KeyError:
- pass
- try:
- subtitles_vti_cfg = getattr(config, CONFIG_SUBTITLES_VTI)
- except KeyError:
- subtitles_vti_cfg = None
- if subtitles_vti_cfg is not None:
- try:
- return getattr(subtitles_vti_cfg, CONFIG_FONTSIZE_VTI)
- except KeyError:
- pass
- return defaultFontSizeCfg
-
- GLOBAL_CONFIG_INIT = False
-
- fontChoiceList = [f for f in getFonts()]
- fontSizeChoiceList = [("%d" % i, "%d px" % i) for i in range(10, 60, 1)]
- positionChoiceList = [("0", _("top"))]
- positionChoiceList.extend([("%d" % i, "%d %%" % i) for i in range(1, 100, 1)])
- positionChoiceList.append(("100", _("bottom")))
- shadowSizeChoiceList = [("%d" % i, "%d px" % i) for i in range(1, 8, 1)]
- shadowOffsetChoiceList = [("%d" % i, "%d px" % i) for i in range(-8, -1, 1)]
- backgroundOffsetChoiceList = [("%d" % i, "%d px" % i) for i in range(5, 100, 1)]
- colorChoiceList = []
- colorChoiceList.append(("ff0000", _("red")))
- colorChoiceList.append(("DCDCDC", _("grey")))
- colorChoiceList.append(("00ff00", _("green")))
- colorChoiceList.append(("ff00ff", _("purple")))
- colorChoiceList.append(("ffff00", _("yellow")))
- colorChoiceList.append(("ffffff", _("white")))
- colorChoiceList.append(("00ffff", _("blue")))
- colorChoiceList.append(("000000", _("black")))
- COLORFILE = os.path.join(os.path.dirname(__file__), 'colors.txt')
- print '[SubsSupport] looking for custom colors in', COLORFILE
- try:
- with open(COLORFILE, 'r') as f:
- for line in f:
- color = re.search('^(\w+)\s+([0-9A-Fa-f]{6})$', line)
- if color is not None:
- alias = color.group(1)
- hex_color = color.group(2)
- print '[SubsSupport] adding custom color', alias
- colorChoiceList.append((hex_color, alias))
- except IOError as e:
- print '[SubsSupport] error while loading custom colors', str(e)
-
- alphaChoiceList = [("00", _("opaque"))]
- alphaChoiceList.extend([("%02x" % val, "%d %%"%(int(percent * 100 / float(32)))) for percent, val in enumerate(xrange(0, 256, 8)) if val != 0])
- alphaChoiceList.append(("ff", _("transparent")))
-
- def initGeneralSettings(configsubsection):
- configsubsection.pauseVideoOnSubtitlesMenu = ConfigYesNo(default=True)
- configsubsection.encodingsGroup = ConfigSelection(default="Central and Eastern Europe", choices=[(e, _(e)) for e in ENCODINGS.keys()])
-
- def initExternalSettings(configsubsection):
- configsubsection.position = ConfigSelection(default="94", choices=positionChoiceList)
- configsubsection.font = ConfigSubsection()
- configsubsection.font.regular = ConfigSubsection()
- configsubsection.font.regular.type = ConfigSelection(default=getDefaultFont("regular"), choices=fontChoiceList)
- configsubsection.font.regular.alpha = ConfigSelection(default="00", choices=alphaChoiceList)
- configsubsection.font.regular.color = ConfigSelection(default="ffffff", choices=colorChoiceList)
- configsubsection.font.italic = ConfigSubsection()
- configsubsection.font.italic.type = ConfigSelection(default=getDefaultFont("italic"), choices=fontChoiceList)
- configsubsection.font.italic.alpha = ConfigSelection(default="00", choices=alphaChoiceList)
- configsubsection.font.italic.color = ConfigSelection(default="ffffff", choices=colorChoiceList)
- configsubsection.font.bold = ConfigSubsection()
- configsubsection.font.bold.type = ConfigSelection(default=getDefaultFont("bold"), choices=fontChoiceList)
- configsubsection.font.bold.alpha = ConfigSelection(default="00", choices=alphaChoiceList)
- configsubsection.font.bold.color = ConfigSelection(default="ffffff", choices=colorChoiceList)
- configsubsection.font.size = ConfigSelection(default="43", choices=fontSizeChoiceList)
- configsubsection.shadow = ConfigSubsection()
- configsubsection.shadow.enabled = ConfigOnOff(default=True)
- configsubsection.shadow.type = ConfigSelection(default="border", choices=[("offset", _("offset")), ("border", _('border'))])
- configsubsection.shadow.color = ConfigSelection(default="000000", choices=colorChoiceList)
- configsubsection.shadow.size = ConfigSelection(default="2", choices=shadowSizeChoiceList)
- configsubsection.shadow.xOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
- configsubsection.shadow.yOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
- configsubsection.background = ConfigSubsection()
- configsubsection.background.enabled = ConfigOnOff(default=True)
- configsubsection.background.type = ConfigSelection(default="dynamic", choices=[("dynamic", _("dynamic")), ("static", _("static"))])
- configsubsection.background.xOffset = ConfigSelection(default="10", choices=backgroundOffsetChoiceList)
- configsubsection.background.yOffset = ConfigSelection(default="10", choices=backgroundOffsetChoiceList)
- configsubsection.background.color = ConfigSelection(default="000000", choices=colorChoiceList)
- configsubsection.background.alpha = ConfigSelection(default="80", choices=alphaChoiceList)
-
- def initEmbeddedSettings(configsubsection):
- configsubsection.position = ConfigSelection(default="94", choices=positionChoiceList)
- configsubsection.font = ConfigSubsection()
- configsubsection.font.regular = ConfigSubsection()
- configsubsection.font.regular.type = ConfigSelection(default=getDefaultFont("regular"), choices=fontChoiceList)
- configsubsection.font.italic = ConfigSubsection()
- configsubsection.font.italic.type = ConfigSelection(default=getDefaultFont("italic"), choices=fontChoiceList)
- configsubsection.font.bold = ConfigSubsection()
- configsubsection.font.bold.type = ConfigSelection(default=getDefaultFont("bold"), choices=fontChoiceList)
- configsubsection.font.size = ConfigSelection(default="34", choices=fontSizeChoiceList)
- configsubsection.color = ConfigSelection(default="ffffff", choices=colorChoiceList)
- configsubsection.shadow = ConfigSubsection()
- configsubsection.shadow.size = ConfigSelection(default="3", choices=shadowSizeChoiceList)
- configsubsection.shadow.color = ConfigSelection(default="000000", choices=colorChoiceList)
- configsubsection.shadow.xOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
- configsubsection.shadow.yOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
-
- def initEngineSettings(configsubsection):
- configsubsection.expert = ConfigSubsection()
- configsubsection.expert.show = NoSave(ConfigYesNo(default=False))
- configsubsection.expert.playerDelay = ConfigSelection(default="0", choices=[("%d" % i, "%d ms" % i) for i in range(0, 20000, 200)])
- configsubsection.expert.startDelay = ConfigSelection(default="1200", choices=[("%d" % i, "%d ms" % i) for i in range(0, 100, 1500)])
- configsubsection.expert.hideDelay = ConfigSelection(default="200", choices=[("%d" % i, "%d ms" % i) for i in range(0, 1000, 50)])
- configsubsection.expert.ptsDelayCheck = ConfigSelection(default="200", choices=[("%d" % i, "%d ms" % i) for i in range(100, 1000, 100)])
- configsubsection.expert.syncDelay = ConfigSelection(default="300", choices=[("%d" % i, "%d ms" % i) for i in range(100, 1000, 100)])
- configsubsection.expert.refreshDelay = ConfigSelection(default="1000", choices=[("%d" % i, "%d ms" % i) for i in range(200, 3000, 200)])
-
- def initSearchSettings(configsubsection):
- configsubsection.downloadHistory = ConfigSubsection()
- configsubsection.downloadHistory.enabled = ConfigYesNo(default=True)
- configsubsection.downloadHistory.limit = ConfigInteger(default=50, limits=(2, 200))
- configsubsection.downloadHistory.path = ConfigDirectory(default = os.path.dirname(__file__), visible_width=30)
- configsubsection.downloadHistory.removeAction = ConfigSelection(default='list', choices=[('list', _("List")), ('file', _("List + File"))])
- configsubsection.downloadHistory.removeActionAsk = ConfigYesNo(default = True)
- configsubsection.downloadPath = ConfigDirectory(default="/tmp/")
- configsubsection.tmpPath = ConfigDirectory(default="/tmp/")
- configsubsection.lang1 = ConfigFinalText(default=language.getLanguage()[:2])
- configsubsection.lang2 = ConfigFinalText(default=language.getLanguage()[:2])
- configsubsection.lang3 = ConfigFinalText(default=language.getLanguage()[:2])
- configsubsection.timeout = ConfigSelection(default="10", choices=[(("%d" % i, "%d s" % i)) for i in range(5, 20)])
- configsubsection.history = ConfigText(default="")
- configsubsection.movieProvider = ConfigSelection(default="all", choices=[("all", _("All")), ])
- configsubsection.tvshowProvider = ConfigSelection(default="all", choices=[("all", _("All")), ])
- configsubsection.manualSearch = ConfigYesNo(default=False)
- configsubsection.defaultSort = ConfigSelection(default='lang', choices=[('lang', _("Language")), ('provider', _("Provider"))])
- configsubsection.saveAs = ConfigSelection(default='version', choices=[('default', _("Default")), ('version', _("Release")), ('video', _("Video filename"))])
- configsubsection.saveAsFallback = ConfigSelection(default='version', choices=[('default', _("Default")), ('version', _("Release"))])
- configsubsection.saveTo = ConfigSelection(default='custom', choices=[('custom', _('User defined')), ('video', _('Next to video'))])
- configsubsection.addLangToSubsFilename = ConfigYesNo(default=False)
- configsubsection.askOverwriteExistingSubs = ConfigYesNo(default=True)
- configsubsection.loadSubtitlesAfterDownload = ConfigYesNo(default=True)
- configsubsection.openParamsDialogOnSearch = ConfigYesNo(default=True)
- configsubsection.showProvidersErrorMessage = ConfigYesNo(default=True)
- # session settings
- configsubsection.title = ConfigTextWithSuggestionsAndHistory(configsubsection.history, default="", fixed_size=False)
- configsubsection.type = ConfigSelection(default="movie", choices=[("tv_show", _("TV show")), ("movie", _("Movie"))])
- configsubsection.year = ConfigInteger(default=0, limits=(0, 2100))
- configsubsection.season = ConfigInteger(default=0, limits=(0, 100))
- configsubsection.episode = ConfigInteger(default=0, limits=(0, 100))
- configsubsection.provider= ConfigSelection(default="all", choices=[("all", _("All")), ])
- configsubsection.useFilePath = ConfigYesNo(default=True)
-
-
- def initSubsSettings(configSubsection=None):
- global GLOBAL_CONFIG_INIT
- if configSubsection:
- print '[SubsSupport] using provided ConfigSubsection to store config'
- subtitles_settings = configSubsection
- elif 'PLUGIN_NAME' in globals():
- print '[SubsSupport] using config.plugins.%s.%s to store config' % (PLUGIN_NAME, 'subtitles')
- plugin_settings = getattr(config.plugins, PLUGIN_NAME)
- setattr(plugin_settings, 'subtitles', ConfigSubsection())
- subtitles_settings = getattr(plugin_settings, 'subtitles')
- elif GLOBAL_CONFIG_INIT:
- print "[SubsSupport] using global config (already initialized)"
- return config.plugins.subtitlesSupport
- else:
- print "[SubsSupport] using global config"
- config.plugins.subtitlesSupport = ConfigSubsection()
- subtitles_settings = config.plugins.subtitlesSupport
- GLOBAL_CONFIG_INIT = True
-
- initGeneralSettings(subtitles_settings)
- subtitles_settings.external = ConfigSubsection()
- initExternalSettings(subtitles_settings.external)
- subtitles_settings.embedded = ConfigSubsection()
- initEmbeddedSettings(subtitles_settings.embedded)
- subtitles_settings.engine = ConfigSubsection()
- initEngineSettings(subtitles_settings.engine)
- subtitles_settings.search = ConfigSubsection()
- initSearchSettings(subtitles_settings.search)
- return subtitles_settings
-
-
- class SubsStatusScreen(Screen, HelpableScreen):
-
- def __init__(self, session, setSubsDelay, getSubsDelay, subscribeDelay, unsubscribeDelay, toNextSub, toPrevSub, setSubsFps, getSubsFps, subsDelayStepInMs=200, showDelayInMs=False):
- desktopWidth = getDesktop(0).size().width()
- offset = 50
- self.skin = """
- <screen position="%d,20" size="%d,90" zPosition="5" backgroundColor="transparent" flags="wfNoBorder">
- <widget source="delay" render="Label" position="0,0" size="%d,70" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="#ffffff" shadowColor="#40101010" shadowOffset="2,2" />
- <widget source="fps" render="Label" position="%d,0" size="%d,70" valign="center" halign="right" font="Regular;22" transparent="1" foregroundColor="#6F9EF5" shadowColor="#40101010" shadowOffset="2,2" />
- </screen>""" % (offset, desktopWidth-(2*offset), (desktopWidth - (2*offset))/2 - 5, (desktopWidth-(2*offset))/2 + 5, (desktopWidth-(2*offset))/2 - 5)
-
- Screen.__init__(self, session)
- HelpableScreen.__init__(self)
- self.setSubsDelay = setSubsDelay
- self.getSubsDelay = getSubsDelay
- self.subscribeDelay = subscribeDelay
- self.unsubscribeDelay = unsubscribeDelay
- self.toNextSub = toNextSub
- self.toPrevSub = toPrevSub
- self.setSubsFps = setSubsFps
- self.getSubsFps = getSubsFps
- self.subsDelayStep = subsDelayStepInMs
- self.showDelayInMs = showDelayInMs
- self.fpsChoices = ["23.976", "23.980", "24.000", "25.000", "29.970", "30.000"]
- self['fps'] = StaticText()
- self['delay'] = StaticText()
- self['SubsArrowActions'] = HelpableActionMap(self, "DirectionActions",
- {
- 'right': (self.nextSubDelay, _("jump to next subtitle")),
- 'left':(self.prevSubDelay, _("jump to previous subtitle")),
- 'up':(self.incSubDelay, _("increase subtitles delay")),
- 'down':(self.decSubDelay, _("decrease subtitles delay")),
- })
- self['SubsColorActions'] = HelpableActionMap(self, "ColorActions",
- {
- 'red': (self.reset, _("reset subtitles delay/fps")),
- 'blue': (self.changeFps, _("change subtitles fps")),
- })
- self['OkCancelActions'] = HelpableActionMap(self, "OkCancelActions",
- {
- 'ok': (self.showHelp, _("displays this menu")),
- 'cancel':(self.close, _("exit"))
- })
- self._subsDelay = None
- self.onLayoutFinish.append(self._subscribeDelay)
- self.onLayoutFinish.append(self.updateSubsFps)
- self.onLayoutFinish.append(self.updateSubsDelay)
- self.onClose.append(self._unsubscribeDelay)
-
- def _subscribeDelay(self):
- self.subscribeDelay(self._setSubsDelayAndUpdate)
-
- def _unsubscribeDelay(self):
- self.unsubscribeDelay(self._setSubsDelayAndUpdate)
-
- def _setSubsDelayAndUpdate(self, delay):
- self._subsDelay = delay
- self.updateSubsDelay()
-
- def _getSubsDelay(self):
- if self._subsDelay is None:
- self._subsDelay = self.getSubsDelay()
- return self._subsDelay
-
- def updateSubsFps(self):
- subsFps = self.getSubsFps()
- videoFps = getFps(self.session, True)
- if subsFps is None or videoFps is None:
- self['fps'].text = "%s: %s"%(_("Subtitles FPS"), _("unknown"))
- return
- if subsFps == videoFps:
- self['fps'].text = "%s: %s"%(_("Subtitles FPS"), _("original"))
- else:
- self['fps'].text = "%s: %s"%(_("Subtitles FPS"), str(subsFps))
-
- def updateSubsDelay(self):
- subsDelay = self._getSubsDelay()
- if self.showDelayInMs:
- if subsDelay > 0:
- self["delay"].text = "%s: +%dms"%(_("Subtitles Delay"), subsDelay)
- else:
- self["delay"].text = "%s: %dms"%(_("Subtitles Delay"), subsDelay)
- else:
- if subsDelay > 0:
- self["delay"].text = "%s: +%.2fs"%(_("Subtitles Delay"), subsDelay/float(1000))
- else:
- self["delay"].text = "%s: %.2fs"%(_("Subtitles Delay"), subsDelay/float(1000))
-
- def nextSubDelay(self):
- self.toNextSub()
-
- def prevSubDelay(self):
- self.toPrevSub()
-
- def incSubDelay(self):
- self.setSubsDelay(self._getSubsDelay() + self.subsDelayStep)
-
- def decSubDelay(self):
- self.setSubsDelay(self._getSubsDelay() - self.subsDelayStep)
-
- def changeFps(self):
- subsFps = self.getSubsFps()
- if subsFps is None:
- return
- currIdx = self.fpsChoices.index(str(subsFps))
- if currIdx == len(self.fpsChoices) -1:
- nextIdx = 0
- else:
- nextIdx = currIdx+1
- self.setSubsFps(fps_float(self.fpsChoices[nextIdx]))
- self.updateSubsFps()
-
- def reset(self):
- self.setSubsFps(getFps(self.session, True))
- self.setSubsDelay(0)
- self.updateSubsFps()
-
-
- class SubsSupportStatus(object):
- def __init__(self, delayStepInMs=200, showDelayInMs=False, statusScreen=None):
- assert isinstance(self, SubsSupport), "not derived from SubsSupport!"
- self.__delayStepInMs = delayStepInMs
- self.__showDelayInMs = showDelayInMs
- self.__statusScreen = statusScreen
- self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
- {
- iPlayableService.evStart: self.__serviceChanged,
- iPlayableService.evEnd: self.__serviceChanged,
- })
- self["SubsStatusActions"] = HelpableActionMap(self, "SubtitlesActions",
- {
- "subtitlesStatus": (self.subsStatus, _("change external subtitles status")),
- } , -5)
- self.onClose.append(self.__closeSubsStatusScreen)
-
- def __serviceChanged(self):
- self.__closeSubsStatusScreen()
-
- def __closeSubsStatusScreen(self):
- try:
- self.__subsStatusScreen.close()
- except Exception:
- pass
-
- def subsStatus(self):
- setDelay = self.setSubsDelay
- getDelay = self.getSubsDelay
- subscribe = self.subscribeOnSubsDelayChanged
- unsubscribe = self.unsubscribeOnSubsDelayChanged
- toNextSub = self.setSubsDelayToNextSubtitle
- toPrevSub = self.setSubsDelayToPrevSubtitle
- getFps = self.getSubsFps
- setFps = self.setSubsFps
- if self.isSubsLoaded():
- self.__subsStatusScreen = self.session.open(SubsStatusScreen,
- setDelay, getDelay, subscribe, unsubscribe, toNextSub, toPrevSub, setFps, getFps,
- self.__delayStepInMs, self.__showDelayInMs)
- else:
- if self.__statusScreen is not None:
- self.__statusScreen.setStatus(_("No external subtitles are loaded"))
- elif isinstance(self, InfoBarNotifications):
- Notifications.AddNotification(MessageBox, _("No external subtitles are loaded"), type=MessageBox.TYPE_INFO, timeout=2)
-
- class SubsSupportEmbedded(object):
-
- def __init__(self, embeddedSupport, preferEmbedded):
- self.embeddedSupport = embeddedSupport
- self.preferEmbedded = preferEmbedded
- self.__subStyles = {}
- self.selected_subtitle = None
- self.subtitle_window = self.session.instantiateDialog(SubsEmbeddedScreen, self.subsSettings.embedded)
- self.subtitle_window.hide()
- if isinstance(self, InfoBarBase):
- self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
- {
- iPlayableService.evStart: self.__serviceChanged,
- iPlayableService.evEnd: self.__serviceChanged,
- # iPlayableService.evUpdatedInfo: self.__updatedInfo
- })
- self.onClose.append(self.exitEmbeddedSubs)
-
- def __isEmbeddedEnabled(self):
- return self.subtitle_window.shown
-
- embeddedEnabled = property(__isEmbeddedEnabled)
-
- def getCurrentServiceSubtitle(self):
- service = self.session.nav.getCurrentService()
- return service and service.subtitle()
-
- def __serviceChanged(self):
- if self.selected_subtitle:
- self.selected_subtitle = None
- self.subtitle_window.hide()
-
- def __updatedInfo(self):
- if not self.selected_subtitle:
- subtitle = self.getCurrentServiceSubtitle()
- cachedsubtitle = subtitle.getCachedSubtitle()
- if cachedsubtitle:
- self.enableSubtitle(cachedsubtitle)
-
- def enableSubtitle(self, selectedSubtitle):
- print '[SubsSupportEmbedded] enableSubtitle', selectedSubtitle
- subtitle = self.getCurrentServiceSubtitle()
- self.selected_subtitle = selectedSubtitle
- if subtitle and self.selected_subtitle:
- self.resetEmbeddedSubs()
- subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
- self.subtitle_window.show()
- print '[SubsSupportEmbedded] enable embedded subtitles'
- else:
- print '[SubsSupportEmbedded] disable embedded subtitles'
- if subtitle:
- subtitle.disableSubtitles(self.subtitle_window.instance)
- self.subtitle_window.hide()
-
- def restartSubtitle(self):
- if self.selected_subtitle:
- print '[SubsSupportEmbedded] restart embedded subtitles'
- self.enableSubtitle(self.selected_subtitle)
-
- def resetEmbeddedSubs(self, reloadScreen=False):
- if QuickSubtitlesConfigMenu:
- return
- print '[SubsSupportEmbedded] updating embedded screen'
- from enigma import eWidget, eSubtitleWidget
- scale = ((1, 1), (1, 1))
- embeddedSettings = self.subsSettings.embedded
- fontSize = embeddedSettings.font.size.value
- fontTypeR = embeddedSettings.font.regular.type.value
- fontTypeI = embeddedSettings.font.italic.type.value
- fontTypeB = embeddedSettings.font.bold.type.value
- foregroundColor = "#" + embeddedSettings.color.value
- foregroundColor = parseColor(foregroundColor)
- borderColor = "#" + embeddedSettings.shadow.color.value
- borderColor = parseColor(borderColor)
- borderWidth = int(embeddedSettings.shadow.size.value)
- offset = "%s,%s" % (embeddedSettings.shadow.xOffset.value,
- embeddedSettings.shadow.yOffset.value)
- shadowOffset = parsePosition(offset, scale)
- fontRegular = parseFont("%s;%s" % (fontTypeR, fontSize), scale)
- fontItalic = parseFont("%s;%s" % (fontTypeI, fontSize), scale)
- fontBold = parseFont("%s;%s" % (fontTypeB, fontSize), scale)
- self._loadEmbeddedStyle({"Subtitle_Regular":(fontRegular, 1, foregroundColor, borderColor, borderWidth, borderColor, shadowOffset),
- "Subtitle_Italic":(fontItalic, 1, foregroundColor, borderColor, borderWidth, borderColor, shadowOffset),
- "Subtitle_Bold":(fontBold, 1, foregroundColor, borderColor, borderWidth, borderColor, shadowOffset)})
- if reloadScreen:
- print '[SubsSupportEmbedded] reloading embedded screen'
- subtitle = self.getCurrentServiceSubtitle()
- if subtitle:
- subtitle.disableSubtitles(self.subtitle_window.instance)
- self.session.deleteDialog(self.subtitle_window)
- self.subtitle_window = None
- self.subtitle_window = self.session.instantiateDialog(SubsEmbeddedScreen, self.subsSettings.embedded)
- self.subtitle_window.hide()
- self.restartSubtitle()
-
- def _parseEmbeddedStyles(self, filename):
- if filename in self.__subStyles:
- return self.defaultStyles[filename]
- skin = parse_xml(filename).getroot()
- for c in skin.findall("subtitles"):
- scale = ((1, 1), (1, 1))
- substyles = {}
- for substyle in c.findall("sub"):
- get_attr = substyle.attrib.get
- font = parseFont(get_attr("font"), scale)
- col = get_attr("foregroundColor")
- if col:
- foregroundColor = parseColor(col)
- haveColor = 1
- else:
- foregroundColor = gRGB(0xFFFFFF)
- haveColor = 0
- col = get_attr("borderColor")
- if col:
- borderColor = parseColor(col)
- else:
- borderColor = gRGB(0)
- borderwidth = get_attr("borderWidth")
- if borderwidth is None:
- # default: use a subtitle border
- borderWidth = 3
- else:
- borderWidth = int(borderwidth)
- col = get_attr("shadowColor")
- if col:
- shadowColor = parseColor(col)
- else:
- shadowColor = gRGB(0)
- col = get_attr("shadowOffset")
- if col:
- shadowOffset = get_attr("shadowOffset")
- else:
- shadowOffset = "-3,-3"
- shadowOffset = parsePosition(shadowOffset, scale)
- substyles[get_attr("name")] = (font, haveColor, foregroundColor, borderColor, borderWidth, shadowColor, shadowOffset)
- self.__subStyles[filename] = substyle
- return substyles
-
- def _loadEmbeddedStyle(self, substyles):
- from enigma import eWidget, eSubtitleWidget
- for faceName in substyles.keys():
- s = substyles[faceName]
- face = eSubtitleWidget.__dict__[faceName]
- font, haveColor, foregroundColor, borderColor, borderWidth, shadowColor, shadowOffset = s[0], s[1], s[2], s[3], s[4], s[5], s[6]
- try:
- eSubtitleWidget.setFontStyle(face, font , haveColor, foregroundColor, borderColor, borderWidth)
- except TypeError:
- eSubtitleWidget.setFontStyle(face, font, haveColor, foregroundColor, shadowColor, shadowOffset)
-
- def resetEmbeddedDefaults(self):
- userSkin = resolveFilename(SCOPE_SKIN, 'skin_user.xml')
- defaultSkin = resolveFilename(SCOPE_SKIN, 'skin_default.xml')
- skinSubtitles = resolveFilename(SCOPE_SKIN, 'skin_subtitles.xml')
- skinPaths = [userSkin, skinSubtitles, defaultSkin]
- for skinPath in skinPaths:
- if fileExists(skinPath):
- styles = self._parseEmbeddedStyles(skinPath)
- if styles:
- print "[SubsEmbeddedSupport] reseting defaults from", skinPath
- self._loadEmbeddedStyle(styles)
- break
-
- def exitEmbeddedSubs(self):
- if self.subtitle_window is not None:
- self.session.deleteDialog(self.subtitle_window)
- self.subtitle_window = None
- if not QuickSubtitlesConfigMenu:
- self.resetEmbeddedDefaults()
-
-
- class SubsSupport(SubsSupportEmbedded):
- """Client class for subtitles
-
- If this class is not subclass of InfoBarBase you should use public function of this class to
- to connect your media player (resume,pause,exit,after seeking, subtitles setup)
- functions with subtitles
-
- @param session: set active session
- @param subsPath: set path for subtitles to load
- @param defaultPath: set default path when choosing external subtitles
- @param forceDefaultPath: always use default path when choosing external subtitles
- @param autoLoad: tries to auto load subtitles according to name of played file
- @param embeddedSupport: added support for embedded subtitles
- """
-
- def __init__(self, session=None, subsPath=None, defaultPath=None, forceDefaultPath=False, autoLoad=True,
- showGUIInfoMessages=True, embeddedSupport=False, preferEmbedded=False, searchSupport=False, configEntry=None):
- if session is not None:
- self.session = session
- self.searchSupport = searchSupport
- self.subsSettings = initSubsSettings(configEntry)
- SubsSupportEmbedded.__init__(self, embeddedSupport, preferEmbedded)
- self.__subsScreen = self.session.instantiateDialog(SubsScreen, self.subsSettings.external)
- self.__subsScreen.hide()
- self.__subsEngine = SubsEngine(self.session, self.subsSettings.engine, self.__subsScreen)
- self.__subsLoader = SubsLoader(PARSERS, ALL_LANGUAGES_ENCODINGS + ENCODINGS[self.subsSettings.encodingsGroup.getValue()])
- self.__subsLoader.set_row_parsing(False)
- self.__loaded = False
- self.__working = False
- self.__firstStart = True
- self.__autoLoad = autoLoad
- self.__subsPath = None
- self.__subsDir = None
- self.__subsEnc = None
- self.__playerDelay = 0
- self.__startDelay = int(self.subsSettings.engine.expert.startDelay.value)
- self.__defaultPath = None
- self.__isServiceSet = False
- self.__subclassOfInfobarBase = isinstance(self, InfoBarBase)
- self.__forceDefaultPath = forceDefaultPath
- self.__showGUIInfoMessages = showGUIInfoMessages
- self.__checkTimer = eTimer()
- self.__starTimer = eTimer()
- self.__starTimer.callback.append(self.__updateSubs)
- try:
- from Screens.InfoBar import InfoBar
- InfoBar.instance.subtitle_window.hide()
- except Exception:
- pass
-
- if self.__subclassOfInfobarBase:
- self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
- {
- iPlayableService.evStart: self.__serviceStarted,
- iPlayableService.evEnd: self.__serviceStopped,
- iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
- })
- self["SubsActions"] = HelpableActionMap(self, "SubtitlesActions",
- {
- "subtitles": (self.subsMenu, _("show subtitles menu")),
- } , -5)
-
- self.onClose.append(self.exitSubs)
-
- if defaultPath is not None and os.path.isdir(toString(defaultPath)):
- self.__defaultPath = toString(defaultPath)
- self.__subsDir = toString(defaultPath)
-
- if subsPath is not None and self.__autoLoad:
- self.loadSubs(subsPath)
-
- def loadSubs(self, subsPath, newService=True):
- """loads subtitles from subsPath
- @param subsPath: path to subtitles (http url supported)
- @param newService: set False if service remains the same
- @return: True if subtitles was successfully loaded
- @return: False if subtitles wasnt successfully loaded
- """
- self.__working = True
- self.__subsPath = None
- if self.__defaultPath is not None:
- self.__subsDir = self.__defaultPath
- else:
- self.__subsDir = None
-
- if subsPath is not None:
- subsPath = toString(subsPath)
- if not subsPath.startswith('http'):
- if self.__defaultPath is not None and self.__forceDefaultPath:
- self.__subsDir = self.__defaultPath
- else:
- if os.path.isdir(os.path.dirname(subsPath)):
- self.__subsDir = os.path.dirname(subsPath)
- else:
- self.__subsDir = self.__defaultPath
- if not os.path.isfile(subsPath):
- print '[Subtitles] trying to load not existing path:', subsPath
- subsPath = None
-
- if subsPath is not None:
- subsList, self.__subsEnc = self.__processSubs(subsPath, self.__subsEnc)
- if subsList is not None:
- self.__subsPath = subsPath
- if newService:
- self.__subsEngine.reset()
- self.__subsEngine.pause()
- self.__subsEngine.setPlayerDelay(self.__playerDelay)
- self.__subsEngine.setSubsList(subsList)
- self.__loaded = True
- self.__working = False
- return True
- else:
- self.__subsEnc = None
- self.__subsPath = None
- self.__working = False
- return False
-
-
- def startSubs(self, time):
- """If subtitles are loaded then start to play them after time set in ms"""
- def wrapped():
- self.__startTimer.start(time, True)
-
- if self.__working or self.__loaded:
- self.__afterWork(wrapped)
-
- def isSubsLoaded(self):
- return self.__loaded
-
- def getSubsFileFromSref(self):
- ref = self.session.nav.getCurrentlyPlayingServiceReference()
- if os.path.isdir(os.path.dirname(ref.getPath())):
- self.__subsDir = os.path.dirname(ref.getPath())
- for parser in PARSERS:
- for ext in parser.parsing:
- subsPath = os.path.splitext(ref.getPath())[0] + ext
- if os.path.isfile(subsPath):
- return subsPath
- return None
-
- def resumeSubs(self):
- if self.__loaded:
- print '[Subtitles] resuming subtitles'
- self.showSubsDialog()
- self.__subsEngine.resume()
-
- def pauseSubs(self):
- if self.__loaded:
- print '[Subtitles] pausing subtitles'
- self.__subsEngine.pause()
-
- def playAfterSeek(self):
- if self.__loaded:
- self.showSubsDialog()
- self.__subsEngine.sync()
-
- def showSubsDialog(self):
- if self.__loaded:
- print '[Subtitles] show dialog'
- self.__subsScreen.show()
-
- def hideSubsDialog(self):
- if self.__loaded:
- print '[Subtitles] hide dialog'
- if self.__subsScreen:
- self.__subsScreen.hide()
-
- def setPlayerDelay(self, delayInMs):
- self.__playerDelay = delayInMs
-
- def subscribeOnSubsDelayChanged(self, fnc):
- if fnc not in self.__subsEngine.onSubsDelayChanged:
- self.__subsEngine.onSubsDelayChanged.append(fnc)
-
- def unsubscribeOnSubsDelayChanged(self, fnc):
- if fnc in self.__subsEngine.onSubsDelayChanged:
- self.__subsEngine.onSubsDelayChanged.remove(fnc)
-
- def setSubsDelay(self, delayInMs):
- if self.__loaded:
- self.__subsEngine.setSubsDelay(delayInMs)
-
- def setSubsDelayToNextSubtitle(self):
- if self.__loaded:
- self.__subsEngine.setSubsDelayToNextSubtitle()
-
- def setSubsDelayToPrevSubtitle(self):
- if self.__loaded:
- self.__subsEngine.setSubsDelayToPrevSubtitle()
-
- def getSubsDelay(self):
- if self.__loaded:
- return self.__subsEngine.getSubsDelay()
-
- def subscribeOnSubsFpsChanged(self, fnc):
- if fnc not in self.__subsEngine.onFpsChanged:
- self.__subsEngine.onFpsChanged.append(fnc)
-
- def unsubscribeOnSubsFpsChanged(self, fnc):
- if fnc in self.__subsEngine.onFpsChanged:
- self.__subsEngine.onFpsChanged.remove(fnc)
-
- def setSubsFps(self, fps):
- if self.__loaded:
- return self.__subsEngine.setSubsFps(fps)
-
- def getSubsFps(self):
- if self.__loaded:
- return self.__subsEngine.getSubsFps()
-
- def getSubsPath(self):
- return self.__subsPath
-
- def subsMenu(self):
- if not self.__working and not (self.__subclassOfInfobarBase and not self.__isServiceSet):
- self.__alreadyPausedVideo = False
- if self.subsSettings.pauseVideoOnSubtitlesMenu.value:
- print '[SubsSupport] stopVideoOnSubtitlesMenu: True'
- if isinstance(self, InfoBarSeek):
- if self.seekstate == InfoBarSeek.SEEK_STATE_PLAY:
- print '[SubsSupport] pausing video'
- self.setSeekState(InfoBarSeek.SEEK_STATE_PAUSE)
- else:
- print '[SubsSupport] video is already paused'
- self.__alreadyPausedVideo = True
- else:
- print '[SubsSupport] not subclass of InfobarSeek'
- self.session.openWithCallback(self.__subsMenuCB, SubsMenu, self,
- self.__subsPath, self.__subsDir, self.__subsEnc, self.embeddedSupport, self.embeddedEnabled, self.searchSupport)
-
- def resetSubs(self, resetEnc=True, resetEngine=True, newSubsScreen=False, newService=True):
- """
- Resets subtitle state -> stops engine, reload encodings, reset paths..
- @param resetEnc : start trying encodings from beginning of current encodings-group list
- @param resetEngine: clean active subtitle, subtitle list, reset engine vars
- @param newSubsSCreen: recreates subtitles screen
- @param newService: set to True if new servicereference is in use
- """
- # start trying encodings from beginning of encodings_group list
- if resetEnc:
- self.__subsEnc = None
- self.__subsLoader.change_encodings(ALL_LANGUAGES_ENCODINGS + ENCODINGS[self.subsSettings.encodingsGroup.getValue()])
- self.__subsEngine.pause()
- # stop subtitles, clean active subtitle, subtitles list, reset delay
- # if new service -> remove service
- if resetEngine:
- self.__subsEngine.setSubsDelay(0)
- self.__subsEngine.reset()
- if newService:
- self.__firstStart = False
- # hide subtitles, reload screen with new settings
- # if newSubsScreen, remove current subscreen and create new one
- self.__resetSubsScreen(newSubsScreen)
- self.__subsPath = None
- self.__loaded = False
-
- def __resetSubsScreen(self, newSubsScreen=False):
- self.__subsScreen.hide()
- if newSubsScreen:
- self.__subsEngine.setRenderer(None)
- self.session.deleteDialog(self.__subsScreen)
- self.__subsScreen = self.session.instantiateDialog(self._getSubsScreenCls(), self.subsSettings.external)
- self.__subsEngine.setRenderer(self.__subsScreen)
- else:
- self.__subsScreen.reloadSettings()
- self.__subsScreen.show()
-
-
- def exitSubs(self):
- """This method should be called at the end of usage of this class"""
- self.hideSubsDialog()
-
- if self.__subsEngine:
- self.__subsEngine.exit()
- self.__subsEngine = None
-
- if self.__subsScreen:
- self.session.deleteDialog(self.__subsScreen)
- self.__subsScreen = None
-
- self.__starTimer.stop()
- self.__starTimer = None
-
- self.__checkTimer.stop()
- self.__checkTimer = None
-
- print '[SubsSupport] closing subtitleDisplay'
-
-
- def __subsMenuCB(self, subsPath, subsEmbedded, settingsChanged, changeEncoding,
- changedEncodingGroup, changedShadowType, reloadEmbeddedScreen, turnOff, forceReload=False):
- if self.embeddedEnabled and self.embeddedSupport and not subsEmbedded and not turnOff and not subsPath:
- print "embedded settings changed"
- self.resetEmbeddedSubs(reloadEmbeddedScreen)
- elif turnOff:
- print '[SubsSupport] turn off'
- if self.embeddedSupport and self.embeddedEnabled:
- self.enableSubtitle(None)
- if self.__loaded:
- self.resetSubs(newService=False)
- elif self.embeddedSupport and subsEmbedded:
- print '[SubsSupport] loading embedded subtitles'
- if self.__loaded:
- self.resetSubs()
- self.__subsScreen.hide()
- self.enableSubtitle(subsEmbedded)
- elif subsPath is not None:
- if self.embeddedEnabled:
- self.enableSubtitle(None)
- newScreen = changedShadowType
- self.__subsScreen.show()
- if self.__subsPath == subsPath:
- if not settingsChanged and not ((changeEncoding or changedEncodingGroup) or newScreen or forceReload):
- print '[SubsSupport] no changes made'
- elif settingsChanged and not (newScreen or changedEncodingGroup or forceReload):
- print '[SubSupport] reloading SubScreen'
- self.__subsEngine.pause()
- self.__resetSubsScreen()
- self.__subsEngine.resume()
- else:
- self.__subsEngine.pause()
- if changedEncodingGroup or (changedShadowType and not changeEncoding) or forceReload:
- self.__subsEnc = None
- if changedEncodingGroup:
- self.__subsLoader.change_encodings(ALL_LANGUAGES_ENCODINGS + ENCODINGS[self.subsSettings.encodingsGroup.getValue()])
- if newScreen:
- self.__resetSubsScreen(newSubsScreen=True)
- self.__subsEngine.reset(position=False)
- if self.loadSubs(subsPath, newService=False):
- self.__subsEngine.refresh()
- else:
- self.pauseSubs()
- self.__subsEnc = None
- if changedEncodingGroup:
- self.__subsLoader.change_encodings(ALL_LANGUAGES_ENCODINGS + ENCODINGS[self.subsSettings.encodingsGroup.getValue()])
- if newScreen:
- self.__resetSubsScreen(newSubsScreen=True)
- self.__subsEngine.reset()
- if self.__loaded:
- if self.loadSubs(subsPath, newService=False):
- self.__subsEngine.refresh()
- else:
- if self.loadSubs(subsPath, newService=False):
- self.__subsEngine.resume()
- if not self.__alreadyPausedVideo and isinstance(self, InfoBarSeek):
- print '[SubsSupport] unpausing video'
- del self.__alreadyPausedVideo
- self.setSeekState(InfoBarSeek.SEEK_STATE_PLAY)
-
-
- def __processSubs(self, subsPath, subsEnc):
- showMessages = self.__showGUIInfoMessages and not (self.__firstStart and self.__subclassOfInfobarBase)
- try:
- return self.__subsLoader.load(subsPath, subsEnc, getFps(self.session))
- except LoadError:
- if showMessages:
- warningMessage(self.session, _("Cannot load subtitles. Invalid path"))
- return None, None
- except DecodeError:
- if showMessages:
- warningMessage(self.session, _("Cannot decode subtitles. Try another encoding group"))
- return None, None
- except ParserNotFoundError:
- if showMessages:
- warningMessage(self.session, _("Cannot parse subtitles. Not supported subtitles format"))
- return None, None
- except ParseError:
- if showMessages:
- warningMessage(self.session, _("Cannot parse subtitles. Invalid subtitles format"))
- return None, None
- finally:
- self.__firstStart = False
-
- def __updateSubs(self):
- if self.__loaded:
- self.resumeSubs()
- return
-
- subsPath = self.getSubsFileFromSref()
- if subsPath is not None:
- if self.loadSubs(subsPath):
- self.resumeSubs()
- self.__working = False
-
- def __afterWork(self, fnc):
- def checkWorking():
- if self.__working:
- print 'check working..'
- self.__checkTimer.start(200, True)
- else:
- self.__checkTimer.stop()
- fnc()
-
- self.__checkTimer.stop()
- self.__starTimer.stop()
-
- if self.__working:
- del self.__checkTimer.callback[:]
- self.__checkTimer.callback.append(checkWorking)
- self.__checkTimer.start(200, True)
- else:
- fnc()
-
-
- ############ Methods triggered by videoEvents when SubsSupport is subclass of Screen ################
- def __serviceStarted(self):
- print '[SubsSupport] Service Started'
- def startSubs():
- self.__starTimer.start(self.__startDelay, True)
-
- self.__isServiceSet = True
- # subtitles are loading or already loaded
- if self.__working or self.__loaded:
- self.__afterWork(startSubs)
- else:
- self.resetSubs(True)
- if self.__subsPath is None and self.__autoLoad:
- startSubs()
-
- def __serviceStopped(self):
- self.resetSubs(True)
- self.__isServiceSet = False
-
- def __seekableStatusChanged(self):
- if not hasattr(self, 'seekstate'):
- return
- if self.seekstate == self.SEEK_STATE_PLAY:
- self.pauseSubs()
- elif self.seekstate == self.SEEK_STATE_PAUSE:
- self.resumeSubs()
- elif self.seekstate == self.SEEK_STATE_EOF:
- self.resetSubs(True)
-
- ########### Methods which extends InfobarSeek seek methods
-
- def doSeekRelative(self, pts):
- if self.__loaded:
- # self.__subsEngine.preSeek(pts)
- super(SubsSupport, self).doSeekRelative(pts)
- self.playAfterSeek()
- else:
- super(SubsSupport, self).doSeekRelative(pts)
- def doSeek(self, pts):
- if self.__loaded:
- super(SubsSupport, self).doSeek(pts)
- self.playAfterSeek()
- else:
- super(SubsSupport, self).doSeek(pts)
-
- ############################################################
-
- class SubsEmbeddedScreen(Screen):
-
- """
- Pli defaults
- <fonts>
- <font filename="nmsbd.ttf" name="Subs" scale="100" />
- </fonts>
- <subtitles>
- <sub name="Subtitle_TTX" font="Subs;34" borderColor="#000000" borderWidth="3" />
- <sub name="Subtitle_Regular" font="Subs;34" foregroundColor="#ffffff" borderColor="#000000" borderWidth="3" />
- <sub name="Subtitle_Bold" font="Subs;34" foregroundColor="#ffffff" borderColor="#000000" borderWidth="3" />
- <sub name="Subtitle_Italic" font="Subs;34" foregroundColor="#ffffff" borderColor="#000000" borderWidth="3" />
- </subtitles>
- """
-
- def __init__(self, session, embeddedSettings):
- desktop = getDesktop(0)
- size = desktop.size()
- vSizeOrig = size.height()
- hSizeOrig = size.width()
- if QuickSubtitlesConfigMenu:
- vPosition = 0
- vSize = vSizeOrig
- else:
- vPositionPercent = int(embeddedSettings.position.value)
- fontSize = int(getEmbeddedFontSizeCfg(embeddedSettings.font.size).value)
- vSize = fontSize * 4 + 10
- vPosition = int(vPositionPercent * float((vSizeOrig - vSize) / 100))
- vPosition = vPosition if vPosition > 0 else 0
- vSize = vSizeOrig - vPosition
- self.skin = """<screen position="0,%s" size="%s,%s" zPosition="-1" backgroundColor="transparent" flags="wfNoBorder" />""" % (vPosition, hSizeOrig, vSize)
- Screen.__init__(self, session)
-
-
- class SubtitlesWidget(GUIComponent):
- STATE_NO_BACKGROUND, STATE_BACKGROUND = range(2)
-
- def __init__(self, boundDynamic=True, boundXOffset=10, boundYOffset=10, boundSize=None, fontSize=25, positionPercent=94):
- GUIComponent.__init__(self)
- self.state = self.STATE_BACKGROUND
- self.boundDynamic = boundDynamic
- self.boundXOffset = boundXOffset
- self.boundYOffset = boundYOffset
- self.font = (gFont("Regular", fontSize), fontSize)
- self.positionPercent = positionPercent
- desktopSize = getDesktop(0).size()
- self.desktopSize = (desktopSize.width(), desktopSize.height())
- self.boundSize = boundSize or (self.desktopSize[0], self.calcWidgetHeight())
-
- def GUIcreate(self, parent):
- self.instance = eLabel(parent)
- self.instance2 = eLabel(parent)
- self.postWidgetCreate()
-
- def GUIdelete(self):
- self.preWidgetRemove()
- self.instance = None
- self.instance2 = None
-
- def postWidgetCreate(self):
- self.instance2.hide()
- self.update()
-
- def preWidgetRemove(self):
- pass
-
- def calcWidgetYPosition(self):
- return int((self.desktopSize[1] - self.calcWidgetHeight() - self.boundYOffset) / float(100) * self.positionPercent)
-
- def calcWidgetHeight(self):
- return int(4 * self.font[1] + 15)
-
- def update(self):
- ds = self.desktopSize
- bs = self.boundSize = (self.desktopSize[0], self.calcWidgetHeight())
- self.instance2.resize(eSize(int(ds[0]), int(bs[1])))
- self.instance2.move(ePoint(int(0), int(self.calcWidgetYPosition())))
- self.instance2.setHAlign(self.instance2.alignCenter)
- self.instance2.setVAlign(self.instance2.alignCenter)
- self.instance2.setFont(self.font[0])
- self.instance2.setTransparent(True)
- if not self.boundDynamic:
- self.instance.resize(eSize(int(bs[0]), int(bs[1])))
- self.instance.move(ePoint(int(ds[0] / 2 - bs[0] / 2), int(self.calcWidgetYPosition())))
- self.instance.setFont(self.font[0])
- self.instance.setHAlign(self.instance.alignCenter)
- self.instance.setVAlign(self.instance.alignCenter)
-
- def setText(self, text):
- if self.instance and self.instance2:
- if self.state == self.STATE_NO_BACKGROUND:
- self.instance.hide()
- self.instance2.setText(text)
- self.instance2.show()
- elif self.state == self.STATE_BACKGROUND:
- self.instance2.hide()
- if not text:
- self.instance.hide()
- return
- if self.boundDynamic:
- # hack so empty spaces are part of calculateSize calculation
- self.instance2.setText(text.replace(' ','.'))
- ds = self.desktopSize
- bs = self.boundSize
- ws = self.instance2.calculateSize()
- ws = (ws.width() + self.boundXOffset * 2, ws.height() + self.boundYOffset * 2)
- wp = self.instance2.position()
- wp = (wp.x(), wp.y())
- wpy = wp[1] + (bs[1] - ws[1]) / 2
- wpx = ds[0] / 2 - ws[0] / 2
- self.instance.resize(eSize(int(ws[0]), int(ws[1])))
- self.instance.move(ePoint(int(wpx), int(wpy)))
- else:
- bs = self.boundSize
- ds = self.desktopSize
- self.instance.resize(eSize(int(bs[0]), int(bs[1])))
- self.instance.move(ePoint(int(ds[0] / 2 - bs[0] / 2), int(self.calcWidgetYPosition())))
- self.instance.setHAlign(self.instance.alignCenter)
- self.instance.setVAlign(self.instance.alignCenter)
- self.instance.setText(text)
- self.instance.show()
-
- def setPosition(self, percent):
- self.positionPercent = percent
- self.update()
-
- def setBoundDynamic(self, value):
- self.boundDynamic = value
- self.update()
-
- def setBoundOffset(self, offsetX, offsetY):
- self.boundXOffset = int(offsetX)
- self.boundYOffset = int(offsetY)
- self.update()
-
- def setForegroundColor(self, color):
- self.instance.setForegroundColor(parseColor(color))
- self.instance2.setForegroundColor(parseColor(color))
-
- def setBackgroundColor(self, color):
- if color[1:3] == "ff":
- self.state = self.STATE_NO_BACKGROUND
- else:
- self.state = self.STATE_BACKGROUND
- self.instance.setBackgroundColor(parseColor(color))
-
- def setBorderColor(self, color):
- self.instance.setBorderColor(parseColor(color))
- self.instance2.setBorderColor(parseColor(color))
-
- def setBorderWidth(self, width):
- self.instance.setBorderWidth(int(width))
- self.instance2.setBorderWidth(int(width))
-
- def setShadowColor(self, color):
- self.instance.setShadowColor(parseColor(color))
- self.instance2.setShadowColor(parseColor(color))
-
- def setShadowOffset(self, offset, scale):
- self.instance.setShadowOffset(parsePosition(offset, scale))
- self.instance2.setShadowOffset(parsePosition(offset, scale))
-
- def setFont(self, font):
- if self.font[1] == font[1]:
- self.font = font
- self.instance.setFont(font[0])
- self.instance2.setFont(font[0])
- else:
- self.font = font
- self.update()
-
- class SubsScreen(Screen):
- def __init__(self, session, externalSettings):
- self.subShown = False
- self.__shadowType = 'border'
- self.__eLabelHasBorderParams = False
- self.externalSettings = externalSettings
- fontSize = int(externalSettings.font.size.getValue())
- self.font = {
- "regular":{
- 'gfont':(gFont(externalSettings.font.regular.type.value, fontSize), fontSize),
- 'color':externalSettings.font.regular.alpha.value + externalSettings.font.regular.color.value
- },
- "italic":{
- 'gfont':(gFont(externalSettings.font.italic.type.value, fontSize), fontSize),
- 'color':externalSettings.font.italic.alpha.value + externalSettings.font.italic.color.value
- },
- "bold":{
- 'gfont':(gFont(externalSettings.font.bold.type.value, fontSize), fontSize),
- 'color':externalSettings.font.bold.alpha.value + externalSettings.font.bold.type.value
- }
- }
- self.selectedFont = "regular"
- self.currentColor = externalSettings.font.regular.color.value
- self.skin = """
- <screen position="0,0" size="%d,%d" zPosition="-1" backgroundColor="transparent" flags="wfNoBorder">
- <widget name="subtitles" />
- </screen>""" % (getDesktop(0).size().width(), getDesktop(0).size().height())
-
- Screen.__init__(self, session)
- self.stand_alone = True
- self["subtitles"] = SubtitlesWidget()
- self.onLayoutFinish.append(self.__checkElabelCaps)
- self.onLayoutFinish.append(self.reloadSettings)
-
- def __checkElabelCaps(self):
- if hasattr(self["subtitles"].instance, 'setBorderWidth') and hasattr(self["subtitles"].instance, 'setBorderColor'):
- self.__eLabelHasBorderParams = True
- elif self.__shadowType == 'border':
- self.__shadowType = 'offset'
-
- def setShadowType(self, type):
- if type == 'border' and self.__eLabelHasBorderParams:
- self.__shadowType = 'border'
- else:
- self.__shadowType = 'offset'
-
- def setShadow(self, type, color, size=None, xOffset=None, yOffset=None):
- self.setShadowType(type)
- if self.__shadowType == 'border':
- self["subtitles"].setBorderColor("#" + color)
- elif self.__shadowType == 'offset':
- self["subtitles"].setShadowColor("#" + color)
- if self.__shadowType == 'border' and size is not None:
- self["subtitles"].setBorderWidth(size)
- elif self.__shadowType == 'offset' and (xOffset is not None and yOffset is not None):
- self["subtitles"].setShadowOffset(str(-xOffset) + ',' + str(-yOffset), self.scale)
-
- def setBackground(self, type, alpha, color, xOffset=None, yOffset=None):
- if type == 'dynamic':
- self["subtitles"].setBoundDynamic(True)
- self["subtitles"].setBoundOffset(xOffset, yOffset)
- else:
- self["subtitles"].setBoundDynamic(False)
- color = "#" + alpha + color
- self["subtitles"].setBackgroundColor(color)
-
- def setColor(self, color):
- self.currentColor = color
- color = "#" + color
- self["subtitles"].setForegroundColor(color)
-
- def setPosition(self, position):
- self["subtitles"].setPosition(position)
-
- def setFonts(self, font):
- self.font = font
- self['subtitles'].setFont(self.font['regular']['gfont'])
-
- def reloadSettings(self):
- shadowType = self.externalSettings.shadow.type.getValue()
- shadowColor = self.externalSettings.shadow.color.getValue()
- shadowSize = int(self.externalSettings.shadow.size.getValue())
- shadowXOffset = int(self.externalSettings.shadow.xOffset.getValue())
- shadowYOffset = int(self.externalSettings.shadow.yOffset.getValue())
- shadowEnabled = int(self.externalSettings.shadow.enabled.getValue())
- if not shadowEnabled:
- shadowXOffset = shadowYOffset = shadowSize = 0
- backgroundType = self.externalSettings.background.type.getValue()
- backgroundAlpha = self.externalSettings.background.alpha.getValue()
- backgroundColor = self.externalSettings.background.color.getValue()
- backgroundXOffset = self.externalSettings.background.xOffset.getValue()
- backgroundYOffset = self.externalSettings.background.yOffset.getValue()
- backgroundEnabled = self.externalSettings.background.enabled.getValue()
- if not backgroundEnabled:
- backgroundAlpha = "ff"
- backgroundColor = "ffffff"
- fontSize = int(self.externalSettings.font.size.getValue())
- position = int(self.externalSettings.position.getValue())
-
- self.setPosition(position)
- self.setShadow(shadowType, shadowColor, shadowSize, shadowXOffset, shadowYOffset)
- self.setBackground(backgroundType, backgroundAlpha, backgroundColor, backgroundXOffset, backgroundYOffset)
- externalSettings = self.externalSettings
- self.setFonts({
- "regular":{
- 'gfont':(gFont(externalSettings.font.regular.type.value, fontSize), fontSize),
- 'color':externalSettings.font.regular.alpha.value + externalSettings.font.regular.color.value
- },
- "italic":{
- 'gfont':(gFont(externalSettings.font.italic.type.value, fontSize), fontSize),
- 'color':externalSettings.font.italic.alpha.value + externalSettings.font.italic.color.value
- },
- "bold":{
- 'gfont':(gFont(externalSettings.font.bold.type.value, fontSize), fontSize),
- 'color':externalSettings.font.bold.alpha.value + externalSettings.font.bold.color.value
- }
- })
-
- def setSubtitle(self, sub):
- if sub['style'] != self.selectedFont:
- self.selectedFont = sub['style']
- self['subtitles'].setFont(self.font[sub['style']]['gfont'])
- color = sub['color']
- if color == "default":
- color = self.font[sub['style']]['color']
- self.setColor(color)
- self["subtitles"].setText(toString(sub['text']))
- self.subShown = True
-
- def hideSubtitle(self):
- if self.subShown:
- self["subtitles"].setText("")
- self.subShown = False
-
- class SubsEngine(object):
- def __init__(self, session, engineSettings, renderer):
- self.session = session
- self.engineSettings = engineSettings
- self.renderer = renderer
- self.subsList = None
- self.position = 0
- self.sub = None
- self.subsFpsRatio = 1
- self.onSubsFpsChanged = []
- self.subsDelay = 0
- self.onSubsDelayChanged = []
- self.playerDelay = 0
- self.syncDelay = 300
- self.hideInterval = 200 * 90
- self.__seek = None
- self.__pts = None
- self.__ptsDelay = None
- self.__callbackPts = None
- self.preDoPlay = [self.updateSubPosition]
- self.refreshTimer = eTimer()
- self.refreshTimer.callback.append(self.play)
- self.refreshTimerDelay = 1000
- self.hideTimer = eTimer()
- self.hideTimer.callback.append(self.checkHideSub)
- self.hideTimer.callback.append(self.incSubPosition)
- self.hideTimer.callback.append(self.doPlay)
- self.getPlayPtsTimer = eTimer()
- self.getPlayPtsTimer.callback.append(self.getPts)
- self.getPlayPtsTimer.callback.append(self.validPts)
- self.getPlayPtsTimer.callback.append(self.callbackPts)
- self.getPlayPtsTimerDelay = 200
- self.resume = self.play
- self.addNotifiers()
-
- def addNotifiers(self):
- def hideInterval(configElement):
- self.hideInterval = int(configElement.value) * 90
- def playerDelay(configElement):
- self.playerDelay = int(configElement.value) * 90
- def syncDelay(configElement):
- self.syncDelay = int(configElement.value)
- def getPlayPtsTimerDelay(configElement):
- self.getPlayPtsTimerDelay = int(configElement.value)
- def refreshTimerDelay(configElement):
- self.refreshTimerDelay = int(configElement.value)
-
- self.engineSettings.expert.hideDelay.addNotifier(hideInterval)
- self.engineSettings.expert.playerDelay.addNotifier(playerDelay)
- self.engineSettings.expert.syncDelay.addNotifier(syncDelay)
- self.engineSettings.expert.ptsDelayCheck.addNotifier(getPlayPtsTimerDelay)
- self.engineSettings.expert.refreshDelay.addNotifier(refreshTimerDelay)
-
- def removeNotifiers(self):
- del self.engineSettings.expert.hideDelay.notifiers[:]
- del self.engineSettings.expert.playerDelay.notifiers[:]
- del self.engineSettings.expert.syncDelay.notifiers[:]
- del self.engineSettings.expert.ptsDelayCheck.notifiers[:]
- del self.engineSettings.expert.refreshDelay.notifiers[:]
-
- def getPlayPts(self, callback, delay=None):
- self.getPlayPtsTimer.stop()
- self.__callbackPts = callback
- self.__ptsDelay = delay
- self.__pts = None
- if delay is None:
- delay = 1
- self.getPlayPtsTimer.start(delay, True)
-
- def getPts(self):
- try:
- if not self.__seek:
- service = self.session.nav.getCurrentService()
- self.__seek = service.seek()
- except Exception:
- return
- r = self.__seek.getPlayPosition()
- if r[0]:
- self.__pts = None
- else:
- self.__pts = long(r[1]) + self.playerDelay
-
- def validPts(self):
- pass
-
- def callbackPts(self):
- if self.__pts is not None:
- self.getPlayPtsTimer.stop()
- self.__callbackPts()
- else:
- delay = self.getPlayPtsTimerDelay
- if self.__ptsDelay is not None:
- delay = self.__ptsDelay
- self.getPlayPtsTimer.start(delay)
-
- def setSubsList(self, subslist):
- self.subsList = subslist
-
- def setRenderer(self, renderer):
- self.renderer = renderer
-
- def setPlayerDelay(self, playerDelay):
- self.pause()
- self.playerDelay = playerDelay * 90
- self.resume()
-
- def setSubsFps(self, subsFps):
- print "[SubsEngine] setSubsFps - setting fps to %s"% str(subsFps)
- videoFps = getFps(self.session, True)
- if videoFps is None:
- print "[SubsEngine] setSubsFps - cannot get video fps!"
- else:
- self.pause()
- self.subsFpsRatio = subsFps/ float(videoFps)
- for f in self.onSubsFpsChanged:
- f(self.getSubsFps())
- self.resume()
-
- def getSubsFps(self):
- videoFps = getFps(self.session, True)
- if videoFps is None:
- return None
- return fps_float(self.subsFpsRatio * videoFps)
-
- def setSubsDelay(self, delayInMs):
- print "[SubsEngine] setSubsDelay - setting delay to %sms"% str(delayInMs)
- self.pause()
- self.subsDelay = int(delayInMs) * 90
- for f in self.onSubsDelayChanged:
- f(self.getSubsDelay())
- self.resume()
-
- def getSubsDelay(self):
- return self.subsDelay / 90
-
- def getSubsPosition(self):
- return self.position
-
- def setSubsDelayToNextSubtitle(self):
- def setDelay():
- if not self.renderer.subShown:
- print '[SubsEngine] setDelayToNextSubtitle - next pos: %d of %d'%(self.position, len(self.subsList))
- toSub = self.subsList[self.position]
- # position is incremented right after subtitle is hidden so we don't do anything
- elif self.renderer.subShown and self.position != len(self.subsList) -1:
- print '[SubsEngine] setDelayToNextSubtitle - next pos: %d of %d'%(self.position+1, len(self.subsList))
- toSub = self.subsList[self.position+1]
- else:
- print '[SubsEngine] setDelayToNextSubtitle - we are on last subtitle'
- return
- toSubDelay = (self.__pts - (toSub['start'] * self.subsFpsRatio))/90
- self.setSubsDelay(toSubDelay)
-
- self.stopTimers()
- self.getPlayPts(setDelay)
-
- def setSubsDelayToPrevSubtitle(self):
- def setDelay():
- if not self.renderer.subShown:
- print '[SubsEngine] setDelayToPrevSubtitle - skipping to start of current sub'
- # position is incremented right after subtitle is hidden so we have to go one back
- toSub = self.subsList[self.position-1]
- elif self.renderer.subShown and self.position != 0:
- print '[SubsEngine] setDelayToPrevSubtitle - prev pos: %d of %d'%(self.position-1, len(self.subsList))
- toSub = self.subsList[self.position -1]
- else:
- print '[SubsEngine] setDelayToPrevSubtitle - we are on first subtitle'
- return
- toSubDelay = (self.__pts - (toSub['start'] * self.subsFpsRatio))/90
- self.setSubsDelay(toSubDelay)
-
- self.stopTimers()
- self.getPlayPts(setDelay)
-
- def reset(self, position=True):
- self.stopTimers()
- self.hideSub()
- if position:
- self.position = 0
- self.__seek = None
- self.__pts = None
- self.__callbackPts = None
- self.sub = None
- self.subsDelay = 0
- self.subsFpsRatio = 1
-
- def refresh(self):
- self.stopTimers()
- self.hideSub()
- self.refreshTimer.start(self.refreshTimerDelay, True)
-
- def pause(self):
- self.stopTimers()
- self.hideSub()
-
- def play(self):
- self.stopTimers()
- self.hideSub()
- self.getPlayPts(self.prePlay)
-
- def sync(self):
- self._oldPts = None
- def checkPts():
- if self._oldPts is None:
- self._oldPts = self.__pts
- self.getPlayPts(checkPts, self.syncDelay)
- # video is frozen no progress made
- elif self._oldPts == self.__pts:
- self._oldPts = None
- self.getPlayPts(checkPts, self.syncDelay)
- # abnormal pts
- elif (self.__pts > self._oldPts + self.syncDelay * 90 + (200 * 90)) or (
- self.__pts < self._oldPts + self.syncDelay * 90 - (200 * 90)):
- self._oldPts = None
- self.getPlayPts(checkPts, self.syncDelay)
- # normal playback
- else:
- del self._oldPts
- self.updateSubPosition()
- self.doPlay()
- self.stopTimers()
- self.hideSub()
- self.getPlayPts(checkPts, self.syncDelay)
-
- def prePlay(self):
- for f in self.preDoPlay:
- f()
- self.doPlay()
-
- def doPlay(self):
- if self.position == len(self.subsList):
- print '[SubsEngine] reached end of subtitle list'
- self.position = len(self.subsList) - 1
- self.stopTimers()
- else:
- self.sub = self.subsList[self.position]
- self.getPlayPts(self.doWait)
-
- def doWait(self):
- subStartPts = int(self.sub['start'] * self.subsFpsRatio) + self.subsDelay
- if self.__pts < subStartPts:
- diffPts = subStartPts - self.__pts
- diffMs = diffPts / 90
- if diffMs > 50:
- self.getPlayPts(self.doWait, diffMs)
- else:
- print '[SubsEngine] sub shown sooner by %dms' % diffMs
- self.renderSub()
- else:
- subsEndPts = (self.sub['end'] * self.subsFpsRatio) + self.subsDelay
- if subsEndPts - self.__pts < 0:
- #print '[SubsEngine] sub should be already shown - %dms, skipping...'%((subsEndPts - self.__pts)/90)
- self.getPlayPts(self.skipSubs, 100)
- else:
- print '[SubsEngine] sub shown later by %dms' % ((self.__pts - subStartPts)/90)
- self.renderSub()
-
- def skipSubs(self):
- if self.position == len(self.subsList) - 1:
- self.incSubPosition()
- else:
- self.updateSubPosition()
- self.doPlay()
-
- def renderSub(self):
- duration = int(self.sub['duration'] * self.subsFpsRatio)
- self.renderer.setSubtitle(self.sub)
- self.hideTimer.start(duration, True)
-
- def checkHideSub(self):
- if self.subsList[-1] == self.sub:
- self.hideSub()
- elif (self.subsList[self.position]['end'] * self.subsFpsRatio) + self.hideInterval < (self.subsList[self.position + 1]['start'] * self.subsFpsRatio):
- self.hideSub()
-
- def hideSub(self):
- self.renderer.hideSubtitle()
-
- def incSubPosition(self):
- self.position += 1
-
- def updateSubPosition(self):
- playPts = self.__pts
- print '[SubsEngine] pre-update sub position:', self.position
- subStartPts = (self.subsList[self.position]['start'] * self.subsFpsRatio) + self.subsDelay
- subStartEndPts = (self.subsList[self.position]['end'] * self.subsFpsRatio) + self.subsDelay
- # seek backwards
- if subStartPts > playPts:
- subPrevEndPts = (self.subsList[self.position -1]['end'] * self.subsFpsRatio) + self.subsDelay
- while self.position > 0 and subPrevEndPts > playPts:
- self.position -= 1
- subPrevEndPts = (self.subsList[self.position - 1]['end'] * self.subsFpsRatio) + self.subsDelay
- # seek forward
- elif subStartPts < playPts and subStartEndPts < playPts:
- while self.position < len(self.subsList) - 1 and subStartPts < playPts and subStartEndPts < playPts:
- self.position += 1
- subStartPts = (self.subsList[self.position]['start'] * self.subsFpsRatio) + self.subsDelay
- subStartEndPts = (self.subsList[self.position]['end'] * self.subsFpsRatio) + self.subsDelay
- print '[SubsEngine] post-update sub position:', self.position
-
- def showDialog(self):
- self.renderer.show()
-
- def hideSubtitlesDialog(self):
- self.renderer.hide()
-
- def stopTimers(self):
- if self.refreshTimer is not None:
- self.refreshTimer.stop()
- if self.getPlayPtsTimer is not None:
- self.getPlayPtsTimer.stop()
- if self.hideTimer is not None:
- self.hideTimer.stop()
-
- def exit(self):
- self.hideTimer = None
- self.refreshTimer = None
- self.getPlayPtsTimer = None
- del self.onSubsDelayChanged[:]
- del self.onSubsFpsChanged[:]
- self.removeNotifiers()
-
-
- class PanelList(MenuList):
- def __init__(self, list, height=30):
- MenuList.__init__(self, list, False, eListboxPythonMultiContent)
- self.l.setItemHeight(height)
- self.l.setFont(0, gFont("Regular", 20))
- self.l.setFont(1, gFont("Regular", 17))
-
- def PanelListEntry(name, mode):
- res = [(name, mode)]
- res.append(MultiContentEntryText(pos=(5, 5), size=(330, 25), font=0, flags=RT_VALIGN_CENTER, text=name))
- return res
-
- def PanelColorListEntry(name, value, colorName, colorValue, sizePanelX):
- res = [(name)]
- res.append(MultiContentEntryText(pos=(0, 5), size=(sizePanelX, 30), font=1, flags=RT_HALIGN_LEFT, text=name, color=colorName))
- res.append(MultiContentEntryText(pos=(0, 5), size=(sizePanelX, 30), font=1, flags=RT_HALIGN_RIGHT, text=value, color=colorValue))
- return res
-
- class SubsMenu(Screen):
- skin = """
- <screen position="center,center" size="500,400" zPosition="1" >
- <widget name="title_label" position="0,5" size="500,35" valign="center" halign="center" font="Regular;25" transparent="1" foregroundColor="white" />
- <widget name="subfile_label" position="0,50" size="500,50" valign="center" halign="center" font="Regular;22" transparent="1" foregroundColor="#DAA520" />
- <widget name="subfile_list" position="center,100" size="300,30" transparent="1" />
- <eLabel position="5,135" size="490,1" backgroundColor="#999999" />
- <widget name="menu_list" position="0,140" size="500,235" transparent="1" scrollbarMode="showOnDemand" />
- <widget name="copyright" position="10,375" size="480,20" valign="center" halign="center" font="Regular;15" transparent="1" foregroundColor="white" />
- </screen>"""
-
- def __init__(self, session, infobar, subfile=None, subdir=None, encoding=None, embeddedSupport=False, embeddedEnabled=False, searchSupport=False):
- Screen.__init__(self, session)
- self.infobar = infobar
- self.subfile = subfile
- self.subdir = subdir
- self.encoding = encoding
- self.embeddedSupport = embeddedSupport
- self.embeddedEnabled = embeddedEnabled
- self.searchSupport = searchSupport
- self.embeddedSubtitle = None
- self.newSelection = False
- self.changeEncoding = False
- self.changedEncodingGroup = False
- self.changedShadowType = False
- self.changedSettings = False
- self.reloadEmbeddedScreen = False
- self.turnOff = False
- self.forceReload = False
-
- self["title_label"] = Label(_("Currently choosed subtitles"))
- self["subfile_label"] = Label("")
- self["subfile_list"] = PanelList([], 25)
- self["menu_list"] = PanelList([], 28)
- self["copyright"] = Label("")
- # self["copyright"] = Label("created by %s <%s>"%(__author__,__email__))
- self["actions"] = ActionMap(["SetupActions", "DirectionActions"],
- {
- "ok": self.ok,
- "cancel": self.cancel,
- }, -2)
-
- self.onLayoutFinish.append(self.initTitle)
- self.onLayoutFinish.append(self.initGUI)
- self.onLayoutFinish.append(self.disableSelection)
-
- def disableSelection(self):
- self["subfile_list"].selectionEnabled(False)
-
- def initTitle(self):
- self.setTitle("SubsSupport %s" % __version__)
-
- def initGUI(self):
- self.initSubInfo()
- self.initMenu()
-
- def initSubInfo(self):
- subInfo = []
- if self.embeddedEnabled or self.embeddedSubtitle:
- self["subfile_label"].setText(_("Embedded Subtitles"))
- self["subfile_label"].instance.setForegroundColor(parseColor("#ffff00"))
- elif self.subfile is not None:
- self["subfile_label"].setText(toString(os.path.split(self.subfile)[1]))
- self["subfile_label"].instance.setForegroundColor(parseColor("#DAA520"))
-
- if self.newSelection:
- pass
- # subInfo.append(PanelColorListEntry(_("State:"),_("not loaded"), 0xDAA520, 0xffff00, 300))
- elif self.encoding and not self.newSelection:
- # subInfo.append(PanelColorListEntry(_("State:"),_("loaded"), 0xDAA520, 0x00ff00, 300))
- subInfo.append(PanelColorListEntry(_("Encoding:"), self.encoding, 0xDAA520, 0xffffff, 300))
- elif not self.encoding and not self.newSelection:
- # subInfo.append(PanelColorListEntry(_("State:"),_("not loaded"), 0xDAA520, 0xffff00, 300))
- subInfo.append(PanelColorListEntry(_("Encoding:"), _("cannot decode"), 0xDAA520, 0xffffff, 300))
- else:
- self["subfile_label"].setText(_("None"))
- self["subfile_label"].instance.setForegroundColor(parseColor("#DAA520"))
- self["subfile_list"].setList(subInfo)
-
- def initMenu(self):
- self.menu = [(_('Choose subtitles'), 'choose')]
- if self.searchSupport:
- self.menu.append((_("Search subtitles"), 'search'))
- if not self.embeddedEnabled:
- if self.subfile is not None and not self.newSelection:
- self.menu.append((_('Change encoding'), 'encoding'))
- self.menu.append((_('Subtitles settings'), 'settings'))
- if self.embeddedEnabled and QuickSubtitlesConfigMenu:
- self.menu.append((_('Subtitles settings (embedded)'), 'settings_embedded_pli'))
- if self.embeddedEnabled and not QuickSubtitlesConfigMenu:
- self.menu.append((_('Subtitles settings (embedded)'), 'settings_embedded'))
- if self.subfile is not None or self.embeddedEnabled:
- self.menu.append((_('Turn off subtitles'), 'subsoff'))
- list = [PanelListEntry(x, y) for x, y in self.menu]
- self["menu_list"].setList(list)
-
- def ok(self):
- mode = self["menu_list"].getCurrent()[0][1]
- if mode == 'choose':
- self.session.openWithCallback(self.subsChooserCB, SubsChooser, self.infobar.subsSettings, self.subdir, self.embeddedSupport, False, True)
- elif mode =='search':
- self.searchSubs()
- elif mode == 'settings':
- self.session.openWithCallback(self.subsSetupCB, SubsSetupMainMisc, self.infobar.subsSettings)
- elif mode == 'settings_embedded':
- self.session.openWithCallback(self.subsSetupEmbeddedCB, SubsSetupEmbedded, self.infobar.subsSettings.embedded)
- elif mode == 'settings_embedded_pli':
- self.session.open(QuickSubtitlesConfigMenu, self.infobar)
- elif mode == 'encoding':
- self.changeEncoding = True
- self.cancel()
- elif mode == 'subsoff':
- self.turnOff = True
- self.cancel()
-
- def getSearchTitleList(self, sName, sPath):
- searchTitles = []
- if sName:
- searchTitles.append(sName)
- if sPath:
- dirname = os.path.basename(os.path.dirname(sPath))
- dirnameFix = dirname.replace('.', ' ').replace('_', ' ').replace('-', ' ')
- filename = os.path.splitext(os.path.basename(sPath))[0]
- filenameFix = filename.replace('.', ' ').replace('_', ' ').replace('-', ' ')
- if filename not in searchTitles:
- searchTitles.append(filename)
- if filenameFix not in searchTitles:
- searchTitles.append(filenameFix)
- if dirname not in searchTitles:
- searchTitles.append(dirname)
- if dirnameFix not in searchTitles:
- searchTitles.append(dirnameFix)
- return searchTitles
-
- def searchSubs(self):
- def checkDownloadedSubsSelection(downloadedSubtitle=None):
- if downloadedSubtitle:
- self.subsChooserCB(downloadedSubtitle, False, True)
-
- def paramsDialogCB(callback=None):
- if callback:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, sPath, titleList, resetSearchParams=False)
-
- def showProvidersErrorCB(callback):
- if not callback:
- subsSettings.search.showProvidersErrorMessage.value = False
- if subsSettings.search.openParamsDialogOnSearch.value:
- self.session.openWithCallback(paramsDialogCB, SubsSearchParamsMenu, seeker, subsSettings.search, titleList, enabledList=False)
- else:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, sPath, titleList)
-
- if self.searchSupport:
- ref = self.session.nav.getCurrentlyPlayingServiceReference()
- try:
- sPath = ref.getPath()
- except Exception:
- sPath = None
- try:
- sName = ref.getName()
- except Exception:
- sName = None
- titleList = self.getSearchTitleList(sName, sPath)
- subsSettings = self.infobar.subsSettings
- seeker = E2SubsSeeker(self.session, subsSettings.search, debug=True)
-
- if seeker.providers_error and subsSettings.search.showProvidersErrorMessage.value:
- msg = _("Some subtitles providers are not working") + ".\n"
- msg += _("For more details please check search settings") + "."
- msg += "\n\n"
- msg += _("Do you want to show this message again?")
- self.session.openWithCallback(showProvidersErrorCB, MessageBox, msg, type=MessageBox.TYPE_YESNO)
-
- elif subsSettings.search.openParamsDialogOnSearch.value:
- self.session.openWithCallback(paramsDialogCB, SubsSearchParamsMenu, seeker, subsSettings.search, titleList, enabledList=False)
- else:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, sPath, titleList)
-
- def subsChooserCB(self, subfile=None, embeddedSubtitle=None, forceReload=False):
- if subfile is not None and self.subfile != subfile:
- self.subfile = subfile
- self.subdir = os.path.dirname(self.subfile)
- self.newSelection = True
- self.embeddedEnabled = False
- self.cancel()
- elif subfile is not None and self.subfile == subfile and forceReload:
- self.forceReload = True
- self.cancel()
- elif embeddedSubtitle and embeddedSubtitle != self.infobar.selected_subtitle:
- self.embeddedSubtitle = embeddedSubtitle
- self.cancel()
- # self.initGUI()
-
- def subsSetupCB(self, changedSettings=False, changedEncodingGroup=False,
- changedShadowType=False):
- self.changedSettings = changedSettings
- self.changedEncodingGroup = changedEncodingGroup
- self.changedShadowType = changedShadowType
-
- def subsSetupEmbeddedCB(self, reloadEmbeddedScreen=False):
- self.reloadEmbeddedScreen = reloadEmbeddedScreen
-
- def cancel(self):
- self.close(self.subfile, self.embeddedSubtitle, self.changedSettings, self.changeEncoding,
- self.changedEncodingGroup, self.changedShadowType, self.reloadEmbeddedScreen, self.turnOff, self.forceReload)
-
- # rework
-
- class SubsSetupExternal(BaseMenuScreen):
-
- @staticmethod
- def getConfigList(externalSettings):
- configList = []
- shadowType = externalSettings.shadow.type.getValue()
- shadowEnabled = externalSettings.shadow.enabled.getValue()
- backgroundType = externalSettings.background.type.getValue()
- backgroundEnabled = externalSettings.background.enabled.getValue()
- configList.append(getConfigListEntry(_("Font type (Regular)"), externalSettings.font.regular.type))
- configList.append(getConfigListEntry(_("Font color (Regular)"), externalSettings.font.regular.color))
- configList.append(getConfigListEntry(_("Font transparency (Regular)"), externalSettings.font.regular.alpha))
- configList.append(getConfigListEntry(_("Font type (Italic)"), externalSettings.font.italic.type))
- configList.append(getConfigListEntry(_("Font color (Italic"), externalSettings.font.italic.color))
- configList.append(getConfigListEntry(_("Font transparency (Italic)"), externalSettings.font.italic.alpha))
- configList.append(getConfigListEntry(_("Font type (Bold)"), externalSettings.font.bold.type))
- configList.append(getConfigListEntry(_("Font color (Bold)"), externalSettings.font.bold.color))
- configList.append(getConfigListEntry(_("Font transparency (Bold)"), externalSettings.font.bold.alpha))
- configList.append(getConfigListEntry(_("Font size"), externalSettings.font.size))
- configList.append(getConfigListEntry(_("Position"), externalSettings.position))
- configList.append(getConfigListEntry(_("Shadow"), externalSettings.shadow.enabled))
- if shadowEnabled:
- configList.append(getConfigListEntry(_("Shadow type"), externalSettings.shadow.type))
- if shadowType == 'offset':
- configList.append(getConfigListEntry(_("Shadow X-offset"), externalSettings.shadow.xOffset))
- configList.append(getConfigListEntry(_("Shadow Y-offset"), externalSettings.shadow.yOffset))
- else:
- configList.append(getConfigListEntry(_("Shadow size"), externalSettings.shadow.size))
- configList.append(getConfigListEntry(_("Shadow color"), externalSettings.shadow.color))
- configList.append(getConfigListEntry(_("Background"), externalSettings.background.enabled))
- if backgroundEnabled:
- configList.append(getConfigListEntry(_("Background type"), externalSettings.background.type))
- if backgroundType == 'dynamic':
- configList.append(getConfigListEntry(_("Background X-offset"), externalSettings.background.xOffset))
- configList.append(getConfigListEntry(_("Background Y-offset"), externalSettings.background.yOffset))
- configList.append(getConfigListEntry(_("Background color"), externalSettings.background.color))
- configList.append(getConfigListEntry(_("Background transparency"), externalSettings.background.alpha))
- return configList
-
- def __init__(self, session, externalSettings):
- BaseMenuScreen.__init__(self, session, _("External Subtitles settings"))
- self.externalSettings = externalSettings
-
- def buildMenu(self):
- self["config"].setList(self.getConfigList(self.externalSettings))
-
- def keySave(self):
- changedShadowType = self.externalSettings.shadow.type.isChanged()
- for x in self["config"].list:
- x[1].save()
- configfile.save()
- self.close(True, changedShadowType)
-
- def keyLeft(self):
- ConfigListScreen.keyLeft(self)
- current = self["config"].getCurrent()[1]
- if current in [self.externalSettings.shadow.type,
- self.externalSettings.shadow.enabled,
- self.externalSettings.background.enabled,
- self.externalSettings.background.type]:
- self.buildMenu()
-
- def keyRight(self):
- ConfigListScreen.keyRight(self)
- current = self["config"].getCurrent()[1]
- if current in [self.externalSettings.shadow.type,
- self.externalSettings.shadow.enabled,
- self.externalSettings.background.enabled,
- self.externalSettings.background.type]:
- self.buildMenu()
-
-
- class SubsSetupMainMisc(BaseMenuScreen):
- def __init__(self, session, subsSettings):
- BaseMenuScreen.__init__(self, session, _("Subtitles setting"))
- self.subsSettings = subsSettings
- self.showExpertSettings = ConfigYesNo(default=False)
-
- def buildMenu(self):
- configList = []
- configList.append(getConfigListEntry(_("Pause video on opening subtitles menu"), self.subsSettings.pauseVideoOnSubtitlesMenu))
- configList.append(getConfigListEntry("-"*200, ConfigNothing()))
- configList.extend(SubsSetupExternal.getConfigList(self.subsSettings.external))
- configList.append(getConfigListEntry(_("Encoding"), self.subsSettings.encodingsGroup))
- configList.append(getConfigListEntry(_("Show expert settings"), self.showExpertSettings))
- if self.showExpertSettings.value:
- engineSettings = self.subsSettings.engine
- configList.append(getConfigListEntry(_("Hide delay"), engineSettings.expert.hideDelay))
- configList.append(getConfigListEntry(_("Sync delay"), engineSettings.expert.syncDelay))
- configList.append(getConfigListEntry(_("Player delay"), engineSettings.expert.playerDelay))
- configList.append(getConfigListEntry(_("Refresh delay"), engineSettings.expert.refreshDelay))
- configList.append(getConfigListEntry(_("PTS check delay"), engineSettings.expert.ptsDelayCheck))
- self["config"].setList(configList)
-
- def keySave(self):
- changedEncodingGroup = self.subsSettings.encodingsGroup.isChanged()
- changedShadowType = self.subsSettings.external.shadow.type.isChanged()
- for x in self["config"].list:
- x[1].save()
- configfile.save()
- self.close(True, changedEncodingGroup, changedShadowType)
-
- def keyLeft(self):
- ConfigListScreen.keyLeft(self)
- current = self["config"].getCurrent()[1]
- if current in [self.subsSettings.external.shadow.type,
- self.subsSettings.external.shadow.enabled,
- self.showExpertSettings,
- self.subsSettings.external.background.enabled,
- self.subsSettings.external.background.type]:
- self.buildMenu()
-
- def keyRight(self):
- ConfigListScreen.keyRight(self)
- current = self["config"].getCurrent()[1]
- if current in [self.subsSettings.external.shadow.type,
- self.subsSettings.external.shadow.enabled,
- self.showExpertSettings,
- self.subsSettings.external.background.enabled,
- self.subsSettings.external.background.type]:
- self.buildMenu()
-
- class SubsSetupEmbedded(BaseMenuScreen):
-
- @staticmethod
- def initConfig(configsubsection):
- configsubsection.position = ConfigSelection(default="94", choices=positionChoiceList)
- configsubsection.font = ConfigSubsection()
- configsubsection.font.regular = ConfigSubsection()
- configsubsection.font.regular.type = ConfigSelection(default=getDefaultFont("regular"), choices=fontChoiceList)
- configsubsection.font.italic = ConfigSubsection()
- configsubsection.font.italic.type = ConfigSelection(default=getDefaultFont("italic"), choices=fontChoiceList)
- configsubsection.font.bold = ConfigSubsection()
- configsubsection.font.bold.type = ConfigSelection(default=getDefaultFont("bold"), choices=fontChoiceList)
- configsubsection.font.size = ConfigSelection(default="34", choices=fontSizeChoiceList)
- configsubsection.color = ConfigSelection(default="ffffff", choices=colorChoiceList)
- configsubsection.shadow = ConfigSubsection()
- configsubsection.shadow.size = ConfigSelection(default="3", choices=shadowSizeChoiceList)
- configsubsection.shadow.color = ConfigSelection(default="000000", choices=colorChoiceList)
- configsubsection.shadow.xOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
- configsubsection.shadow.yOffset = ConfigSelection(default="-3", choices=shadowOffsetChoiceList)
-
- @staticmethod
- def getConfigList(embeddedSettings):
- fontSizeCfg = getEmbeddedFontSizeCfg(embeddedSettings.font.size)
- configList = []
- configList.append(getConfigListEntry(_("Font type (Regular)"), embeddedSettings.font.regular.type))
- configList.append(getConfigListEntry(_("Font type (Italic)"), embeddedSettings.font.italic.type))
- configList.append(getConfigListEntry(_("Font type (Bold)"), embeddedSettings.font.bold.type))
- configList.append(getConfigListEntry(_("Font size"), fontSizeCfg))
- configList.append(getConfigListEntry(_("Position"), embeddedSettings.position))
- configList.append(getConfigListEntry(_("Color"), embeddedSettings.color))
- configList.append(getConfigListEntry(_("Shadow X-offset"), embeddedSettings.shadow.xOffset))
- configList.append(getConfigListEntry(_("Shadow Y-offset"), embeddedSettings.shadow.yOffset))
- return configList
-
- def __init__(self, session, embeddedSettings):
- BaseMenuScreen.__init__(self, session, _("Embedded subtitles settings"))
- self.embeddedSettings = embeddedSettings
-
- def buildMenu(self):
- self["config"].setList(self.getConfigList((self.embeddedSettings)))
-
- def keySave(self):
- reloadEmbeddedScreen = (self.embeddedSettings.position.isChanged() or
- getEmbeddedFontSizeCfg(self.embeddedSettings.font.size).isChanged())
- for x in self["config"].list:
- x[1].save()
- configfile.save()
- self.close(reloadEmbeddedScreen)
-
- class SubsSetupGeneral(BaseMenuScreen):
- def __init__(self, session, generalSettings):
- BaseMenuScreen.__init__(self, session, _("General settings"))
- self.generalSettings = generalSettings
-
- def buildMenu(self):
- self["config"].setList([
- getConfigListEntry(_("Pause video on opening subtitles menu"), self.generalSettings.pauseVideoOnSubtitlesMenu),
- getConfigListEntry(_("Encoding"), self.generalSettings.encodingsGroup),
- ])
-
- def FileEntryComponent(name, absolute=None, isDir=False):
- res = [ (absolute, isDir) ]
- res.append((eListboxPythonMultiContent.TYPE_TEXT, 35, 1, 470, 20, 0, RT_HALIGN_LEFT, toString(name)))
- if isDir:
- png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "extensions/directory.png"))
- else:
- png = LoadPixmap(os.path.join(os.path.dirname(__file__), 'img', 'subtitles.png'))
- if png is not None:
- res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 10, 2, 20, 20, png))
- return res
-
-
-
- class SubFileList(FileList):
- def __init__(self, defaultDir):
- extensions = []
- for parser in PARSERS:
- extensions += list(parser.parsing)
- FileList.__init__(self, defaultDir, matchingPattern="(?i)^.*\." + '(' + '|'.join(ext[1:] for ext in extensions) + ')', useServiceRef=False)
-
- def changeDir(self, directory, select = None):
- self.list = []
-
- # if we are just entering from the list of mount points:
- if self.current_directory is None:
- if directory and self.showMountpoints:
- self.current_mountpoint = self.getMountpointLink(directory)
- else:
- self.current_mountpoint = None
- self.current_directory = directory
- directories = []
- files = []
-
- if directory is None and self.showMountpoints: # present available mountpoints
- for p in harddiskmanager.getMountedPartitions():
- path = os.path.join(p.mountpoint, "")
- if path not in self.inhibitMounts and not self.inParentDirs(path, self.inhibitDirs):
- self.list.append(FileEntryComponent(name = p.description, absolute = path, isDir = True))
- files = [ ]
- directories = [ ]
- elif directory is None:
- files = [ ]
- directories = [ ]
- elif self.useServiceRef:
- # we should not use the 'eServiceReference(string)' constructor, because it doesn't allow ':' in the directoryname
- root = eServiceReference(2, 0, directory)
- if self.additional_extensions:
- root.setName(self.additional_extensions)
- serviceHandler = eServiceCenter.getInstance()
- list = serviceHandler.list(root)
-
- while 1:
- s = list.getNext()
- if not s.valid():
- del list
- break
- if s.flags & s.mustDescent:
- directories.append(s.getPath())
- else:
- files.append(s)
- directories.sort()
- files.sort()
- else:
- if fileExists(directory):
- try:
- files = os.listdir(directory)
- except:
- files = []
- files.sort()
- tmpfiles = files[:]
- for x in tmpfiles:
- if os.path.isdir(directory + x):
- directories.append(directory + x + "/")
- files.remove(x)
-
- if self.showDirectories:
- if directory:
- if self.showMountpoints and directory == self.current_mountpoint:
- self.list.append(FileEntryComponent(name = "<" +_("List of storage devices") + ">", absolute = None, isDir = True))
- elif (directory != self.topDirectory) and not (self.inhibitMounts and self.getMountpoint(directory) in self.inhibitMounts):
- self.list.append(FileEntryComponent(name = "<" +_("Parent directory") + ">", absolute = '/'.join(directory.split('/')[:-2]) + '/', isDir = True))
- for x in directories:
- if not (self.inhibitMounts and self.getMountpoint(x) in self.inhibitMounts) and not self.inParentDirs(x, self.inhibitDirs):
- name = x.split('/')[-2]
- self.list.append(FileEntryComponent(name = name, absolute = x, isDir = True))
-
- if self.showFiles:
- for x in files:
- if self.useServiceRef:
- path = x.getPath()
- name = path.split('/')[-1]
- else:
- path = directory + x
- name = x
-
- if (self.matchingPattern is None) or self.matchingPattern.search(path):
- self.list.append(FileEntryComponent(name = name, absolute = x , isDir = False))
-
- if self.showMountpoints and len(self.list) == 0:
- self.list.append(FileEntryComponent(name = _("nothing connected"), absolute = None, isDir = False))
-
- self.l.setList(self.list)
-
- if select is not None:
- i = 0
- self.moveToIndex(0)
- for x in self.list:
- p = x[0][0]
-
- if isinstance(p, eServiceReference):
- p = p.getPath()
-
- if p == select:
- self.moveToIndex(i)
- i += 1
-
- class SubsChooserMenuList(MenuList):
- def __init__(self, embeddedAvailable=False, searchSupport=False, historySupport=False):
- MenuList.__init__(self, [], False, eListboxPythonMultiContent)
- self.l.setItemHeight(30)
- self.l.setFont(0, gFont("Regular", 20))
- menulist = []
- if embeddedAvailable:
- res = [('embedded')]
- res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(35, 25), png=loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'key_red.png'))))
- res.append(MultiContentEntryText(pos=(60, 5), size=(350, 25), font=0, flags=RT_VALIGN_CENTER, text=_("Choose from embedded subtitles")))
- menulist.append(res)
- if historySupport:
- res = [('downloaded')]
- res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(35, 25), png=loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'key_yellow.png'))))
- res.append(MultiContentEntryText(pos=(60, 5), size=(350, 25), font=0, flags=RT_VALIGN_CENTER, text=_("Choose from downloaded subtitles")))
- menulist.append(res)
- if searchSupport:
- res = [('search')]
- res.append(MultiContentEntryPixmapAlphaTest(pos=(5, 5), size=(35, 25), png=loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'key_blue.png'))))
- res.append(MultiContentEntryText(pos=(60, 5), size=(350, 25), font=0, flags=RT_VALIGN_CENTER, text=_("Choose from web subtitles")))
- menulist.append(res)
- if embeddedAvailable or historySupport or searchSupport:
- self.l.setList(menulist)
-
- class E2SubsSeeker(SubsSeeker):
- def __init__(self, session, searchSettings, debug=False):
- self.session = session
- self.download_thread = None
- self.search_settings = searchSettings
- download_path = searchSettings.downloadPath.value
- tmp_path = searchSettings.tmpPath.value
-
- class SubsSearchSettingsProvider(E2SettingsProvider):
- def __init__(self, providerName, defaults, configSubSection):
- E2SettingsProvider.__init__(self, providerName, configSubSection, defaults)
-
- SubsSeeker.__init__(self, download_path, tmp_path,
- captcha_cb=self.captcha_cb,
- delay_cb=self.delay_cb,
- message_cb=messageCB,
- settings_provider_cls=SubsSearchSettingsProvider,
- settings_provider_args=searchSettings,
- debug=debug)
-
- self.providers_error = False
- for p in self.seekers:
- if p.error is not None:
- self.providers_error = True
-
- def downloadSubtitle(self, success_cb, error_cb, cancel_cb, selected_subtitle, subtitles_dict, settings, path=None, fname=None):
- download_fnc = super(E2SubsSeeker, self).downloadSubtitle
- if settings.get('ask_overwrite', True):
- overwrite_cb = self.overwrite_cb
- else:
- overwrite_cb = None
- params = (selected_subtitle, subtitles_dict, self.choice_cb, path, fname, overwrite_cb, settings)
- download_thread = SubsDownloadThread(self.session, download_fnc, params, success_cb, error_cb, cancel_cb)
- self.download_thread = download_thread
- self.download_thread.start()
-
- def _unpack_rarsub(self, rar_path, dest_dir):
- assert self.download_thread is not None
- assert self.download_thread.is_alive()
- files = self.download_thread.getUnrar(rar_path, dest_dir)
- return filter(lambda x:os.path.splitext(x)[1] in ('.srt', '.sub', 'txt'), files)
-
- def overwrite_cb(self, subfile):
- assert self.download_thread is not None
- assert self.download_thread.is_alive()
- return self.download_thread.getOverwrite(subfile)
-
- def choice_cb(self, subfiles):
- assert self.download_thread is not None
- assert self.download_thread.is_alive()
- return self.download_thread.getChoice(subfiles)
-
- def captcha_cb(self, image_path):
- assert self.download_thread is not None
- assert self.download_thread.is_alive()
- return self.download_thread.getCaptcha(image_path)
-
- def delay_cb(self, seconds):
- assert self.download_thread is not None
- assert self.download_thread.is_alive()
- message = _("Subtitles will be downloaded in") + " " + str(seconds) + " " + _("seconds")
- self.download_thread.getDelay(seconds, message)
-
-
- class SubsChooser(Screen):
- skin = """
- <screen position="center,center" size="610,460" zPosition="3" >
- <!-- <widget source="filename" render="Label" position="10, 10" size="590,50" valign="center" halign="center" font="Regular;21" /> -->
- <!-- <eLabel position="5,65" size="600,1" backgroundColor="#999999" /> -->
- <widget name="file_list" position="0,30" size="610,330" scrollbarMode="showOnDemand" />
- <eLabel position="5,370" size="600,1" backgroundColor="#999999" />
- <widget name="menu_list" position="0,380" size="610,80" scrollbarMode="showOnDemand" />
- </screen>
- """
-
- def __init__(self, session, subsSettings, subdir=None, embeddedSupport=False, searchSupport=False, historySupport=False, titleList=None):
- Screen.__init__(self, session)
- self.session = session
- self.subsSettings = subsSettings
- defaultDir = subdir
- if subdir is not None and not subdir.endswith('/'):
- defaultDir = subdir + '/'
- self.embeddedList = None
- self.embeddedSubtitle = None
- if embeddedSupport:
- service = self.session.nav.getCurrentService()
- subtitle = service and service.subtitle()
- self.embeddedList = subtitle and subtitle.getSubtitleList()
- self.searchSupport = searchSupport
- self.historySupport = historySupport
- self.titleList = titleList
- ref = self.session.nav.getCurrentlyPlayingServiceReference()
- videoPath = ref and ref.getPath()
- if videoPath and os.path.isfile(videoPath):
- self.videoPath = videoPath
- else:
- self.videoPath = None
- videoName = ref and os.path.split(ref.getPath())[1]
- self["filename"] = StaticText(videoName)
- self["file_list"] = SubFileList(defaultDir)
- self["menu_list"] = SubsChooserMenuList(self.embeddedList, searchSupport, historySupport)
- self["actions"] = NumberActionMap(["OkCancelActions", "ColorActions"],
- {
- "ok": self.ok,
- "cancel": self.close,
- "red": self.embeddedSubsSelection,
- "yellow":self.downloadedSubsSelection,
- "blue": self.webSubsSelection,
- }, -2)
-
- self.onLayoutFinish.append(self.updateTitle)
- self.onLayoutFinish.append(self.disableMenuList)
-
- def updateTitle(self):
- self.setTitle(_("Choose Subtitles"))
-
- def disableMenuList(self):
- self["menu_list"].selectionEnabled(False)
-
- def ok(self):
- if self['file_list'].canDescent():
- self['file_list'].descent()
- else:
- filePath = os.path.join(self['file_list'].current_directory, self['file_list'].getFilename())
- print '[SubsFileChooser]' , filePath
- self.close(filePath, False)
-
- def checkEmbeddedSubsSelection(self, embeddedSubtitle=None):
- if embeddedSubtitle:
- self.close(None, embeddedSubtitle)
-
- def embeddedSubsSelection(self):
- if self.embeddedList:
- self.session.openWithCallback(self.checkEmbeddedSubsSelection, SubsEmbeddedSelection)
-
- def webSubsSelection(self):
- def checkDownloadedSubsSelection(downloadedSubtitle=None):
- if downloadedSubtitle:
- self.close(downloadedSubtitle, False, True)
-
- def paramsDialogCB(callback=None):
- if callback:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, self.videoPath, self.titleList, resetSearchParams=False)
-
- def showProvidersErrorCB(callback):
- if not callback:
- subsSettings.search.showProvidersErrorMessage.value = False
- if subsSettings.search.openParamsDialogOnSearch.value:
- self.session.openWithCallback(paramsDialogCB, SubsSearchParamsMenu, seeker, subsSettings.search, self.titleList, enabledList=False)
- else:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, self.videoPath, self.titleList)
- subsSettings = self.subsSettings
- if not self.searchSupport:
- return
- seeker = E2SubsSeeker(self.session, subsSettings.search, debug=True)
- if seeker.providers_error and subsSettings.search.showProvidersErrorMessage.value:
- msg = _("Some subtitles providers are not working") + ".\n"
- msg += _("For more details please check search settings") + "."
- msg += "\n\n"
- msg += _("Do you want to show this message again?")
- self.session.openWithCallback(showProvidersErrorCB, MessageBox, msg, type=MessageBox.TYPE_YESNO)
-
- elif subsSettings.search.openParamsDialogOnSearch.value:
- self.session.openWithCallback(paramsDialogCB, SubsSearchParamsMenu, seeker, subsSettings.search, self.titleList, enabledList=False)
- else:
- self.session.openWithCallback(checkDownloadedSubsSelection, SubsSearch, seeker, subsSettings.search, self.videoPath, self.titleList)
-
-
- def downloadedSubsSelectionCB(self, subtitles, downloadedSubtitle=None):
- fpath = os.path.join(self.subsSettings.search.downloadHistory.path.value,'hsubtitles.json')
- try:
- json.dump(subtitles, open(fpath,"w"))
- except Exception as e:
- print '[SubsFileChooser] downloadedSubsSelectionCB - %s'% str(e)
- if downloadedSubtitle:
- self.close(downloadedSubtitle, False, True)
-
- def downloadedSubsSelection(self):
- if not self.historySupport:
- return
- fpath = os.path.join(self.subsSettings.search.downloadHistory.path.value,'hsubtitles.json')
- try:
- subtitles = json.load(open(fpath, "r"))
- except Exception as e:
- print '[SubsFileChooser] downloadedSubsSelection - %s'% str(e)
- subtitles = []
- self.session.openWithCallback(self.downloadedSubsSelectionCB, SubsDownloadedSelection, subtitles, self.subsSettings.search.downloadHistory)
-
-
- class SubsDownloadedSelection(Screen):
- class InfoScreen(Screen):
- skin = """
- <screen position = "center,center" size="650,200" zPosition="4" flags="wfNoBorder" backgroundColor="#333333">
- <widget source="path" render="Label" position="5,5" size="640,190" valign="center" halign="center" font="Regular;20"/>
- </screen>
- """
- def __init__(self, session, subtitle):
- Screen.__init__(self, session)
- self["path"] = StaticText(_(toString(subtitle['fpath'])))
-
- skin = """
- <screen position="center,center" size="700,520" zPosition="3">
- <widget source="header_name" render="Label" position = "5,10" size="360,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_provider" render="Label" position = "380,10" size="165,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_date" render="Label" position = "525, 10" size="170,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <eLabel position="5,45" size="690,1" backgroundColor="#999999" />
- <widget source="subtitles" render="Listbox" scrollbarMode="showOnDemand" position="5,55" size="690,355" zPosition="3" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (50, [
- MultiContentEntryPixmapAlphaBlend(pos = (0, 15), size = (24, 24), png=0), # key,
- MultiContentEntryText(pos = (30, 0), size = (325, 50), font = 0, flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text=1, color=0xFF000004), # name,
- MultiContentEntryText(pos = (375, 0), size = (165, 50), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 2, color=0xFF000004), # provider,
- MultiContentEntryText(pos = (520, 0), size = (170, 50), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 3, color=0xFF000004), # date,
- ], True, "showOnDemand"),
- },
- "fonts": [gFont("Regular", 19), gFont("Regular", 16)],
- "itemHeight": 50
- }
- </convert>
- </widget>
- <eLabel position="5,430" size="690,1" backgroundColor="#999999" />
- <widget source="entries_sum" render="Label" position = "10, 440" size="300,25" font="Regular;18" halign="left" foregroundColor="white" />
- <eLabel position="5,470" size="690,1" backgroundColor="#999999" />
- <ePixmap pixmap="skin_default/buttons/key_info.png" position="10,485" size="35,25" transparent="1" alphatest="on" />
- <ePixmap pixmap="skin_default/buttons/key_red.png" position="50,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_red" render="Label" position = "90, 485" size="230,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_blue.png" position="500,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_blue" render="Label" position = "540, 485" size="130,25" font="Regular;20" halign="left" foregroundColor="white" />
- </screen> """
-
- def __init__(self, session, subtitles, historySettings, marked=None):
- Screen.__init__(self, session)
- self["header_name"] = StaticText(_("Name"))
- self["header_provider"] = StaticText(_("Provider"))
- self["header_date"] = StaticText(_("Download date"))
- self["subtitles"] = List()
- self["entries_sum"] = StaticText()
- self["key_red"] = StaticText(_("Remove (file)"))
- self["key_blue"] = StaticText(_("Settings"))
- self["actions"] = ActionMap(["ColorActions", "OkCancelActions", "InfoActions"],
- {
- "ok": self.ok,
- "cancel": self.cancel,
- "info":self.showInfo,
- "red":self.removeEntry,
- "blue":self.openSettings,
- }, -2)
- self["infoActions"] = ActionMap(["ColorActions", "OkCancelActions", "DirectionActions", "InfoActions"],
- {
- "ok": self.closeInfoDialog,
- "cancel": self.closeInfoDialog,
- "info": self.closeInfoDialog,
- "red": self.closeInfoDialog,
- "green":self.closeInfoDialog,
- "blue": self.closeInfoDialog,
- "up": self.closeInfoDialog,
- "upUp":self.closeInfoDialog,
- "down":self.closeInfoDialog,
- "downUp": self.closeInfoDialog,
- "right":self.closeInfoDialog,
- "rightUp":self.closeInfoDialog,
- "left":self.closeInfoDialog,
- "leftUp":self.closeInfoDialog,
- } )
- self["infoActions"].setEnabled(False)
- self.subtitles = subtitles
- self.historySettings = historySettings
- self.marked = marked or []
- self.onLayoutFinish.append(self.updateWindowTitle)
- self.onLayoutFinish.append(self.updateSubsList)
- self.onLayoutFinish.append(self.updateEntriesSum)
- self.onLayoutFinish.append(self.updateRemoveAction)
-
- def updateWindowTitle(self):
- self.setTitle(_("Downloaded Subtitles"))
-
- def updateSubsList(self):
- imgDict = {'unk':loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'countries', 'UNK.png'))}
- subtitleListGUI = []
- for sub in self.subtitles[:]:
- fpath = toString(sub['fpath'])
- if not os.path.isfile(fpath):
- self.subtitles.remove(sub)
- continue
- if sub.get('country','unk') not in imgDict:
- countryImgPath = os.path.join(os.path.dirname(__file__), 'img', 'countries', sub['country'] + '.png')
- if os.path.isfile(countryImgPath):
- imgDict[sub['country']] = loadPNG(toString(countryImgPath))
- countryPng = imgDict[sub['country']]
- else:
- countryPng = imgDict['unk']
- if sub in self.marked:
- color = 0x00ff00
- else:
- color = 0xffffff
- date = datetime.fromtimestamp(os.path.getctime(fpath)).strftime("%d-%m-%Y %H:%M")
- name = os.path.splitext(os.path.basename(fpath))[0]
- subtitleListGUI.append((countryPng,toString(name), toString(sub['provider']), date, color),)
- imgDict = None
- self['subtitles'].list = subtitleListGUI
-
- def updateEntriesSum(self):
- limit = int(self.historySettings.limit.value)
- self["entries_sum"].text = _("Entries count:") + " " + str(len(self.subtitles)) + " / " + str(limit)
-
- def updateRemoveAction(self):
- if self.historySettings.removeAction.value == 'file':
- self["key_red"].text = _("Remove Entry (List+File)")
- else:
- self["key_red"].text = _("Remove Entry (List)")
-
- def removeEntry(self):
- def removeEntryCB(doRemove=False):
- if doRemove:
- if self.historySettings.removeAction.value == 'file':
- try:
- os.unlink(subtitle['fpath'])
- except OSError as e:
- print "[SubsDownloadedSelection] cannot remove - %s"%(str(e))
- self.session.open(MessageBox, _("There was an error while removing subtitle, please check log"), type=MessageBox.TYPE_ERROR)
- else:
- self.subtitles.remove(subtitle)
- curridx = self['subtitles'].index
- self.updateSubsList()
- self['subtitles'].index = curridx -1
- self.updateEntriesSum()
- else:
- self.subtitles.remove(subtitle)
- curridx = self['subtitles'].index
- self.updateSubsList()
- self['subtitles'].index = curridx -1
- self.updateEntriesSum()
-
- if self["subtitles"].count() > 0:
- subtitle = self.subtitles[self["subtitles"].index]
- if self.historySettings.removeAction.value == 'file':
- if self.historySettings.removeActionAsk.value:
- message = _("Subtitle") + " '" + toString(subtitle['name'])+ "' " + _("will be removed from file system")
- message += "\n\n" + _("Do you want to proceed?")
- self.session.openWithCallback(removeEntryCB, MessageBox, message, type=MessageBox.TYPE_YESNO)
- else:
- removeEntryCB(True)
- else:
- if self.historySettings.removeActionAsk.value:
- message = _("Subtitle") + " '" + toString(subtitle['name'])+ "' " + _("will be removed from list")
- message += "\n\n" + _("Do you want to proceed?")
- self.session.openWithCallback(removeEntryCB, MessageBox, message, type=MessageBox.TYPE_YESNO)
- else:
- removeEntryCB(True)
-
- def openSettings(self):
- def menuCB(callback=None):
- self.updateEntriesSum()
- self.updateRemoveAction()
- self.session.openWithCallback(menuCB, SubsDownloadedSubtitlesMenu, self.historySettings)
-
- def showInfo(self):
- if self["subtitles"].count() > 0:
- subtitle = self.subtitles[self["subtitles"].index]
- self["actions"].setEnabled(False)
- self["infoActions"].setEnabled(True)
- self.__infoScreen = self.session.instantiateDialog(self.InfoScreen, subtitle)
- self.__infoScreen.show()
-
- def closeInfoDialog(self):
- self.session.deleteDialog(self.__infoScreen)
- self["infoActions"].setEnabled(False)
- self["actions"].setEnabled(True)
-
- def ok(self):
- if self["subtitles"].count() > 0:
- subtitle = self.subtitles[self["subtitles"].index]
- self.close(self.subtitles, subtitle['fpath'])
- self.close(self.subtitles, None)
-
- def cancel(self):
- self.close(self.subtitles, None)
-
-
- class SubsDownloadedSubtitlesMenu(Screen, ConfigListScreen):
- skin = """
- <screen position="center,center" size="610,435" >
- <widget name="key_red" position="10,5" zPosition="1" size="140,45" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_green" position="160,5" zPosition="1" size="140,45" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_yellow" position="310,5" zPosition="1" size="140,45" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_blue" position="460,5" zPosition="1" size="140,45" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" shadowOffset="-2,-2" shadowColor="black" />
- <eLabel position="-1,55" size="612,1" backgroundColor="#999999" />
- <widget name="config" position="0,75" size="610,360" scrollbarMode="showOnDemand" />
- </screen>"""
-
- def __init__(self, session, historySettings):
- Screen.__init__(self, session)
- ConfigListScreen.__init__(self, [], session=session)
- self["actions"] = ActionMap(["SetupActions", "ColorActions"],
- {
- "cancel": self.keyCancel,
- "green": self.keySave,
- "red": self.keyCancel,
- "blue": self.resetDefaults,
- }, -2)
-
- self["key_green"] = Label(_("Save"))
- self["key_red"] = Label(_("Cancel"))
- self["key_blue"] = Label(_("Reset Defaults"))
- self["key_yellow"] = Label("")
- self.historySettings = historySettings
- self.buildMenu()
- self.onLayoutFinish.append(self.updateTitle)
-
- def updateTitle(self):
- self.setTitle(_("Downloaded Subtitles - Settings"))
-
- def buildMenu(self):
- menuList = []
- menuList.append(getConfigListEntry(_("Max history entries"), self.historySettings.limit))
- menuList.append(getConfigListEntry(_("Remove action") , self.historySettings.removeAction))
- menuList.append(getConfigListEntry(_("Ask on remove action"), self.historySettings.removeActionAsk))
- self["config"].setList(menuList)
-
- def resetDefaults(self):
- for x in self["config"].list:
- x[1].value = x[1].default
- self.buildMenu()
-
- def keyOK(self):
- if self["config"].getCurrent()[1] == self.historySettings.path:
- self.session.openWithCallback(self.changeDir, LocationBox,
- _("Select Directory"), currDir=self.historySettings.path.value)
-
- def keySave(self):
- for x in self["config"].list:
- x[1].save()
- configfile.save()
- self.close(True)
-
- def keyCancel(self):
- for x in self["config"].list:
- x[1].cancel()
- self.close()
-
- def keyLeft(self):
- ConfigListScreen.keyLeft(self)
-
- def keyRight(self):
- ConfigListScreen.keyRight(self)
-
- # source from openpli
- class SubsEmbeddedSelection(Screen):
- skin = """<screen name="SubsEmbeddedSelection" position="center,center" size="485,220">
- <widget source="streams" render="Listbox" scrollbarMode="showOnDemand" position="10,40" size="465,180" zPosition="3" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (25, [
- MultiContentEntryText(pos = (0, 0), size = (35, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # key,
- MultiContentEntryText(pos = (40, 0), size = (60, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # number,
- MultiContentEntryText(pos = (110, 0), size = (120, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # description,
- MultiContentEntryText(pos = (240, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # language,
- ], True, "showNever"),
- },
- "fonts": [gFont("Regular", 20), gFont("Regular", 16)],
- "itemHeight": 25
- }
- </convert>
- </widget>
- </screen>"""
- def __init__(self, session):
- Screen.__init__(self, session)
- self["streams"] = List([], enableWrapAround=True)
- self["actions"] = ActionMap(["SetupActions", "DirectionActions", "MenuActions"],
- {
- "ok": self.keyOk,
- "cancel": self.cancel,
- }, -2)
- self.onLayoutFinish.append(self.updateTitle)
- self.onLayoutFinish.append(self.fillList)
-
- def updateTitle(self):
- self.setTitle(_("Choose subtitles"))
-
- def fillList(self):
- idx = 0
- streams = []
- subtitlelist = self.getSubtitleList()
- for x in subtitlelist:
- number = str(x[1])
- description = "?"
- language = ""
-
- try:
- if x[4] != "und":
- if LanguageCodes.has_key(x[4]):
- language = LanguageCodes[x[4]][0]
- else:
- language = x[4]
- except:
- language = ""
-
- if x[0] == 0:
- description = "DVB"
- number = "%x" % (x[1])
-
- elif x[0] == 1:
- description = "teletext"
- number = "%x%02x" % (x[3] and x[3] or 8, x[2])
-
- elif x[0] == 2:
- types = ("unknown", "embedded", "SSA file", "ASS file",
- "SRT file", "VOB file", "PGS file")
- try:
- description = types[x[2]]
- except:
- description = _("unknown") + ": %s" % x[2]
- number = str(int(number) + 1)
- print x, number, description, language
- streams.append((x, "", number, description, language))
- idx += 1
- self["streams"].list = streams
-
-
- def getSubtitleList(self):
- service = self.session.nav.getCurrentService()
- subtitle = service and service.subtitle()
- subtitlelist = subtitle and subtitle.getSubtitleList()
- embeddedlist = []
- for x in subtitlelist:
- if x[0] == 2:
- types = ("unknown", "embedded", "SSA file", "ASS file",
- "SRT file", "VOB file", "PGS file")
- # filter embedded subtitles
- if x[2] not in [1, 2, 3, 4, 5, 6]:
- continue
- embeddedlist.append(x)
- return embeddedlist
-
- self.selectedSubtitle = None
- return subtitlelist
-
- def cancel(self):
- self.close()
-
- def keyOk(self):
- cur = self["streams"].getCurrent()
- self.close(cur[0][:4])
-
- class SimpleObserverList(list):
- def __init__(self, *args):
- list.__init__(self, *args)
- self.observer_fncs = list()
-
- def add_observer(self, observer_fnc):
- self.observer_fncs.append(observer_fnc)
-
- def remove_observer(self, observer_fnc):
- self.observer_fncs.remove(observer_fnc)
-
- def append (self, value):
- list.append(self, value)
- for f in self.observer_fncs:
- f()
-
- def remove(self, value):
- list.remove(self, value)
- for f in self.observer_fncs:
- f()
-
- class SubsDownloadThread(Thread):
- THREADS = SimpleObserverList()
-
- CAPTCHA_REQUEST = 0
- DELAY_REQUEST = 1
- FINISH_REQUEST_SUCCESS = 2
- FINISH_REQUEST_ERROR = 3
- OVERWRITE_REQUEST = 4
- CHOICE_REQUEST = 5
- UNRAR_REQUEST = 6
-
- def __init__(self, session, fnc, params, callback, errorback, cancelback):
- Thread.__init__(self)
- self.session = session
- self.fnc = fnc
- self.params = params
- self.callback = callback
- self.errorback = errorback
- self.cancelback = cancelback
- self.cancelled = False
- self.messageIn = Queue()
- self.messageOut = Queue()
- self.messagePump = ePythonMessagePump()
- self.messagePump.recv_msg.get().append(self._runInMainThread)
-
- def start(self):
- SubsDownloadThread.THREADS.append(self)
- Thread.start(self)
-
- def run(self):
- try:
- ret = self.fnc(*self.params)
- self.messageOut.put((self.FINISH_REQUEST_SUCCESS, ret))
- self.messagePump.send(0)
- except Exception:
- exc_value, exc_traceback = sys.exc_info()[1:]
- exc_value.tb = exc_traceback
- self.messageOut.put((self.FINISH_REQUEST_ERROR, exc_value))
- self.messagePump.send(0)
-
- def _runInMainThread(self, val):
- ret = self.messageOut.get()
- request = ret[0]
- if request == self.CAPTCHA_REQUEST:
- imagePath = ret[1]
- Captcha(self.session, self.getCaptchaCB, imagePath)
- elif request == self.DELAY_REQUEST:
- seconds, message = ret[1], ret[2]
- self.session.openWithCallback(self.getDelayCB, DelayMessageBox, seconds, message)
- elif request == self.FINISH_REQUEST_SUCCESS:
- subFile = ret[1]
- if self.cancelled:
- self.cancelback()
- else:
- self.callback(subFile)
- SubsDownloadThread.THREADS.remove(self)
- elif request == self.FINISH_REQUEST_ERROR:
- error = ret[1]
- self.errorback(error)
- SubsDownloadThread.THREADS.remove(self)
- elif request == self.CHOICE_REQUEST:
- subFiles = ret[1]
- choiceTitle = _("There are more subtitles in unpacked archive\n please select which one do you want to use")
- choiceList = [(os.path.basename(subfile), subfile) for subfile in subFiles]
- self.session.openWithCallback(self.getChoiceCB, ChoiceBox, choiceTitle, choiceList)
- elif request == self.OVERWRITE_REQUEST:
- overwriteText = _("Subtitles with this name already exist\nDo you want to overwrite them") + "?"
- self.session.openWithCallback(self.getOverwriteCB, MessageBox, overwriteText, MessageBox.TYPE_YESNO)
- elif request == self.UNRAR_REQUEST:
- rarPath = ret[1]
- destDir = ret[2]
- unrar(rarPath, destDir, self.getUnrarCB, self.getUnrarCB)
-
- def getUnrar(self, subFile, destPath):
- self.messageOut.put((self.UNRAR_REQUEST, subFile, destPath))
- self.messagePump.send(0)
- ret = self.messageIn.get()
- if isinstance(ret, str):
- raise Exception(ret)
- return ret
-
- def getUnrarCB(self, callback):
- self.messageIn.put(callback)
-
- def getOverwrite(self, subFile):
- self.messageOut.put((self.OVERWRITE_REQUEST, subFile))
- self.messagePump.send(0)
- return self.messageIn.get()
-
- def getOverwriteCB(self, callback):
- self.messageIn.put(callback)
-
- def getChoice(self, files):
- self.messageOut.put((self.CHOICE_REQUEST, files))
- self.messagePump.send(0)
- return self.messageIn.get()
-
- def getChoiceCB(self, selfile):
- if selfile:
- selfile = selfile[1]
- if selfile is None:
- self.cancelled = True
- return self.messageIn.put(selfile)
-
- def getCaptcha(self, imagePath):
- self.messageOut.put((self.CAPTCHA_REQUEST, imagePath))
- self.messagePump.send(0)
- return self.messageIn.get()
-
- def getCaptchaCB(self, word):
- word = word or ""
- self.messageIn.put(word)
-
- def getDelay(self, seconds, message):
- self.messageOut.put((self.DELAY_REQUEST, seconds, message))
- self.messagePump.send(0)
- return self.messageIn.get()
-
- def getDelayCB(self, callback=None):
- return self.messageIn.put(None)
-
- class SubsSearchProcess(object):
- processes = []
- process_path = os.path.join(os.path.dirname(__file__), 'searchsubs.py')
-
- def __init__(self):
- self.log = SimpleLogger('SubsSearchProcess', SimpleLogger.LOG_INFO)
- self.toRead = None
- self.pPayload = None
- self.data = ""
- self.__stopping = False
- self.appContainer = eConsoleAppContainer()
- self.appContainer.stdoutAvail.append(self.dataOutCB)
- self.appContainer.stderrAvail.append(self.dataErrCB)
- self.appContainer.appClosed.append(self.finishedCB)
-
- def recieveMessages(self, data):
- def getMessage(data):
- mSize = int(data[:7])
- mPayload = data[7:mSize]
- mPart = mSize > len(data)
- return mSize, mPayload, mPart
-
- def readMessage(payload):
- try:
- message = json.loads(payload)
- except EOFError:
- pass
- except Exception:
- self.log.debug('data is not in JSON format! - %s' % str(payload))
- else:
- self.log.debug('message successfully recieved')
- self.toRead = None
- self.pPayload = None
- self.handleMessage(message)
-
- def readStart(data):
- mSize, mPayload, mPart = getMessage(data)
- if not mPart:
- data = data[mSize:]
- readMessage(mPayload)
- if len(data) > 0:
- readStart(data)
- else:
- self.toRead = mSize - len(data)
- self.pPayload = mPayload
-
- def readContinue(data):
- nextdata = data[:self.toRead]
- self.pPayload += nextdata
- data = data[len(nextdata):]
- self.toRead -= len(nextdata)
- if self.toRead == 0:
- readMessage(self.pPayload)
- if len(data) > 0:
- readStart(data)
-
- if self.pPayload is not None:
- readContinue(data)
- else:
- readStart(data)
-
- def handleMessage(self, data):
- self.log.debug('handleMessage "%s"', data)
- if data['message'] == Messages.MESSAGE_UPDATE_CALLBACK:
- self.updateCB(data['value'])
- if data['message'] == Messages.MESSAGE_FINISHED_SCRIPT:
- self.successCB(data['value'])
- if data['message'] == Messages.MESSAGE_CANCELLED_SCRIPT:
- print 'script successfully cancelled'
- if data['message'] == Messages.MESSAGE_ERROR_SCRIPT:
- self.errorCB(data['value'])
-
- def start(self, params, updateCB, successCB, errorCB):
- self.processes.append(self)
- self.updateCB = updateCB
- self.successCB = successCB
- self.errorCB = errorCB
- cmd = "python %s" % self.process_path
- self.log.debug("start - '%s'", cmd)
- self.appContainer.execute(cmd)
- self.write(params)
-
- def running(self):
- return self.appContainer.running()
-
- def stop(self):
- def check_stopped():
- if not self.appContainer.running():
- timer.stop()
- del self.__i
- return
- if self.__i == 0:
- self.__i += 1
- self.log.debug('2. sending SIGKILL')
- self.appContainer.kill()
- elif self.__i == 1:
- timer.stop()
- raise Exception("cannot kill process")
-
- if self.__stopping:
- self.log.debug('already stopping..')
- return
- self.__stopping = True
- self.log.debug('stopping process..')
- self.__i = 0
-
- if self.appContainer.running():
- self.log.debug('1. sending SIGINT')
- self.appContainer.sendCtrlC()
- timer = eTimer()
- timer.callback.append(check_stopped)
- timer.start(2000, False)
- else:
- self.log.debug('process is already stopped')
-
- def write(self, data):
- dump = json.dumps(data)
- dump = "%07d%s" % (len(dump), dump)
- self.appContainer.write(dump)
-
- def dataErrCB(self, data):
- self.log.debug("dataErrCB: '%s'", data)
- self.error = data
-
- def dataOutCB(self, data):
- self.log.debug("dataOutCB: '%s", data)
- self.recieveMessages(data)
-
- def finishedCB(self, retval):
- self.processes.remove(self)
- self.log.debug('process finished, retval:%d', retval)
-
-
- class Suggestions(object):
- def __init__(self):
- self._cancelled = False
-
- def __str__(self):
- return self.__class__.__name__
-
- def cancel(self):
- self._cancelled = True
-
- def getSuggestions(self, queryString, successCB, errorCB):
- if queryString is not None:
- d = self._getSuggestions(queryString)
- self.successCB = successCB
- self.errorCB = errorCB
- d.addCallbacks(self.getSuggestionsSuccess, self.getSuggestionsError)
-
- def getSuggestionsSuccess(self, data):
- if not self._cancelled:
- self.successCB(self._processResult(data))
-
- def getSuggestionsError(self, failure):
- if not self._cancelled:
- failure.printTraceback()
- self.errorCB(failure)
-
- def _getSuggestions(self):
- return Deferred()
-
- def _processResult(self, data):
- return data
-
-
- class OpenSubtitlesSuggestions(Suggestions):
- def _getSuggestions(self, queryString):
- query = "http://www.opensubtitles.org/libs/suggest.php?format=json2&SubLanguageID=null&MovieName=" + queryString
- return client.getPage(query, timeout=6)
-
- def _processResult(self, data):
- return json.loads(data)['result']
-
- class HistorySuggestions(Suggestions):
- def __init__(self, historyCfg):
- Suggestions.__init__(self)
- self.historyCfg = historyCfg
-
- def _getSuggestions(self, queryString):
- def getHistory(queryString):
- historyList = self.historyCfg.value.split(',')
- historyList = [{'name':name, 'total':len(historyList) - idx} for idx, name in enumerate(historyList)]
- d.callback(historyList)
- d = Deferred()
- getHistory(queryString)
- return d
-
- class SuggestionsListScreen(Screen):
- s = getDesktop(0).size()
- desktopSize = (s.width(), s.height())
- windowSize = (int(0.35 * desktopSize[0]), 160)
- skin = """
- <screen name="SuggestionsListScreen" position="%d, 20" zPosition="6" size="%d,160" flags="wfNoBorder" backgroundColor="#33202020" >
- <widget source="suggestionstitle" render="Label" position = "0,0" size="%d, 25" foregroundColor="#00ff00" font="Regular;20" halign="center" valign="center" transparent="0" />
- <widget source="suggestionslist" render="Listbox" position="%d,35" size="%d,115" scrollbarMode="showOnDemand" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (23, [
- MultiContentEntryText(pos = (0, 0), size = (360, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # title,
- ], True, "showOnDemand"),
- "notselected": (23, [
- MultiContentEntryText(pos = (0, 0), size = (360, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # title,
- ], False, "showOnDemand")
- },
- "fonts": [gFont("Regular", 18), gFont("Regular", 16)],
- "itemHeight": 23
- }
- </convert>
- </widget>
- </screen>""" % (int(0.6 * desktopSize[0]), windowSize[0],
- windowSize[0],
- int(0.05 * windowSize[0]), int(0.9 * windowSize[0]))
-
- def __init__(self, session, title, configTextWithSuggestions):
- Screen.__init__(self, session)
- self.activeState = False
- self.list = []
- self.suggestlist = []
- self["suggestionslist"] = List(self.list)
- self["suggestionstitle"] = StaticText(toString(title))
- self.configTextWithSuggestion = configTextWithSuggestions
-
- def update(self, suggestions):
- if suggestions and len(suggestions) > 0:
- if not self.shown:
- self.show()
- suggestions.sort(key=lambda x: int(x['total']))
- suggestions.reverse()
- if len(suggestions):
- self.list = []
- for s in suggestions:
- self.list.append((toString(s['name']),))
- self["suggestionslist"].setList(self.list)
- self["suggestionslist"].setIndex(0)
- else:
- self.hide()
-
- def getlistlenght(self):
- return len(self.list)
-
- def up(self):
- if self.list and len(self.list) > 0:
- self["suggestionslist"].selectPrevious()
- return self.getSelection()
-
- def down(self):
- if self.list and len(self.list) > 0:
- self["suggestionslist"].selectNext()
- return self.getSelection()
-
- def pageUp(self):
- if self.list and len(self.list) > 0:
- self["suggestionslist"].selectPrevious()
- return self.getSelection()
-
- def pageDown(self):
- if self.list and len(self.list) > 0:
- self["suggestionslist"].selectNext()
- return self.getSelection()
-
- def activate(self):
- self.enableSelection(True)
- return self.getSelection()
-
- def deactivate(self):
- self.enableSelection(False)
- return self.getSelection()
-
- def getSelection(self):
- if not self["suggestionslist"].getCurrent():
- return None
- return self["suggestionslist"].getCurrent()[0]
-
- def enableSelection(self, value):
- if value:
- self['suggestionslist'].style = 'default'
- else:
- self['suggestionslist'].style = 'notselected'
-
- class HistoryListScreen(SuggestionsListScreen):
- s = getDesktop(0).size()
- desktopSize = (s.width(), s.height())
- windowSize = (int(0.35 * desktopSize[0]), 160)
- skin = """
- <screen name="HistoryListScreen" position="%d, 20" zPosition="6" size="%d,160" flags="wfNoBorder" backgroundColor="#33202020" >
- <widget source="suggestionstitle" render="Label" position = "0,0" size="%d, 25" foregroundColor="#ff0000" font="Regular;20" halign="center" valign="center" transparent="0" />
- <widget source="suggestionslist" render="Listbox" position="%d,35" size="%d,115" scrollbarMode="showOnDemand" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (23, [
- MultiContentEntryText(pos = (0, 0), size = (360, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # title,
- ], True, "showOnDemand"),
- "notselected": (23, [
- MultiContentEntryText(pos = (0, 0), size = (360, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # title,
- ], False, "showOnDemand")
- },
- "fonts": [gFont("Regular", 18), gFont("Regular", 16)],
- "itemHeight": 23
- }
- </convert>
- </widget>
- </screen>""" % (int(0.05 * desktopSize[0]), windowSize[0],
- windowSize[0],
- int(0.05 * windowSize[0]), int(0.9 * windowSize[0]))
-
- def __init__(self, session, title, configTextWithSuggestions):
- SuggestionsListScreen.__init__(self, session, title, configTextWithSuggestions)
-
- class ConfigTextWithSuggestionsAndHistory(ConfigText):
- def __init__(self, historyCfg, default="", fixed_size=True, visible_width=False):
- ConfigText.__init__(self, default, fixed_size, visible_width)
- self.historyCfg = historyCfg
- self.historyClass = HistorySuggestions
- self.historyWindow = None
- self.__history = None
- self.suggestionsClass = OpenSubtitlesSuggestions
- self.suggestionsWindow = None
- self.__suggestions = None
- self.currentWindow = None
-
- def handleKey(self, key):
- ConfigText.handleKey(self, key)
- if key in [KEY_DELETE, KEY_BACKSPACE, KEY_ASCII, KEY_TIMEOUT]:
- self.getSuggestions()
-
- def onSelect(self, session):
- ConfigText.onSelect(self, session)
- if session is not None:
- if self.suggestionsWindow is None:
- suggestionsWindowTitle = _("Suggestions") + " (" + _("press green") + ")"
- self.suggestionsWindow = session.instantiateDialog(SuggestionsListScreen, suggestionsWindowTitle , self)
- self.suggestionsWindow.deactivate()
- self.suggestionsWindow.show()
- historyWindowTitle = _("History") + " (" + _("press red") + ")"
- if self.historyWindow is None:
- self.historyWindow = session.instantiateDialog(HistoryListScreen, historyWindowTitle, self)
- self.historyWindow.deactivate()
- self.historyWindow.show()
- self.getSuggestions()
- self.getHistory()
-
- def onDeselect(self, session):
- self.cancelGetSuggestions()
- self.cancelGetHistory()
- ConfigText.onDeselect(self, session)
- if self.suggestionsWindow is not None:
- self.suggestionsWindow.hide()
- if self.historyWindow is not None:
- self.historyWindow.hide()
-
- def getCurrentSelection(self):
- if self.currentWindow.getlistlenght() > 0:
- return self.currentWindow.getSelection()
-
- def currentListUp(self):
- if self.currentWindow.getlistlenght() > 0:
- self.value = self.currentWindow.up()
-
- def currentListDown(self):
- if self.currentWindow.getlistlenght() > 0:
- self.value = self.currentWindow.down()
-
- def currentListPageDown(self):
- if self.currentWindow.getlistlenght() > 0:
- self.value = self.currentWindow.pageDown()
-
- def currentListPageUp(self):
- if self.currentWindow.getlistlenght() > 0:
- self.value = self.currentWindow.pageUp()
-
- def propagateSuggestions(self, suggestionsList):
- self.cancelGetSuggestions()
- if self.suggestionsWindow:
- self.suggestionsWindow.update(suggestionsList)
-
- def propagateHistory(self, historyList):
- self.cancelGetHistory()
- if self.historyWindow:
- self.historyWindow.update(historyList)
-
- def enableSuggestions(self, value):
- if value:
- if self.suggestionsWindow:
- self.tmpValue = self.value
- selection = self.suggestionsWindow.activate()
- if selection is None:
- print 'empty suggesstions list'
- return False
- self.value = selection
- self.currentWindow = self.suggestionsWindow
- return True
- else:
- print 'Error - suggestionsWindow no longer exists'
- return False
- else:
- self.cancelGetSuggestions()
- if self.suggestionsWindow:
- self.suggestionsWindow.deactivate()
- self.currentWindow = None
- self.getSuggestions()
- return True
- else:
- print 'Error - suggestionsWindow no longer exists'
- return False
-
- def enableHistory(self, value):
- if value:
- if self.historyWindow:
- self.tmpValue = self.value
- selection = self.historyWindow.activate()
- if selection is None:
- print "Error - empty history list"
- return False
- self.value = selection
- self.currentWindow = self.historyWindow
- return True
- else:
- print 'Error - historyWindow no longer exists'
- return False
- else:
- self.cancelGetHistory()
- if self.historyWindow:
- self.historyWindow.deactivate()
- self.currentWindow = None
- self.getHistory()
- return True
- else:
- print 'Error - historyWindow no longer exists'
- return False
-
- def cancelGetSuggestions(self):
- if self.__suggestions is not None:
- self.__suggestions.cancel()
-
- def cancelGetHistory(self):
- if self.__history is not None:
- self.__history.cancel()
-
- def gotSuggestionsError(self, val):
- print "[ConfigTextWithSuggestions] gotSuggestionsError:", val
-
- def gotHistoryError(self, val):
- print "[ConfigTextWithSuggestions] gotHistoryError:", val
-
- def getSuggestions(self):
- self.__suggestions = self.suggestionsClass().getSuggestions(self.value, self.propagateSuggestions, self.gotSuggestionsError)
-
- def getHistory(self):
- self.__history = self.historyClass(self.historyCfg).getSuggestions(self.value, self.propagateHistory, self.gotHistoryError)
-
- def cancelSuggestions(self):
- self.value = self.tmpValue
- self.enableSuggestions(False)
- self.enableHistory(False)
-
- class Message(object):
- def __init__(self, infowidget, errorwidget):
- self.infowidget = infowidget
- self.errorwidget = errorwidget
- self.timer = eTimer()
- self.timer.callback.append(self.hide)
-
- def info(self, text, timeout=None):
- self.timer.stop()
- self.errorwidget.hide()
- self.infowidget.setText(text)
- self.infowidget.show()
- if timeout:
- self.timer.start(timeout, True)
-
- def error(self, text, timeout=None):
- self.timer.stop()
- self.infowidget.hide()
- self.errorwidget.setText(text)
- self.errorwidget.show()
- if timeout:
- self.timer.start(timeout, True)
-
- def hide(self):
- self.timer.stop()
- self.errorwidget.hide()
- self.infowidget.hide()
-
- class SearchParamsHelper(object):
- def __init__(self, seeker, searchSettings):
- self.seeker = seeker
- self.searchSettings = searchSettings
- self.searchTitle = searchSettings.title
- self.searchType = searchSettings.type
- self.searchYear = searchSettings.year
- self.searchSeason = searchSettings.season
- self.searchEpisode = searchSettings.episode
- self.searchProvider = searchSettings.provider
- self.searchUseFilePath = searchSettings.useFilePath
-
- def resetSearchParams(self):
- self.searchType.value = self.searchType.default
- self.searchType.save()
- self.searchTitle.value = self.searchTitle.default
- self.searchTitle.save()
- self.searchSeason.value = self.searchSeason.default
- self.searchSeason.save()
- self.searchEpisode.value = self.searchEpisode.default
- self.searchEpisode.save()
- self.searchYear.value = self.searchYear.default
- self.searchYear.save()
- self.searchProvider.value = self.searchProvider.default
- self.searchProvider.save()
- self.searchUseFilePath.value = self.searchUseFilePath.default
-
- def detectSearchParams(self, searchExpression):
- self.resetSearchParams()
- params = detectSearchParams(searchExpression)
- if params[2]:
- self.searchType.value = "tv_show"
- self.searchTitle.value = params[2]
- self.searchSeason.value = params[3] and int(params[3]) or 0
- self.searchEpisode.value = params[4] and int(params[4]) or 0
- else:
- self.searchType.value = "movie"
- self.searchTitle.value = params[0]
- self.searchYear.value = params[1] and int(params[1]) or 0
- self.updateProviders()
-
- def getSearchParams(self):
- langs = [self.searchSettings.lang1.value,
- self.searchSettings.lang2.value,
- self.searchSettings.lang3.value]
- provider = self.searchProvider.value
- title = self.searchTitle.value
- tvshow = self.searchType.value == "tv_show" and title or ""
- year = self.searchYear.value and not tvshow and str(self.searchYear.value) or ""
- season = self.searchSeason.value and tvshow and str(self.searchSeason.value) or ""
- episode = self.searchEpisode.value and tvshow and str(self.searchEpisode.value) or ""
- return provider, langs, title, year, tvshow, season, episode
-
- def updateProviders(self):
- tvshow = self.searchType.value == "tv_show"
- providers = self.seeker.getProviders([self.searchSettings.lang1.value,
- self.searchSettings.lang2.value,
- self.searchSettings.lang3.value], not tvshow, tvshow)
- choiceList = []
- choiceList.append(("all", _("All")))
- choiceList.extend((p.id, p.provider_name) for p in providers)
- self.searchProvider.setChoices(choiceList)
- if self.searchProvider.value not in [p.id for p in providers]:
- if tvshow:
- self.searchProvider.value = self.searchSettings.tvshowProvider.value
- else:
- self.searchProvider.value = self.searchSettings.movieProvider.value
- tvshowProviders = self.seeker.getProviders(movie=False, tvshow=True)
- choiceList = []
- choiceList.append(("all", _("All")))
- choiceList.extend((p.id, p.provider_name) for p in tvshowProviders)
- self.searchSettings.tvshowProvider.setChoices(choiceList)
- movieProviders = self.seeker.getProviders(movie=True, tvshow=False)
- choiceList = []
- choiceList.append(("all", _("All")))
- choiceList.extend((p.id, p.provider_name) for p in movieProviders)
- self.searchSettings.movieProvider.setChoices(choiceList)
-
- class SubsSearchDownloadOptions(Screen, ConfigListScreen):
- skin="""
- <screen position="center,center" size="490,350" zPosition="5" >
- <widget name="config" position="10, 10" size="470,110" zPosition="1" />
- <eLabel position="8,128" size="474,79" backgroundColor="#ff0000" />
- <widget source="fname" render="Label" position="10,130" size="470,75" valign="center" halign="center" font="Regular;19" foregroundColor="#ffffff" zPosition="1" />
- <eLabel position="8,220" size="474,79" backgroundColor="#00ff00" />
- <widget source="dpath" render="Label" position="10,222" size="470,75" valign="center" halign="center" font="Regular;19" foregroundColor="#ffffff" zPosition="1" />
- <eLabel position="5,305" size="480,1" backgroundColor="#999999" />
- <ePixmap pixmap="skin_default/buttons/key_red.png" position="10,315" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_red" render="Label" position = "50, 315" size="110,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_green.png" position="170,315" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_green" render="Label" position = "210, 315" size="110,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_blue.png" position="330,315" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_blue" render="Label" position = "370, 315" size="480,25" font="Regular;20" halign="left" foregroundColor="white" />
- </screen>
- """
- def __init__(self, session, subtitle, saveAs, saveTo, addLang, dPath, vPath=None):
- Screen.__init__(self, session)
- saveAsOptions = []
- saveAsOptions.append(('version', _("Release")))
- if vPath is not None and os.path.isfile(vPath):
- saveAsOptions.append(('video', _("Video filename")))
- saveAsOptions.append(('custom', _("User defined")))
- saveToOptions = []
- saveToOptions.append(('custom', _('User defined')))
- if vPath is not None and os.path.isfile(vPath):
- saveToOptions.append(('video', _('Next to video')))
- if saveAs == 'default':
- # we don't know what the default filename will be
- saveAs = 'version'
- elif saveAs == 'video' and vPath is None:
- saveAs = 'version'
- if saveTo == 'video' and vPath is None:
- saveTo = 'custom'
- self.configSaveAs = ConfigSelection(default=saveAs, choices=saveAsOptions)
- self.configSaveTo = ConfigSelection(default=saveTo, choices=saveToOptions)
- self.configAddLang = ConfigYesNo(default=addLang)
- configList = [
- getConfigListEntry(_("Save to"), self.configSaveTo),
- getConfigListEntry(_("Save as"), self.configSaveAs),
- getConfigListEntry(_("Append language to filename"), self.configAddLang),
- ]
- ConfigListScreen.__init__(self, configList, session)
- self.subtitle = subtitle
- self.dPath = dPath
- self.vPath = vPath
- self["fname"] = StaticText()
- self["dpath"] = StaticText()
- self["key_red"] = StaticText(_("Filename"))
- self["key_green"] = StaticText(_("Path"))
- self["key_blue"] = StaticText(_("Reset"))
- self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ColorActions"],
- {
- "right": self.keyRight,
- "left":self.keyLeft,
- "ok":self.confirm,
- "cancel":self.cancel,
- "red": self.editFName,
- "green": self.editDPath,
- "blue":self.resetDefaults
- }, -2)
- self.onLayoutFinish.append(self.updateWindowTitle)
- self.onLayoutFinish.append(self.updateFName)
- self.onLayoutFinish.append(self.updateDPath)
-
- def buildMenu(self):
- configList = []
- configList.append(getConfigListEntry(_("Save to"), self.configSaveTo))
- configList.append(getConfigListEntry(_("Save as"), self.configSaveAs))
- if self.configSaveAs.value != "custom":
- configList.append(getConfigListEntry(_("Append language to filename"), self.configAddLang))
- self["config"].setList(configList)
-
- def updateWindowTitle(self):
- self.setTitle(_("Download options"))
-
- def updateFName(self):
- fname = None
- if self.configSaveAs.value == "video":
- fname = os.path.splitext(os.path.basename(self.vPath))[0]
- elif self.configSaveAs.value == "version":
- fname = os.path.splitext(self.subtitle['filename'])[0]
- if self.configAddLang.value and not self.configSaveAs.value == "custom":
- fname = "%s.%s"%(fname, languageTranslate(self.subtitle['language_name'], 0, 2))
- if fname:
- self["fname"].text = toString(fname)
-
- def updateDPath(self):
- dpath = None
- if self.configSaveTo.value == "video":
- dpath = os.path.dirname(self.vPath)
- elif self.configSaveTo.value == "custom":
- dpath = self.dPath
- if dpath:
- self["dpath"].text = toString(dpath)
-
- def resetDefaults(self):
- for x in self["config"].list:
- x[1].value = x[1].default
- self.buildMenu()
- self.updateFName()
- self.updateDPath()
-
- def editFName(self):
- def editFnameCB(callback=None):
- if callback is not None and len(callback):
- self["fname"].text = callback
- self.configSaveAs.value = "custom"
- self.buildMenu()
- self.updateFName()
- from Screens.VirtualKeyBoard import VirtualKeyBoard
- self.session.openWithCallback(editFnameCB, VirtualKeyBoard, _("Edit Filename"), text= toString(self["fname"].text.strip()))
-
- def editDPath(self):
- def editDPathCB(callback=None):
- if callback is not None and len(callback):
- self["dpath"].text = callback
- self.configSaveTo.value = "custom"
- self["config"].invalidate(self.configSaveTo)
- self.session.openWithCallback(editDPathCB, LocationBox, _("Edit download path"), currDir = toString(self["dpath"].text.strip()))
-
- def confirm(self):
- fname = self["fname"].text.strip()
- if len(fname) == "":
- self.session.open(MessageBox, _("Filename cannot be empty!"), type=MessageBox.TYPE_WARNING)
- return
- dpath = self["dpath"].text.strip()
- if not os.path.isdir(dpath):
- self.session.open(MessageBox, _("Path doesn't exist!"), type=MessageBox.TYPE_WARNING)
- return
- self.close(dpath, fname)
-
- def cancel(self):
- self.close(None, None)
-
- def keyRight(self):
- saveAsConfig = False
- if self['config'].getCurrent()[1] == self.configSaveAs:
- saveAsConfig = True
- currIdx = self.configSaveAs.choices.index(self.configSaveAs.value)
- if currIdx == len(self.configSaveAs.choices) -1:
- nextChoice = self.configSaveAs.choices[0]
- else:
- nextChoice = self.configSaveAs.choices[currIdx+1]
- if nextChoice == 'custom':
- self.configSaveAs.value = nextChoice
- ConfigListScreen.keyRight(self)
- if saveAsConfig:
- self.buildMenu()
- if self['config'].getCurrent()[1] in (self.configSaveAs, self.configAddLang):
- self.updateFName()
- elif self['config'].getCurrent()[1] in (self.configSaveTo,):
- self.updateDPath()
-
- def keyLeft(self):
- saveAsConfig = False
- if self['config'].getCurrent()[1] == self.configSaveAs:
- saveAsConfig = True
- currIdx = self.configSaveAs.choices.index(self.configSaveAs.value)
- if currIdx == 0:
- nextChoice = self.configSaveAs.choices[len(self.configSaveAs.choices)-1]
- else:
- nextChoice = self.configSaveAs.choices[currIdx-1]
- if nextChoice == 'custom':
- self.configSaveAs.value = nextChoice
- ConfigListScreen.keyLeft(self)
- if saveAsConfig:
- self.buildMenu()
- if self['config'].getCurrent()[1] in (self.configSaveAs, self.configAddLang):
- self.updateFName()
- elif self['config'].getCurrent()[1] in (self.configSaveTo,):
- self.updateDPath()
-
-
- class SubsSearchContextMenu(Screen):
- skin = """
- <screen position="center,center" size="400,350" zPosition="5" flags="wfNoBorder">
- <eLabel position="0,0" size="400,350" backgroundColor="#999999" zPosition="0" />
- <widget source="subtitle_release" render="Label" position="5,5" size="390,50" valign="center" halign="center" font="Regular;19" foregroundColor="#66BFFF" zPosition="1" />
- <widget source="context_menu" render="Listbox" position="5,60" size="390,285" scrollbarMode="showNever" zPosition="1">
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (22, [
- MultiContentEntryText(pos = (5, 0), size = (380, 22), font = 0, color = 0xffffff, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = 0), # langname,
- ], True, "showOnDemand"),
- },
- "fonts": [gFont("Regular", 19)],
- "itemHeight":22,
- }
- </convert>
- </widget>
- </screen>
- """
-
- def __init__(self, session):
- Screen.__init__(self, session)
- self.options = []
- self["subtitle_release"] = StaticText()
- self["context_menu"] = List()
-
- def up(self):
- self["context_menu"].selectNext()
-
- def down(self):
- self["context_menu"].selectPrevious()
-
- def right(self):
- self["context_menu"].selectNext()
-
- def left(self):
- self["context_menu"].selectPrevious()
-
- def updateGUI(self, subtitle, options):
- self["subtitle_release"].text = toString(subtitle['filename'])
- self["context_menu"].list = [(o[0],) for o in options]
- self.options = options
-
- def getSelection(self):
- return self.options[self["context_menu"].index][1]
-
-
- class SubsSearch(Screen):
- skin = """
- <screen name="SubsSearch" position="center,center" size="700,520" zPosition="3" >
- <widget source="search_info" render="Listbox" position="10,10" size="680,150" zPosition="3" scrollbarMode="showNever" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (22, [
- MultiContentEntryText(pos = (0, 0), size = (200, 22), font = 0, color = 0xDAA520, flags = RT_HALIGN_LEFT, text = 0), # langname,
- MultiContentEntryText(pos = (205, 0), size = (400, 22), font = 0, flags = RT_HALIGN_LEFT, text = 1)
- ], False, "showNever"),
- },
- "fonts": [gFont("Regular", 18)],
- "itemHeight":22,
- }
- </convert>
- </widget>
- <widget source="header_country" render="Label" position = "5,175" size="120,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_release" render="Label" position = "145,175" size="335,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_provider" render="Label" position = "505, 175" size="135,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_sync" render="Label" position = "650, 175" size="20,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <eLabel position="5,205" size="690,1" backgroundColor="#999999" />
- <widget name="loadmessage" position="5,210" size="690,260" valign="center" halign="center" font="Regular;19" foregroundColor="#ffffff" zPosition="4" />
- <widget name="errormessage" position="5,210" size="690,260" valign="center" halign="center" font="Regular;19" foregroundColor="#ff0000" zPosition="5" />
- <widget source="subtitles" render="Listbox" scrollbarMode="showOnDemand" position="5,210" size="690,260" zPosition="3" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (23, [
- MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (24, 24), png=0), # key,
- MultiContentEntryText(pos = (30, 0), size = (100, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # language,
- MultiContentEntryText(pos = (140, 0), size = (335, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # filename,
- MultiContentEntryText(pos = (500, 0), size = (135, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # size,
- MultiContentEntryPixmapAlphaBlend(pos = (645, 0), size = (24, 24), png=4), # syncPng,
- ], True, "showOnDemand"),
- "old": (23, [
- MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (24, 24), png=0), # key,
- MultiContentEntryText(pos = (30, 0), size = (60, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # language,
- MultiContentEntryText(pos = (100, 0), size = (335, 25), font = 0, flags = RT_HALIGN_LEFT, text = 2), # filename,
- MultiContentEntryText(pos = (445, 0), size = (130, 25), font = 0, flags = RT_HALIGN_LEFT, text = 3), # size,
- MultiContentEntryText(pos = (585, 0), size = (95, 25), font = 0, flags = RT_HALIGN_LEFT, text = 4), # sync,
- ], True, "showOnDemand"),
- },
- "fonts": [gFont("Regular", 18), gFont("Regular", 16)],
- "itemHeight": 23
- }
- </convert>
- </widget>
- <eLabel position="5,475" size="690,1" backgroundColor="#999999" />
- <widget source="key_menu_img" render="Pixmap" pixmap="skin_default/buttons/key_menu.png" position="3,485" size="35,25" transparent="1" alphatest="on" >
- <convert type="ConditionalShowHide" />
- </widget>
- <ePixmap pixmap="skin_default/buttons/key_red.png" position="40,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_red" render="Label" position = "80, 485" size="120,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_green.png" position="205,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_green" render="Label" position = "245, 485" size="110,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_yellow.png" position="365,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_yellow" render="Label" position = "405, 485" size="110,25" font="Regular;20" halign="left" foregroundColor="white" />
- <ePixmap pixmap="skin_default/buttons/key_blue.png" position="525,485" size="35,25" transparent="1" alphatest="on" />
- <widget source="key_blue" render="Label" position = "565, 485" size="110,25" font="Regular;20" halign="left" foregroundColor="white" />
- </screen> """
-
- def __init__(self, session, seeker, searchSettings, filepath=None, searchTitles=None, resetSearchParams=True, standAlone=False):
- Screen.__init__(self, session)
- self.searchSettings = searchSettings
- self.standAlone = standAlone
- searchTitles = searchTitles or [""]
- self.searchParamsHelper = SearchParamsHelper(seeker, searchSettings)
- self.seeker = seeker
- self.searchExpression = searchTitles[0]
- self.searchTitles = searchTitles
- self.filepath = filepath
- self.isLocalFilepath = filepath and os.path.isfile(filepath) or False
- self.searchTitle = searchSettings.title
- self.searchType = searchSettings.type
- self.searchYear = searchSettings.year
- self.searchSeason = searchSettings.season
- self.searchEpisode = searchSettings.episode
- self.searchProvider = searchSettings.provider
- self.searchUseFilePath = searchSettings.useFilePath
- self.__downloadedSubtitles = []
- self.__downloading = False
- self.__searching = False
- self["loadmessage"] = Label("")
- self["errormessage"] = Label("")
- self["search_info"] = List([])
- self["header_country"] = StaticText(_("Language"))
- self["header_release"] = StaticText(_("Release"))
- self["header_provider"] = StaticText(_("Provider"))
- self["header_sync"] = StaticText(_("S"))
- self["subtitles"] = List([])
- self["key_menu_img"] = Boolean()
- self["key_red"] = StaticText(_("Update"))
- self["key_green"] = StaticText(_("Search"))
- self["key_yellow"] = StaticText(_("History"))
- self["key_blue"] = StaticText(_("Settings"))
- self["okCancelActions"] = ActionMap(["OkCancelActions"],
- {
- "ok": self.keyOk,
- "cancel": self.keyCancel,
- })
- self["menuActions"] = ActionMap(["ColorActions", "MenuActions"],
- {
- "red":self.updateSearchParams,
- "green":self.searchSubs,
- "yellow":self.openDownloadHistory,
- "blue":self.openSettings,
- "menu":self.openContextMenu,
- })
-
- self["listActions"] = ActionMap(["DirectionActions"],
- {
- "up": self.keyUp,
- "upRepeated": self.keyUp,
- "down": self.keyDown,
- "downRepeated": self.keyDown,
- "right":self.keyRight,
- "rightRepeated":self.keyRight,
- "left":self.keyLeft,
- "leftRepeated":self.keyLeft,
- }, -2)
-
- self["searchActions"] = ActionMap(["OkCancelActions"],
- {
- "ok":self.cancelSearchSubs,
- "cancel":self.close,
- })
- self["searchActions"].setEnabled(False)
-
- self.__contextMenu = self.session.instantiateDialog(SubsSearchContextMenu)
- self.__contextMenu.hide()
- self["contextMenuActions"] = ActionMap(["DirectionActions", "OkCancelActions", "MenuActions"],
- {
- "up":self.__contextMenu.up,
- "down":self.__contextMenu.down,
- "right":self.__contextMenu.right,
- "left": self.__contextMenu.left,
- "ok": self.contextMenuOk,
- "cancel":self.contextMenuCancel,
- "menu":self.contextMenuCancel,
- })
- self["contextMenuActions"].setEnabled(False)
- self.message = Message(self['loadmessage'], self['errormessage'])
- self.onLayoutFinish.append(self.updateTitle)
- self.onLayoutFinish.append(self.__getSubtitlesRenderer)
- if resetSearchParams:
- self.onLayoutFinish.append(self.detectSearchParams)
- self.onLayoutFinish.append(self.searchParamsHelper.updateProviders)
- self.onLayoutFinish.append(self.updateSearchInfoList)
- self.onLayoutFinish.append(self.updateBottomMenu)
- if not searchSettings.manualSearch.value and not self.standAlone:
- self.onLayoutFinish.append(self.searchSubs)
- else:
- self.onLayoutFinish.append(self.searchMessage)
- self.onClose.append(self.__contextMenu.hide)
- self.onClose.append(self.__contextMenu.doClose)
- self.onClose.append(self.message.hide)
- self.onClose.append(self.searchParamsHelper.resetSearchParams)
- self.onClose.append(self.stopSearchSubs)
- self.onClose.append(self.closeSeekers)
-
- def __getSubtitlesRenderer(self):
- from Components.Sources.Source import Source
- from Components.Renderer.Listbox import Listbox
- for r in self.renderer:
- if isinstance(r, Listbox):
- s = r
- while not isinstance(s,Source):
- s = s.source
- if s == self['subtitles']:
- self.__listboxRenderer = r
- break
-
- def updateTitle(self):
- self.title = _("Subtitles search")
-
- def updateSearchInfoList(self):
- searchInfoList = []
- lang1 = self.searchSettings.lang1.value
- lang2 = self.searchSettings.lang2.value
- lang3 = self.searchSettings.lang3.value
- lang1 = lang1 in LanguageCodes and LanguageCodes[lang1][0] or lang1
- lang2 = lang2 in LanguageCodes and LanguageCodes[lang2][0] or lang2
- lang3 = lang3 in LanguageCodes and LanguageCodes[lang3][0] or lang3
- langs = [lang1]
- if lang2 not in langs:
- langs.append(lang2)
- if lang3 not in langs:
- langs.append(lang3)
- languages = ", ".join(_(lang) for lang in langs)
- year = self.searchYear.value and str(self.searchYear.value) or ""
- season = self.searchSeason.value and str(self.searchSeason.value) or ""
- episode = self.searchEpisode.value and str(self.searchEpisode.value) or ""
- useFilePathStr = self.searchUseFilePath.value and _("yes") or _("no")
- searchInfoList.append((_("Title") + ":", self.searchTitle.value))
- searchInfoList.append((_("Type") + ":", self.searchType.getText()))
- if self.searchType.value == "movie":
- searchInfoList.append((_("Year") + ":", year))
- else:
- searchInfoList.append((_("Season") + ":", season))
- searchInfoList.append((_("Episode") + ":", episode))
- searchInfoList.append((_("Provider") + ":", self.searchProvider.getText()))
- searchInfoList.append((_("Preferred languages") + ":", languages))
- searchInfoList.append((_("Use File path") + ":", useFilePathStr))
- self['search_info'].list = searchInfoList
-
- def updateSubsList(self):
- imgDict = {
- 'sync':loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'check.png')),
- 'unk':loadPNG(os.path.join(os.path.dirname(__file__), 'img', 'countries', 'UNK.png'))
- }
- subtitleListGUI = []
- for sub in self.subtitlesList:
- sync = 'sync' in sub and sub['sync'] or False
- if sub['country'] not in imgDict:
- countryImgPath = os.path.join(os.path.dirname(__file__), 'img', 'countries', sub['country'] + '.png')
- if os.path.isfile(countryImgPath):
- countryPng = loadPNG(countryImgPath)
- imgDict[sub['country']] = countryPng
- else:
- countryPng = imgDict['unk']
- syncPng = sync and imgDict['sync'] or None
- subtitleListGUI.append((countryPng, _(toString(sub['language_name'])),
- toString(sub['filename']), toString(sub['provider']), syncPng),)
- imgDict = None
- self['subtitles'].list = subtitleListGUI
-
- def updateBottomMenu(self):
- if self.__searching:
- self["key_red"].text = ""
- self["key_green"].text = ""
- self["key_yellow"].text = ""
- self["key_blue"].text = ""
- self["key_menu_img"].boolean = False
- elif self.__downloading:
- self["key_red"].text = ""
- self["key_green"].text = ""
- self["key_yellow"].text = ""
- self["key_blue"].text = ""
- self["key_menu_img"].boolean = False
- else:
- self["key_red"].text = (_("Update"))
- self["key_green"].text = (_("Search"))
- self["key_yellow"].text = (_("History"))
- self["key_blue"].text = (_("Settings"))
- if self["subtitles"].count() > 0:
- self["key_menu_img"].boolean = True
-
- def updateActionMaps(self):
- if self.__searching:
- self["okCancelActions"].setEnabled(False)
- self["listActions"].setEnabled(False)
- self["menuActions"].setEnabled(False)
- self["searchActions"].setEnabled(True)
- self["contextMenuActions"].setEnabled(False)
- elif self.__downloading:
- self["okCancelActions"].setEnabled(False)
- self["listActions"].setEnabled(False)
- self["menuActions"].setEnabled(False)
- self["searchActions"].setEnabled(False)
- self["contextMenuActions"].setEnabled(False)
- elif self.__contextMenu.shown:
- self["okCancelActions"].setEnabled(False)
- self["listActions"].setEnabled(False)
- self["menuActions"].setEnabled(False)
- self["searchActions"].setEnabled(False)
- self["contextMenuActions"].setEnabled(True)
- else:
- self["okCancelActions"].setEnabled(True)
- self["listActions"].setEnabled(True)
- self["menuActions"].setEnabled(True)
- self["searchActions"].setEnabled(False)
- self["contextMenuActions"].setEnabled(False)
-
- def detectSearchParams(self):
- self.searchParamsHelper.detectSearchParams(self.searchExpression)
-
- def closeSeekers(self):
- for seeker in self.seeker.seekers:
- seeker.close()
-
- def keyOk(self):
- if self['subtitles'].count():
- self.downloadSubs(self.subtitlesList[self["subtitles"].index])
-
- def keyCancel(self):
- self.close()
-
- def keyUp(self):
- if self['subtitles'].count():
- self.message.hide()
- self['subtitles'].selectPrevious()
-
- def keyDown(self):
- if self['subtitles'].count():
- self.message.hide()
- self['subtitles'].selectNext()
-
- def keyRight(self):
- if self['subtitles'].count():
- self.message.hide()
- self.__listboxRenderer.move(self.__listboxRenderer.instance.pageDown)
-
- def keyLeft(self):
- if self['subtitles'].count():
- self.message.hide()
- self.__listboxRenderer.move(self.__listboxRenderer.instance.pageUp)
-
- def searchMessage(self):
- self.message.info(_("Update search parameters if not correct\n and press green button for search"))
-
- def searchSubs(self):
- def searchSubsUpdate(args):
- pfinished, status, value = args
- if status:
- self.__finished[pfinished] = value
- else:
- self.__finished[pfinished] = {'list':[], 'status':status,'message':str(value)}
- progressMessage = "%s - %d%%" % (_("loading subtitles list"), int(len(self.__finished.keys()) / float(len(provider)) * 100))
- progressMessage +="\n" + _("subtitles found") + " (%d)"%(sum(len(self.__finished[p]['list']) for p in self.__finished.keys()))
- progressMessage +="\n\n" + _("Press OK to Stop")
- self.message.info(progressMessage)
-
- self.stopSearchSubs()
- self.subtitlesList = []
- self.subtitlesDict = {}
- self.__finished = {}
- p = self.searchParamsHelper.getSearchParams()
- langs, title, year, tvshow, season, episode = p[1], p[2], p[3], p[4], p[5], p[6]
- providers = self.seeker.getProviders(langs, not tvshow, tvshow)
- if self.searchProvider.value == "all":
- provider = providers
- else:
- provider = [p for p in providers if p.id == self.searchProvider.value]
- filepath = self.searchUseFilePath.value and self.filepath or None
- timeout = float(self.searchSettings.timeout.value)
- params = {
- 'search':{
- 'providers':[p.id for p in provider],
- 'title':title,
- 'filepath':filepath,
- 'langs':langs,
- 'year': year,
- 'tvshow': tvshow,
- 'season': season,
- 'episode': episode,
- 'timeout': timeout
- },
- 'settings': dict((s.id, s.settings_provider.getSettingsDict()) for s in self.seeker.seekers)
- }
- progressMessage = "%s - %d%%" % (_("loading subtitles list"), 0)
- progressMessage +="\n" + _("subtitles found") + " (%d)"% 0
- progressMessage +="\n\n" + _("Press OK to Stop")
- self.message.info(progressMessage)
- self.__searching = True
- self.updateActionMaps()
- self.updateSubsList()
- self.updateBottomMenu()
- SubsSearchProcess().start(params, searchSubsUpdate, self.searchSubsSuccess, self.searchSubsError)
-
- def cancelSearchSubs(self):
- self.stopSearchSubs()
- self.searchSubsSuccess(self.__finished)
-
- def stopSearchSubs(self):
- for p in SubsSearchProcess.processes:
- p.stop()
- print len(SubsSearchProcess.processes), 'processes still running'
-
- def searchSubsSuccess(self, subtitles):
- print '[SubsSearch] search success'
- self.message.hide()
- self.subtitlesDict = subtitles
- subtitlesList = self.seeker.getSubtitlesList(subtitles)
- subtitlesList = self.seeker.sortSubtitlesList(subtitlesList, sort_sync=True)
- langs = [self.searchSettings.lang1.value,
- self.searchSettings.lang2.value,
- self.searchSettings.lang3.value]
- if self.searchSettings.defaultSort.value == 'lang':
- subtitlesList = self.seeker.sortSubtitlesList(subtitlesList, langs, sort_langs=True)
- elif self.searchSettings.defaultSort.value == 'provider':
- subtitlesList = self.seeker.sortSubtitlesList(subtitlesList, langs, sort_provider=True)
- self.subtitlesList = subtitlesList
- if len(self.subtitlesList) == 0:
- noSubtitlesMessage = _("No subtitles found :(")
- noSubtitlesMessage += "\n" + _("Try update(simplify) search expression and try again..")
- self.message.info(noSubtitlesMessage)
- self.__searching = False
- self.updateSubsList()
- self.updateBottomMenu()
- self.updateActionMaps()
-
- def searchSubsError(self, error):
- print '[SubsSearch] search error', str(error)
- self.message.error(error.message, 4000)
- self.subtitlesList = []
- self.subtitlesDict = {}
- self.updateSubsList()
- self.__searching = False
- self.updateBottomMenu()
- self.updateActionMaps()
-
- def downloadSubs(self, subtitle, downloadDir=None, fName=None, saveAs=None,
- saveTo=None, langToFilename=None, askOverwrite=None, closeOnSuccess = None):
-
- if saveAs is None:
- saveAs = self.searchSettings.saveAs.value
- if saveAs == 'video' and not self.isLocalFilepath:
- saveAs = self.searchSettings.saveAsFallback.value
- if langToFilename is None:
- langToFilename = self.searchSettings.addLangToSubsFilename.value
- if askOverwrite is None:
- askOverwrite = self.searchSettings.askOverwriteExistingSubs.value
- if closeOnSuccess is None:
- closeOnSuccess = self.searchSettings.loadSubtitlesAfterDownload.value
- if downloadDir is None:
- if saveTo is None:
- saveTo = self.searchSettings.saveTo.value
- if saveTo == 'video' and self.isLocalFilepath:
- downloadDir = os.path.dirname(self.filepath)
- else:
- downloadDir = self.searchSettings.downloadPath.value
- self.__downloading = True
- self.__downloadingSubtitle = subtitle
- self.updateActionMaps()
- self.updateBottomMenu()
- self.message.info(_('downloading subtitles...'))
- self.__closeOnSuccess = closeOnSuccess
- settings = {
- "save_as": saveAs,
- "lang_to_filename":langToFilename,
- "ask_overwrite":askOverwrite
- }
- self.seeker.downloadSubtitle(self.downloadSubsSuccess, self.downloadSubsError, self.downloadSubsCancel, subtitle, self.subtitlesDict, settings, downloadDir, fName)
-
- def downloadSubsSuccess(self, subFile):
- print '[SubsSearch] download success %s' % toString(subFile)
- dsubtitle = {
- "name":toUnicode(os.path.basename(subFile)),
- "country": toUnicode(self.__downloadingSubtitle['country']),
- "provider":toUnicode(self.__downloadingSubtitle['provider']),
- "fpath": toUnicode(subFile),
- }
- if self.searchSettings.downloadHistory.enabled.value:
- fpath = os.path.join(self.searchSettings.downloadHistory.path.value, 'hsubtitles.json')
- try:
- subtitles = json.load(open(fpath,"r"))
- except Exception as e:
- print '[SubsSearch] cannot load download history:', e
- subtitles = []
- limit = int(self.searchSettings.downloadHistory.limit.value)
- if dsubtitle in subtitles:
- subtitles.remove(dsubtitle)
- if len(subtitles) >= limit:
- print '[SubsSearch] download history limit reached!, removing oldest entries'
- del subtitles[-(len(subtitles)-limit):]
- subtitles.insert(0, dsubtitle)
- try:
- json.dump(subtitles, open(fpath,'w'))
- except Exception as e:
- print '[SubsSearch] cannot save download history:', e
- self.__downloadedSubtitles.append(dsubtitle)
- self.afterDownloadSuccess(dsubtitle)
- self.message.hide()
- self.__downloading = False
- del self.__downloadingSubtitle
- self.updateBottomMenu()
- self.updateActionMaps()
-
- def downloadSubsError(self, e):
- print '[SubsSearch] download error', str(e)
- self.__downloading = False
- del self.__downloadingSubtitle
- self.updateBottomMenu()
- self.updateActionMaps()
- errorMessageFormat = "[{0}]: {1}"
- if isinstance(e, SubtitlesDownloadError):
- if e.code == SubtitlesErrors.CAPTCHA_RETYPE_ERROR:
- self.message.error(errorMessageFormat.format(e.provider, _("captcha doesn't match, try again...")), 4000)
- elif e.code == SubtitlesErrors.INVALID_CREDENTIALS_ERROR:
- self.message.error(errorMessageFormat.format(e.provider, _("invalid credentials provided, correct them and try again")), 4000)
- elif e.code == SubtitlesErrors.NO_CREDENTIALS_ERROR:
- self.message.error(errorMessageFormat.format(e.provider, _("no credentials provided, set them and try again")), 4000)
- else:
- self.message.error(str(e), 4000)
- else:
- print "".join(traceback.format_tb(e.tb))
- self.message.error(str(e), 4000)
-
- def downloadSubsCancel(self):
- print '[SubsSearch] download cancelled'
- self.__downloading = False
- del self.__downloadingSubtitle
- self.updateBottomMenu()
- self.updateActionMaps()
- self.message.hide()
-
- def afterDownloadSuccess(self, subtitle):
- if not self.standAlone and self.__closeOnSuccess:
- self.close(subtitle['fpath'])
- self.__closeOnSuccess = None
-
- def openContextMenu(self):
- if not self["subtitles"].count() > 0:
- return
- downloadOptions = [
- (_("Download (user defined)"), "d_custom"),
- (_("Download (next to video)"), "d_video"),
- (_("Download (more...)"), "d_more"),
- ]
- downloadAndLoadOptions = [
- (_("Download and Load (user defined) "), "do_custom"),
- (_("Download and Load (next to video)"), "do_video"),
- (_("Download and Load (more...)"), "do_more"),
- ]
- if not self.isLocalFilepath or self.standAlone:
- downloadOptions.remove(downloadOptions[1])
- downloadAndLoadOptions.remove(downloadAndLoadOptions[1])
- if self.standAlone:
- del downloadAndLoadOptions[:]
- options = []
- if not self.searchSettings.loadSubtitlesAfterDownload.value or self.standAlone:
- if len(downloadOptions) > 0:
- if self.searchSettings.saveTo.value == "custom":
- options.append(downloadOptions[0])
- elif self.searchSettings.saveTo.value == "video" and self.isLocalFilepath:
- options.append(downloadOptions[1])
- elif self.searchSettings.saveTo.value == "more":
- options.append(downloadOptions[-1])
- for o in downloadOptions:
- if o not in options:
- options.append(o)
- options.extend(downloadAndLoadOptions)
- else:
- if len(downloadAndLoadOptions) > 0:
- if self.searchSettings.saveTo.value == "custom":
- options.append(downloadAndLoadOptions[0])
- elif self.searchSettings.saveTo.value == "video" and self.isLocalFilepath:
- options.append(downloadAndLoadOptions[1])
- elif self.searchSettings.saveTo.value == "more":
- options.append(downloadAndLoadOptions[-1])
- for o in downloadAndLoadOptions:
- if o not in options:
- options.append(o)
- options.extend(downloadOptions)
-
- subtitle = self.subtitlesList[self["subtitles"].index]
- self.__contextMenu.updateGUI(subtitle, options)
- self.__contextMenu.show()
- self.updateActionMaps()
-
- def contextMenuOk(self):
- def downloadMoreCB(dPath, fName):
- if dPath and fName:
- self.downloadSubs(subtitle, downloadDir=dPath, fName=fName, closeOnSuccess=closeOnSuccess)
- answer = self.__contextMenu.getSelection()
- self.__contextMenu.hide()
- self.updateActionMaps()
- subtitle = self.subtitlesList[self["subtitles"].index]
- if answer == "d_custom":
- self.downloadSubs(subtitle, saveTo='custom', closeOnSuccess=False)
- elif answer == 'd_video':
- self.downloadSubs(subtitle, saveTo='video', closeOnSuccess=False)
- elif answer == 'do_custom':
- self.downloadSubs(subtitle, saveTo='custom', closeOnSuccess=True)
- elif answer == 'do_video':
- self.downloadSubs(subtitle, saveTo='video', closeOnSuccess=True)
- elif answer == 'do_more':
- closeOnSuccess = True
- elif answer == 'd_more':
- closeOnSuccess = False
- if answer == 'd_more' or answer == 'do_more':
- saveAs = self.searchSettings.saveAs.value
- saveTo = self.searchSettings.saveTo.value
- addLang = self.searchSettings.addLangToSubsFilename.value
- dPath = self.searchSettings.downloadPath.value
- vPath = self.filepath
- self.session.openWithCallback(downloadMoreCB, SubsSearchDownloadOptions,
- subtitle, saveAs, saveTo, addLang, dPath, vPath)
-
- def contextMenuCancel(self):
- self.__contextMenu.hide()
- self.updateActionMaps()
-
- def updateSearchParams(self):
- def updateSearchParamsCB(callback=None):
- if callback:
- self.updateSearchInfoList()
- self.updateBottomMenu()
- if not self.searchSettings.manualSearch.value:
- self.searchSubs()
- self.session.openWithCallback(updateSearchParamsCB, SubsSearchParamsMenu, self.seeker, self.searchSettings, self.searchTitles, False)
-
- def openDownloadHistory(self):
- def openDownloadHistoryCB(subtitles, subtitle=None):
- if len(subtitles) > 0:
- if not self.searchSettings.downloadHistory.enabled.value:
- for i in self.__downloadedSubtitles:
- if i in subtitles:
- subtitles.remove(i)
- try:
- json.dump(subtitles, open(fpath,"w"))
- except Exception as e:
- print '[SubsSearch] save download history:', e
- if subtitle is not None:
- if not self.standAlone:
- self.close(subtitle)
-
- fpath = os.path.join(self.searchSettings.downloadHistory.path.value, 'hsubtitles.json')
- try:
- subtitles = json.load(open(fpath,"r"))
- except Exception as e:
- print '[SubsSearch] cannot load download history:', e
- subtitles = []
- self.session.openWithCallback(openDownloadHistoryCB, SubsDownloadedSelection,
- subtitles, self.searchSettings.downloadHistory, self.__downloadedSubtitles)
-
- def openSettings(self):
- def openSettingsCB(langChanged = False):
- self.seeker.tmp_path = self.searchSettings.tmpPath.value
- self.seeker.download_path = self.searchSettings.downloadPath.value
- self.searchParamsHelper.updateProviders()
- self.updateSearchInfoList()
- self.updateBottomMenu()
- if langChanged and not self.searchSettings.manualSearch.value:
- self.searchSubs()
-
- self.session.openWithCallback(openSettingsCB, SubsSearchSettings, self.searchSettings, self.seeker, self.isLocalFilepath)
-
-
- class SubsSearchSettings(Screen, ConfigListScreen):
-
- @staticmethod
- def getConfigList(searchSettings):
- configList = []
- configList.append(getConfigListEntry(_("Preferred subtitles language") + ' 1', searchSettings.lang1))
- configList.append(getConfigListEntry(_("Preferred subtitles language") + ' 2', searchSettings.lang2))
- configList.append(getConfigListEntry(_("Preferred subtitles language") + ' 3', searchSettings.lang3))
- configList.append(getConfigListEntry(_("Preferred Movie provider"), searchSettings.movieProvider))
- configList.append(getConfigListEntry(_("Preferred TV show provider"), searchSettings.tvshowProvider))
- configList.append(getConfigListEntry(_("Manual search"), searchSettings.manualSearch))
- configList.append(getConfigListEntry(_("Subtitles provider timeout"), searchSettings.timeout))
- configList.append(getConfigListEntry(_("Check search parameters before subtitles search"), searchSettings.openParamsDialogOnSearch))
- configList.append(getConfigListEntry(_("Sort subtitles list by"), searchSettings.defaultSort))
- configList.append(getConfigListEntry(_("Save subtitles as"), searchSettings.saveAs))
- configList.append(getConfigListEntry(_("Save subtitles as (fallback)"), searchSettings.saveAsFallback))
- configList.append(getConfigListEntry(_("Add subtitle's language to filename"), searchSettings.addLangToSubsFilename))
- configList.append(getConfigListEntry(_("Save subtitles to"), searchSettings.saveTo))
- configList.append(getConfigListEntry(_("Subtitles download path"), searchSettings.downloadPath))
- configList.append(getConfigListEntry(_("Subtitles temp path"), searchSettings.tmpPath))
- configList.append(getConfigListEntry(_("Always ask before overwriting existing subtitles"), searchSettings.askOverwriteExistingSubs))
- configList.append(getConfigListEntry(_("Load subtitles after download"), searchSettings.loadSubtitlesAfterDownload))
- historySettings = searchSettings.downloadHistory
- configList.append(getConfigListEntry(_("Save downloaded subtitles to history"), historySettings.enabled))
- if historySettings.enabled.value:
- configList.append(getConfigListEntry(_("Load/Save download history directory"), historySettings.path))
- return configList
-
- skin = """
- <screen name="SubsSearch" position="center,center" size="650,500" zPosition="3" >
- <widget name="key_red" position="10,5" zPosition="1" size="150,45" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_green" position="170,5" zPosition="1" size="150,45" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_yellow" position="330,5" zPosition="1" size="150,45" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" shadowOffset="-2,-2" shadowColor="black" />
- <widget name="key_blue" position="490,5" zPosition="1" size="150,45" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" shadowOffset="-2,-2" shadowColor="black" />
- <eLabel position="-1,55" size="650,1" backgroundColor="#999999" />
- <widget name="config" position="10,75" size="630,178" scrollbarMode="showOnDemand" />
- <!-- <eLabel position="5,245" size="640,1" backgroundColor="#999999" /> -->
- <widget source="header_name" render="Label" position = "10,265" size="200,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_lang" render="Label" position = "220,265" size="180,25" font="Regular;18" halign="left" foregroundColor="#0xcccccc" />
- <widget source="header_state" render="Label" position = "410, 265" size="200,25" font="Regular;18" halign="right" foregroundColor="#0xcccccc" />
- <eLabel position="5,295" size="640,1" backgroundColor="#999999" />
- <widget source="providers" render="Listbox" scrollbarMode="showOnDemand" position="10,305" size="630,185" zPosition="3" transparent="1" >
- <convert type="TemplatedMultiContent">
- {"templates":
- {"default": (23, [
- MultiContentEntryText(pos = (0, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # name,
- MultiContentEntryText(pos = (210, 0), size = (180, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # lang,
- MultiContentEntryText(pos = (400, 0), size = (200, 25), font = 0, flags = RT_HALIGN_RIGHT, text = 2, color=0xFF000003) # enabled,
- ], True, "showOnDemand"),
- "notselected": (23, [
- MultiContentEntryText(pos = (0, 0), size = (200, 25), font = 0, flags = RT_HALIGN_LEFT, text = 0), # name,
- MultiContentEntryText(pos = (210, 0), size = (180, 25), font = 0, flags = RT_HALIGN_LEFT, text = 1), # lang,
- MultiContentEntryText(pos = (400, 0), size = (200, 25), font = 0, flags = RT_HALIGN_RIGHT, text = 2, color=0xFF000003) # enabled,
- ], False, "showOnDemand")
- },
- "fonts": [gFont("Regular", 18), gFont("Regular", 16)],
- "itemHeight": 23
- }
- </convert>
- </widget>
- </screen> """
-
- FOCUS_CONFIG, FOCUS_PROVIDERS = range(2)
-
- def __init__(self, session, searchSettings, seeker, isLocalFilepath=True):
- Screen.__init__(self, session)
- ConfigListScreen.__init__(self, [], session=session)
- self.searchSettings = searchSettings
- self.searchParamsHelper = SearchParamsHelper(seeker, searchSettings)
- self.providers = seeker.seekers
- self.isLocalFilepath = isLocalFilepath
- self.focus = self.FOCUS_CONFIG
- self['providers'] = List([])
- self["header_name"] = StaticText(_("Provider name"))
- self["header_lang"] = StaticText(_("Supported languages"))
- self["header_state"] = StaticText(_("State"))
- self["key_green"] = Label(_("Save"))
- self["key_red"] = Label(_("Cancel"))
- self["key_blue"] = Label(_("Reset Defaults"))
- self["key_yellow"] = Label(_("Switch List"))
- self["actions"] = ActionMap(["DirectionActions", "SetupActions", "OkCancelActions", "ColorActions", "ListboxActions"],
- {
- "ok": self.keyOk,
- "cancel": self.keyCancel,
- "save":self.keySave,
- "up": self.keyUp,
- "down": self.keyDown,
- "right":self.keyRight,
- "left":self.keyLeft,
- "blue":self.resetDefaults,
- "yellow":self.switchList,
- "pageUp":self.switchList,
- "pageDown":self.switchList,
- }, -2)
- self.onLayoutFinish.append(self.setWindowTitle)
- self.onLayoutFinish.append(self.buildMenu)
- self.onLayoutFinish.append(self.updateProvidersList)
- self.onLayoutFinish.append(self.setConfigFocus)
-
- def setWindowTitle(self):
- self.setTitle(_("Subtitles search settings"))
-
- def buildMenu(self):
- self["config"].setList(self.getConfigList(self.searchSettings))
-
- def updateProvidersList(self):
- providerListGUI = []
- for provider in self.providers:
- providerName = provider.provider_name
- providerLangs = ','.join(provider.supported_langs)
- if provider.error is not None:
- providerState = _("error")
- providerStateColor = 0xff0000
- elif provider.settings_provider.getSetting('enabled'):
- providerState = _("enabled")
- providerStateColor = 0x00ff00
- else:
- providerState = _("disabled")
- providerStateColor = 0xffff00
- providerListGUI.append((toString(providerName), providerLangs, providerState, providerStateColor))
- self['providers'].list = providerListGUI
-
- def setConfigFocus(self):
- self.focus = self.FOCUS_CONFIG
- self['config'].instance.setSelectionEnable(True)
- self['providers'].style = 'notselected'
-
- def switchList(self):
- if self.focus == self.FOCUS_PROVIDERS:
- self.focus = self.FOCUS_CONFIG
- self['providers'].style = "notselected"
- self['config'].instance.setSelectionEnable(True)
- else:
- self.focus = self.FOCUS_PROVIDERS
- self['config'].instance.setSelectionEnable(False)
- self['providers'].style = 'default'
-
- def keyOk(self):
- if self.focus == self.FOCUS_PROVIDERS:
- provider = self.providers[self['providers'].index]
- if provider.error:
- self.showProviderError(provider)
- else:
- self.openProviderSettings(provider)
- else:
- current = self['config'].getCurrent()[1]
- if current == self.searchSettings.downloadPath:
- currentPath = self.searchSettings.downloadPath.value
- self.session.openWithCallback(self.setDownloadPath, LocationBox, "", "", currentPath)
- elif current == self.searchSettings.tmpPath:
- currentPath = self.searchSettings.tmpPath.value
- self.session.openWithCallback(self.setTmpPath, LocationBox, "", "", currentPath)
- elif current == self.searchSettings.downloadHistory.path:
- currentPath = self.searchSettings.downloadHistory.path.value
- self.session.openWithCallback(self.setHistoryPath, LocationBox, "", "", currentPath)
- elif current in [self.searchSettings.lang1,
- self.searchSettings.lang2,
- self.searchSettings.lang3]:
- self.session.openWithCallback(self.setLanguage, MyLanguageSelection, current.value)
-
- def setLanguage(self, language=None):
- if language:
- self['config'].getCurrent()[1].value = language
- self.buildMenu()
-
- def setDownloadPath(self, downloadPath=None):
- if downloadPath:
- self.searchSettings.downloadPath.value = downloadPath
- self.buildMenu()
-
- def setTmpPath(self, tmpPath=None):
- if tmpPath:
- self.searchSettings.tmpPath.value = tmpPath
- self.buildMenu()
-
- def setHistoryPath(self, historyPath=None):
- if historyPath:
- self.searchSettings.downloadHistory.path.value = historyPath
- self.buildMenu()
-
- def keySave(self):
- langChanged = (self.searchSettings.lang1.isChanged() or
- self.searchSettings.lang2.isChanged() or
- self.searchSettings.lang3.isChanged())
- for x in self["config"].list:
- x[1].save()
- self.close(langChanged)
-
- def keyCancel(self):
- for x in self["config"].list:
- x[1].cancel()
- self.close()
-
- def keyUp(self):
- if self.focus == self.FOCUS_CONFIG:
- self['config'].instance.moveSelection(self["config"].instance.moveUp)
- else:
- if self['providers'].index == 0:
- self['providers'].index = len(self['providers'].list) - 1
- else:
- self['providers'].selectPrevious()
-
- def keyDown(self):
- if self.focus == self.FOCUS_CONFIG:
- self['config'].instance.moveSelection(self["config"].instance.moveDown)
- else:
- if self['providers'].index == len(self['providers'].list) -1:
- self['providers'].index = 0
- else:
- self['providers'].selectNext()
-
- def keyRight(self):
- if self.focus == self.FOCUS_CONFIG:
- ConfigListScreen.keyRight(self)
- if self['config'].getCurrent()[1] in [self.searchSettings.saveTo,
- self.searchSettings.downloadHistory.enabled]:
- self.buildMenu()
-
- def keyLeft(self):
- if self.focus == self.FOCUS_CONFIG:
- ConfigListScreen.keyLeft(self)
- if self['config'].getCurrent()[1] in [self.searchSettings.saveTo,
- self.searchSettings.downloadHistory.enabled]:
- self.buildMenu()
-
- def resetDefaults(self):
- for x in self["config"].list:
- x[1].value = x[1].default
- self.buildMenu()
-
- def showProviderError(self, provider):
- providerError = provider.error
- if isinstance(providerError, tuple):
- err_msg = providerError[1]
- else:
- err_msg = "unknown error"
- if isinstance(providerError,Exception):
- if isinstance(providerError, ImportError):
- # No module named ...
- err_msg= _("missing") + " python-%s "% (providerError.message.split()[-1]) + _("library")
- else:
- err_msg = providerError.message
- msg = "%s: %s"%(provider.provider_name, err_msg)
- self.session.open(MessageBox, msg, MessageBox.TYPE_WARNING, timeout = 5)
-
- def openProviderSettings(self, provider):
- self.session.openWithCallback(self.openProviderSettingsCB, SubsSearchProviderMenu, provider)
-
- def openProviderSettingsCB(self, changed=False):
- if changed:
- configIndex = self['config'].getCurrentIndex()
- providersIndex = self['providers'].index
- self.updateProvidersList()
- self.searchParamsHelper.updateProviders()
- self.buildMenu()
- self['config'].setCurrentIndex(configIndex)
- self['providers'].index = providersIndex
-
- class SubsSearchParamsMenu(Screen, ConfigListScreen):
- LIST_CONFIG = 0
- LIST_SUGGESTIONS = 1
- LIST_HISTORY = 2
-
- def __init__(self, session, seeker, searchSettings, titleList=None, resetSearchParams=True, enabledList=True, windowTitle=None):
- s = getDesktop(0).size()
- desktopSize = (s.width(), s.height())
- windowSize = (550, 330)
- self.skin = """
- <screen position="center,%d" size="550,330" >
- <widget source="sourceTitleInfo" render="Label" position="10,10" size="530,25" halign="center" font="Regular;22" foregroundColor="#66BFFF" />
- <widget source="sourceTitle" render="Label" position="10,35" size="530,55" halign="center" valign="center" font="Regular;21" />
- <widget source="searchTitleParams" render="Label" position="10,90" size="530,25" halign="center" font="Regular;22" foregroundColor="#ffbb00"/>
- <eLabel position="10,120" size="530,1" backgroundColor="#999999" />
- <widget name="config" position="10,130" size="530,160" scrollbarMode="showOnDemand" />
- <eLabel position="10,285" size="530,1" backgroundColor="#999999" />
- <widget source="pressOkTitleInfo" render="Label" position="10,295" size="530,25" halign="center" font="Regular;21" />
- </screen>""" % ((desktopSize[1] / 2) - (windowSize[1] / 2) + 50)
-
-
- Screen.__init__(self, session)
- ConfigListScreen.__init__(self, [], session=session)
- self["config"] = MyConfigList([], session, enabledList)
- if not self.handleInputHelpers in self["config"].onSelectionChanged:
- self["config"].onSelectionChanged.append(self.handleInputHelpers)
- self.searchParamsHelper = SearchParamsHelper(seeker, searchSettings)
- self.searchSettings = searchSettings
- if titleList is None:
- titleList = []
- self.sourceTitleList = titleList
- self.sourceTitle = titleList and titleList[0] or ""
- self.currentList = self.LIST_CONFIG
- self.windowTitle = windowTitle
- if len(self.sourceTitleList) == 0:
- self['sourceTitleInfo'] = StaticText(_("Source title not provided"))
- else:
- self['sourceTitleInfo'] = StaticText("%s [%d/%d]" % (_("Source title"), 1, len(self.sourceTitleList)))
- self['sourceTitle'] = StaticText(self.sourceTitle)
- self['searchTitleParams'] = StaticText(_("Search parameters"))
- self['pressOkTitleInfo'] = StaticText(_("Press OK to confirm"))
- self["suggestionActions"] = ActionMap(["DirectionActions", "ColorActions", "OkCancelActions"],
- {
- "red": self.cancelToHistoryList,
- "green": self.cancelToSuggestionsList,
- "ok": self.switchToConfigList,
- "cancel":self.cancelToConfigList,
- "right": self.keyRight,
- "rightRepeated": self.keyRight,
- "left": self.keyLeft,
- "leftRepeated": self.keyLeft,
- "up": self.keyUp,
- "upRepeated": self.keyUp,
- "down": self.keyDown,
- "downRepeated": self.keyDown
- }, -2)
-
- self["configActions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"],
- {
- "ok": self.keyOK,
- "cancel": self.keyCancel,
- "green": self.switchToSuggestionsList,
- "red": self.switchToHistoryList,
- "blue": self.toggleSourceTitle,
- "right": self.keyRight,
- "rightRepeated": self.keyRight,
- "left": self.keyLeft,
- "leftRepeated": self.keyLeft,
- "up": self.keyUp,
- "upRepeated": self.keyUp,
- "down": self.keyDown,
- "downRepeated": self.keyDown
- }, -2)
-
- self['suggestionActions'].setEnabled(False)
- if resetSearchParams and titleList is not None:
- self.onLayoutFinish.append(self.detectSearchParams)
- self.onLayoutFinish.append(self.buildMenu)
- self.onLayoutFinish.append(self.setWindowTitle)
- self.onLayoutFinish.append(self.saveAll)
- self.onClose.append(self.removeSuggestionWindows)
-
- def setWindowTitle(self):
- if self.windowTitle is not None:
- self.setTitle(self.windowTitle)
- else: self.setTitle(_("Update Search params"))
-
- def buildMenu(self):
- menuList = []
- menuList.append(getConfigListEntry(_("Title") , self.searchSettings.title))
- menuList.append(getConfigListEntry(_("Type") , self.searchSettings.type))
- if self.searchSettings.type.value == "movie":
- menuList.append(getConfigListEntry(_("Year") , self.searchSettings.year))
- else:
- menuList.append(getConfigListEntry(_("Season") , self.searchSettings.season))
- menuList.append(getConfigListEntry(_("Episode") , self.searchSettings.episode))
- menuList.append(getConfigListEntry(_("Provider") , self.searchSettings.provider))
- menuList.append(getConfigListEntry(_("Use File path"), self.searchSettings.useFilePath))
- self["config"].list = menuList
- self["config"].setList(menuList)
-
- def detectSearchParams(self):
- self.searchParamsHelper.detectSearchParams(self.sourceTitle)
- self.searchParamsHelper.updateProviders()
-
- def toggleSourceTitle(self):
- if len(self.sourceTitleList) == 0:
- return
- currIdx = self.sourceTitleList.index(self.sourceTitle)
- if self.sourceTitle == self.sourceTitleList[-1]:
- currIdx = 0
- else: currIdx += 1
- self.sourceTitle = self.sourceTitleList[currIdx]
- self['sourceTitle'].text = self.sourceTitle
- self['sourceTitleInfo'].text = "%s [%d/%d]" % (_("Source title"), currIdx + 1, len(self.sourceTitleList))
- self.detectSearchParams()
- self.buildMenu()
-
- def switchToSuggestionsList(self):
- if not self['config'].enabled:
- return
-
- if self["config"].getCurrent()[1] == self.searchSettings.title:
- self["configActions"].setEnabled(False)
- self["suggestionActions"].setEnabled(True)
- self["config"].invalidateCurrent()
- self["config"].getCurrent()[1].enableHistory(False)
- if self["config"].getCurrent()[1].enableSuggestions(True):
- self.currentList = self.LIST_SUGGESTIONS
- else:
- self.cancelToConfigList()
-
- def switchToHistoryList(self):
- if not self['config'].enabled:
- return
-
- if self["config"].getCurrent()[1] == self.searchSettings.title:
- self["configActions"].setEnabled(False)
- self["suggestionActions"].setEnabled(True)
- self["config"].invalidateCurrent()
- self["config"].getCurrent()[1].enableSuggestions(False)
- if self["config"].getCurrent()[1].enableHistory(True):
- self.currentList = self.LIST_HISTORY
- else:
- self.cancelToConfigList()
-
- def switchToConfigList(self):
- self["config"].getCurrent()[1].enableSuggestions(False)
- self["config"].getCurrent()[1].enableHistory(False)
- self["suggestionActions"].setEnabled(False)
- self["configActions"].setEnabled(True)
- self.currentList = self.LIST_CONFIG
-
- def cancelToHistoryList(self):
- self["config"].invalidateCurrent()
- self["config"].getCurrent()[1].cancelSuggestions()
- self.switchToHistoryList()
-
- def cancelToSuggestionsList(self):
- self["config"].invalidateCurrent()
- self["config"].getCurrent()[1].cancelSuggestions()
- self.switchToSuggestionsList()
-
- def cancelToConfigList(self):
- self["config"].invalidateCurrent()
- self["config"].getCurrent()[1].cancelSuggestions()
- self.switchToConfigList()
-
- def addToHistory(self):
- history = self.searchSettings.history.value.split(',')
- if history[0] == '':
- del history[0]
- if self.searchSettings.title.value in history:
- history.remove((self.searchSettings.title.value))
- history.insert(0, (self.searchSettings.title.value))
- if len(history) == 30:
- history.pop()
- self.searchSettings.history.value = ",".join(history)
- self.searchSettings.history.save()
-
- def keySave(self):
- for x in self["config"].list:
- x[1].save()
- self.close(True)
-
- def keyCancel(self):
- for x in self["config"].list:
- x[1].cancel()
- self.close()
-
- def keyOK(self):
- if self.currentList == self.LIST_CONFIG:
- self.addToHistory()
- self.saveAll()
- self.close(True)
- elif self.currentList in (self.LIST_SUGGESTIONS, self.LIST_HISTORY):
- self.switchToConfigList()
-
- def keyDown(self):
- if not self['config'].enabled:
- self['config'].enableList()
- elif self.currentList in (self.LIST_SUGGESTIONS, self.LIST_HISTORY):
- self["config"].getCurrent()[1].currentListDown()
- self["config"].invalidateCurrent()
- elif self.currentList == self.LIST_CONFIG:
- self['config'].instance.moveSelection(self["config"].instance.moveDown)
-
- def keyUp(self):
- if not self['config'].enabled:
- self['config'].enableList()
- elif self.currentList in (self.LIST_SUGGESTIONS, self.LIST_HISTORY):
- self["config"].getCurrent()[1].currentListUp()
- self["config"].invalidateCurrent()
- elif self.currentList == self.LIST_CONFIG:
- self['config'].instance.moveSelection(self["config"].instance.moveUp)
-
- def keyLeft(self):
- if not self['config'].enabled:
- self['config'].enableList()
- elif self.currentList in (self.LIST_SUGGESTIONS, self.LIST_HISTORY):
- self["config"].getCurrent()[1].currentListPageUp()
- self["config"].invalidateCurrent()
- elif self.currentList == self.LIST_CONFIG:
- ConfigListScreen.keyLeft(self)
- if self['config'].getCurrent()[1] == self.searchSettings.type:
- self.searchParamsHelper.updateProviders()
- self.buildMenu()
-
- def keyRight(self):
- if not self['config'].enabled:
- self['config'].enableList()
- elif self.currentList in (self.LIST_SUGGESTIONS, self.LIST_HISTORY):
- self["config"].getCurrent()[1].currentListPageDown()
- self["config"].invalidateCurrent()
- elif self.currentList == self.LIST_CONFIG:
- ConfigListScreen.keyRight(self)
- if self['config'].getCurrent()[1] == self.searchSettings.type:
- self.searchParamsHelper.updateProviders()
- self.buildMenu()
-
- def removeSuggestionWindows(self):
- if hasattr(self.searchSettings.title, 'suggestionsWindow'):
- suggestionsWindow = self.searchSettings.title.suggestionsWindow
- if suggestionsWindow is not None:
- self.session.deleteDialog(suggestionsWindow)
- self.searchSettings.title.suggestionsWindow = None
- if hasattr(self.searchSettings.title, 'historyWindow'):
- historyWindow = self.searchSettings.title.historyWindow
- if historyWindow is not None:
- self.session.deleteDialog(historyWindow)
- self.searchSettings.title.historyWindow = None
-
-
- class SubsSearchProviderMenu(BaseMenuScreen):
- def __init__(self, session, provider):
- title = toString(provider.provider_name) +" " + _("settings")
- BaseMenuScreen.__init__(self, session, title)
- self.provider = provider
-
- def buildMenu(self):
- settingsProvider = self.provider.settings_provider
- self["config"].setList(settingsProvider.getE2Settings())
-
|