|
@@ -1,7 +1,6 @@
|
1
|
1
|
#!/usr/bin/env python
|
2
|
2
|
# coding=utf8
|
3
|
3
|
#
|
4
|
|
-#
|
5
|
4
|
# This file is part of PlayStream - enigma2 plugin to play video streams from various sources
|
6
|
5
|
# Copyright (c) 2016 ivars777 (ivars777@gmail.com)
|
7
|
6
|
# Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
@@ -12,51 +11,47 @@ import os,time,sys,os,os.path
|
12
|
11
|
import datetime,re
|
13
|
12
|
import urllib2
|
14
|
13
|
|
|
14
|
+from Plugins.Plugin import PluginDescriptor
|
15
|
15
|
from enigma import ePicLoad, eServiceReference, eTimer, getDesktop
|
16
|
|
-from Components.ActionMap import ActionMap, HelpableActionMap
|
|
16
|
+from Screens.Screen import Screen
|
17
|
17
|
from Screens.InfoBarGenerics import InfoBarShowHide
|
|
18
|
+from Screens.InfoBar import MoviePlayer
|
|
19
|
+from Screens.MessageBox import MessageBox
|
|
20
|
+from Screens.LocationBox import LocationBox
|
|
21
|
+from Screens.ChoiceBox import ChoiceBox
|
|
22
|
+from Screens.VirtualKeyBoard import VirtualKeyBoard
|
|
23
|
+#from Screens.InputBox import InputBox
|
18
|
24
|
from Components.AVSwitch import AVSwitch
|
|
25
|
+from Components.ActionMap import ActionMap, HelpableActionMap
|
19
|
26
|
from Components.Label import Label
|
|
27
|
+from Components.Input import Input
|
20
|
28
|
from Components.MenuList import MenuList
|
21
|
29
|
from Components.Pixmap import Pixmap
|
22
|
30
|
from Components.Sources.List import List
|
23
|
31
|
from Components.Sources.StaticText import StaticText
|
24
|
32
|
from Components.Button import Button
|
25
|
|
-from Plugins.Plugin import PluginDescriptor
|
26
|
|
-from Screens.InfoBar import MoviePlayer
|
27
|
|
-from Screens.MessageBox import MessageBox
|
|
33
|
+from Components.Task import job_manager
|
|
34
|
+from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigDirectory, ConfigSet, ConfigYesNo, ConfigSelection, getConfigListEntry, ConfigSelectionNumber, ConfigNumber
|
|
35
|
+from Components.ConfigList import ConfigListScreen
|
28
|
36
|
from Tools import Notifications
|
29
|
|
-from Screens.LocationBox import LocationBox
|
30
|
|
-#from Screens.InputBox import InputBox
|
31
|
|
-from Screens.ChoiceBox import ChoiceBox
|
32
|
|
-from Screens.VirtualKeyBoard import VirtualKeyBoard
|
33
|
|
-from Components.Input import Input
|
34
|
|
-from Screens.Screen import Screen
|
35
|
37
|
from Tools.BoundFunction import boundFunction
|
36
|
38
|
from Tools.Directories import resolveFilename, SCOPE_PLUGINS
|
37
|
39
|
from Tools.LoadPixmap import LoadPixmap
|
38
|
40
|
from twisted.web.client import downloadPage,defer,reactor
|
39
|
|
-from Components.Task import job_manager
|
40
|
|
-from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigDirectory, ConfigSet, ConfigYesNo, ConfigSelection, getConfigListEntry, ConfigSelectionNumber
|
41
|
|
-
|
42
|
41
|
|
43
|
42
|
import ContentSources
|
44
|
43
|
import util
|
45
|
44
|
from VideoDownload import downloadJob, HLSDownloadJob,VideoDownloadList
|
46
|
45
|
#import enigma2_api
|
47
|
|
-e2 = None
|
48
|
46
|
|
|
47
|
+e2 = None
|
49
|
48
|
##########################################################################
|
50
|
|
-from Components.config import config, ConfigSubsection, ConfigYesNo, getConfigListEntry, \
|
51
|
|
- ConfigSelection, ConfigNumber, ConfigDirectory,ConfigText
|
52
|
|
-from Components.ConfigList import ConfigListScreen
|
53
|
|
-from Screens.LocationBox import LocationBox
|
54
|
|
-
|
55
|
49
|
config.plugins.playstream = ConfigSubsection()
|
56
|
50
|
config.plugins.playstream.locations = ConfigLocations(default=["/media/hdd/movie/"])
|
57
|
51
|
config.plugins.playstream.download_dir = ConfigDirectory(default="/media/hdd/movie/")
|
58
|
52
|
config.plugins.playstream.tmp_dir = ConfigDirectory(default="/tmp/playstream/")
|
59
|
53
|
config.plugins.playstream.streamproxy_start = ConfigYesNo(default = True)
|
|
54
|
+config.plugins.playstream.overwrite_download = ConfigYesNo(default = False)
|
60
|
55
|
#config.plugins.playstream.size = ConfigSelection({"400x240":"400x240","220x132":"220x132","100x60":"100x60"}, default="220x132")
|
61
|
56
|
config.plugins.playstream.clear_tmp = ConfigYesNo(default = True)
|
62
|
57
|
|
|
@@ -83,9 +78,11 @@ class ConfigScreen(ConfigListScreen,Screen):
|
83
|
78
|
cfg = config.plugins.playstream
|
84
|
79
|
self.list = [
|
85
|
80
|
getConfigListEntry(_("Download folder"), cfg.download_dir),
|
|
81
|
+ getConfigListEntry(_("Overwrite download video"), cfg.overwrite_download),
|
86
|
82
|
getConfigListEntry(_("TMP folder"), cfg.tmp_dir),
|
87
|
83
|
getConfigListEntry(_("Clear tmp folder on exit"), cfg.clear_tmp),
|
88
|
84
|
getConfigListEntry(_("Start playstreamproxy"), cfg.streamproxy_start),
|
|
85
|
+
|
89
|
86
|
]
|
90
|
87
|
ConfigListScreen.__init__(self, self.list, session = self.session)
|
91
|
88
|
self["key_red"] = Button(_("Cancel"))
|
|
@@ -110,14 +107,14 @@ class ConfigScreen(ConfigListScreen,Screen):
|
110
|
107
|
def ok(self):
|
111
|
108
|
if self["config"].getCurrent()[1] == config.plugins.playstream.download_dir:
|
112
|
109
|
folder = config.plugins.playstream.download_dir.value
|
113
|
|
- #self.session.openWithCallback(self.select_download_dir, LocationBox,"Select Folder")
|
114
|
|
- self.session.openWithCallback(self.select_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
|
110
|
+ #self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select Folder")
|
|
111
|
+ self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
115
|
112
|
elif self["config"].getCurrent()[1] == config.plugins.playstream.tmp_dir:
|
116
|
113
|
self.session.openWithCallback(self.select_tmp_dir, LocationBox,"Select tmp folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
117
|
114
|
else:
|
118
|
115
|
self.save()
|
119
|
116
|
|
120
|
|
- def select_download_dir(self, folder, select=None):
|
|
117
|
+ def cb_download_dir(self, folder, select=None):
|
121
|
118
|
if not folder:
|
122
|
119
|
return
|
123
|
120
|
print "Folder selected - %s"%folder
|
|
@@ -160,10 +157,10 @@ def make_service(stream):
|
160
|
157
|
service_type = 4097
|
161
|
158
|
if re.search("\.ts$",url.split("?")[0],re.IGNORECASE):
|
162
|
159
|
service_type = 1
|
163
|
|
- if "resolver" in stream and stream["resolver"] in ("hqq","viaplay"):
|
|
160
|
+ if "resolver" in stream and stream["resolver"] in ("hqq","viaplay","filmas"):
|
164
|
161
|
url = util.streamproxy_encode(stream["url"], stream["headers"])
|
165
|
|
- if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
|
166
|
|
- service_type = 5002
|
|
162
|
+ #if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
|
|
163
|
+ #service_type = 5002
|
167
|
164
|
print "service_type=",service_type
|
168
|
165
|
print "stream_url=",url
|
169
|
166
|
service = eServiceReference(service_type, 0, url)
|
|
@@ -632,7 +629,7 @@ class MainScreen(Screen):
|
632
|
629
|
try:
|
633
|
630
|
self.session.open(PSPlayer, streams)
|
634
|
631
|
except Exception as e:
|
635
|
|
- self.msg2("Error launching player - " + str(e))
|
|
632
|
+ self.msg("Error launching player - " + str(e))
|
636
|
633
|
return
|
637
|
634
|
else:
|
638
|
635
|
self.msg("No stream found - %s"%(self.current[1]))
|
|
@@ -715,11 +712,15 @@ class MainScreen(Screen):
|
715
|
712
|
]
|
716
|
713
|
if self.sources.is_video(self.current[1]):
|
717
|
714
|
lst.extend([
|
718
|
|
- ("Download video","download","Download video in background"),
|
|
715
|
+ ("Download video to default folder","download","Download video to default folder"),
|
|
716
|
+ ("Download video, ask folder","download2","Download video, ask download folder"),
|
|
717
|
+ ("Download video to subfolder, ask parent folder","download3","Download video to subfolder, ask download folder"),
|
|
718
|
+
|
719
|
719
|
])
|
720
|
720
|
else:
|
721
|
721
|
lst.extend([
|
722
|
|
- ("Download videos in folder","download","Download videos in folder (if any)"),
|
|
722
|
+ ("Download list to default folder","download","Download videos in list (if any)"),
|
|
723
|
+ ("Download list, ask folder","download2","Download videos in list (if any), ask download folder"),
|
723
|
724
|
])
|
724
|
725
|
if "config::" in self.cur_menu[1]:
|
725
|
726
|
lst.extend([
|
|
@@ -735,6 +736,7 @@ class MainScreen(Screen):
|
735
|
736
|
#print "item_menu_selected",answer
|
736
|
737
|
if not answer:
|
737
|
738
|
return
|
|
739
|
+ self.answer = answer[1]
|
738
|
740
|
|
739
|
741
|
if answer[1] == "info":
|
740
|
742
|
self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
|
|
@@ -748,33 +750,22 @@ class MainScreen(Screen):
|
748
|
750
|
|
749
|
751
|
elif answer[1] == "favorites":
|
750
|
752
|
lists = self.config.get_lists()
|
751
|
|
- lists2 = [(l,l) for l in lists]
|
|
753
|
+ lists2 = [(self.config.get_title(l),l) for l in lists]
|
|
754
|
+ print lists2
|
752
|
755
|
self.session.openWithCallback(self.cb_favorites, ChoiceBox, title="Selected menu item will be added",list = lists2)
|
753
|
756
|
|
754
|
|
- elif answer[1] == 'download':
|
755
|
|
- current = self.current
|
756
|
|
- if not self.sources.is_video(current[1]):
|
757
|
|
- #self.msg("Can not download listst (yet) - %s"%(current[1]))
|
758
|
|
- n = 0
|
759
|
|
- for current2 in self.sources.get_content(current[1]):
|
760
|
|
- if self.sources.is_video(current2[1]):
|
761
|
|
- n += 1
|
762
|
|
- self.download_video(current2)
|
763
|
|
- if n>0:
|
764
|
|
- self.msg("%s videos download started"%n)
|
765
|
|
- else:
|
766
|
|
- self.msg("No videos to download")
|
767
|
|
- else:
|
768
|
|
- if self.download_video(current):
|
769
|
|
- self.msg("Video download started")
|
|
757
|
+ elif answer[1] in ("download2","download3"): # ask download folder before
|
|
758
|
+ self.session.openWithCallback(self.download_prepare, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
770
|
759
|
|
|
760
|
+ elif answer[1] == 'download':
|
|
761
|
+ self.download_prepare(config.plugins.playstream.download_dir.value)
|
771
|
762
|
|
772
|
763
|
elif answer[1] == 'download_list':
|
773
|
764
|
self.download_list()
|
774
|
765
|
|
775
|
766
|
elif answer[1] == 'download_folder':
|
776
|
767
|
#downloadDir = "/media/hdd/movie" #config.plugins.playstream.downloadDir.value TODO
|
777
|
|
- self.session.openWithCallback(self.select_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
|
768
|
+ self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
|
778
|
769
|
|
779
|
770
|
elif answer[1] == "delete":
|
780
|
771
|
lst = self.cur_menu[1].replace("config::","")
|
|
@@ -793,7 +784,31 @@ class MainScreen(Screen):
|
793
|
784
|
pass #TODO
|
794
|
785
|
return
|
795
|
786
|
|
796
|
|
- def select_download_dir(self, downloadDir, select=None):
|
|
787
|
+ def download_prepare(self, download_dir=""):
|
|
788
|
+ current = self.current
|
|
789
|
+ if not download_dir:
|
|
790
|
+ return
|
|
791
|
+ #download_dir = config.plugins.playstream.download_dir.value
|
|
792
|
+ title = re.sub("\[.+?\]","", util.make_fname(current[0])).strip()
|
|
793
|
+ download_dir2 = os.path.join(download_dir, title)
|
|
794
|
+ if not self.sources.is_video(current[1]):
|
|
795
|
+ #self.msg("Can not download listst (yet) - %s"%(current[1]))
|
|
796
|
+ n = 0
|
|
797
|
+ for current2 in self.sources.get_content(current[1]):
|
|
798
|
+ if self.sources.is_video(current2[1]):
|
|
799
|
+ n += 1
|
|
800
|
+ self.download_video(current2,download_dir2)
|
|
801
|
+ if n>0:
|
|
802
|
+ self.msg("%s videos download started to %s"%(n,download_dir2))
|
|
803
|
+ else:
|
|
804
|
+ self.msg("No videos to download")
|
|
805
|
+ else:
|
|
806
|
+ if self.answer == "download":
|
|
807
|
+ download_dir2 = download_dir
|
|
808
|
+ if self.download_video(current,download_dir2):
|
|
809
|
+ self.msg("Video download started to %s"%download_dir2)
|
|
810
|
+
|
|
811
|
+ def cb_download_dir(self, downloadDir, select=None):
|
797
|
812
|
if not downloadDir:
|
798
|
813
|
return
|
799
|
814
|
print "Folder selected - %s"%downloadDir
|
|
@@ -805,7 +820,7 @@ class MainScreen(Screen):
|
805
|
820
|
def download_list(self):
|
806
|
821
|
self.session.open(VideoDownloadList)
|
807
|
822
|
|
808
|
|
- def download_video(self,current):
|
|
823
|
+ def download_video(self,current, download_dir=""):
|
809
|
824
|
if self.sources.stream_type(current[1]):
|
810
|
825
|
stream = util.item()
|
811
|
826
|
stream["url"] = current[1]
|
|
@@ -831,9 +846,9 @@ class MainScreen(Screen):
|
831
|
846
|
else:
|
832
|
847
|
stream = streams[0]
|
833
|
848
|
stream = util.stream_change(stream)
|
834
|
|
- return self.download_stream(stream)
|
|
849
|
+ return self.download_stream(stream, download_dir)
|
835
|
850
|
|
836
|
|
- def download_stream(self,stream):
|
|
851
|
+ def download_stream(self,stream,download_dir=""):
|
837
|
852
|
print "download stream",stream
|
838
|
853
|
#self.msg("Start downloading..")
|
839
|
854
|
self.stream = stream
|
|
@@ -846,16 +861,31 @@ class MainScreen(Screen):
|
846
|
861
|
title = self.stream["name"].strip()
|
847
|
862
|
url = self.stream["url"]
|
848
|
863
|
stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
|
849
|
|
- downloadDir = config.plugins.playstream.download_dir.value
|
|
864
|
+ downloadDir = config.plugins.playstream.download_dir.value if not download_dir else download_dir
|
850
|
865
|
if not os.path.exists(downloadDir):
|
851
|
|
- print 'Sorry, download directory "%s" not exist!\nPlease specify in the settings existing directory'%downloadDir
|
852
|
|
- self.msg0(_('Sorry, download directory "%s" not exist!\nPlease specify in the settings existing directory'%downloadDir))
|
853
|
|
- return
|
854
|
|
- fname0 = re.sub("[/\n\r\t,:]"," ",title)
|
855
|
|
- fname0 = re.sub("['""]","",fname0)
|
|
866
|
+ try:
|
|
867
|
+ os.mkdir(downloadDir)
|
|
868
|
+ except Exception as e:
|
|
869
|
+ print 'Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e))
|
|
870
|
+ self.msg('Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e)))
|
|
871
|
+ return
|
|
872
|
+ fname0 = util.make_fname(title)
|
856
|
873
|
fname = fname0 +".mp4"
|
857
|
874
|
outputfile = os.path.join(downloadDir, fname)
|
858
|
875
|
#print "Trying to download - ", current
|
|
876
|
+ if self.stream["img"]:
|
|
877
|
+ try:
|
|
878
|
+ thumb = urllib2.urlopen(stream["img"]).read()
|
|
879
|
+ except:
|
|
880
|
+ thumb = ""
|
|
881
|
+ if thumb:
|
|
882
|
+ imgext = ".jpg"
|
|
883
|
+ m = re.search("(\.\w{3})$",stream["img"])
|
|
884
|
+ if m:
|
|
885
|
+ imgext = m.group(1)
|
|
886
|
+ imgfile = os.path.join(downloadDir,fname0+imgext)
|
|
887
|
+ with open(imgfile,"wb") as f:
|
|
888
|
+ f.write(thumb)
|
859
|
889
|
if self.stream["subs"]:
|
860
|
890
|
suburl = self.stream["subs"][0]["url"]
|
861
|
891
|
print "\n**Download subtitles %s - %s"%(title,suburl)
|
|
@@ -870,8 +900,17 @@ class MainScreen(Screen):
|
870
|
900
|
f.write(subs)
|
871
|
901
|
else:
|
872
|
902
|
print "\n Error downloading subtitle %s"%suburl
|
873
|
|
-
|
874
|
|
- if os.path.exists(outputfile):
|
|
903
|
+ if "nfo" in self.stream and self.stream["nfo"]:
|
|
904
|
+ nfofile = subfile = os.path.join(downloadDir,fname0+".nfo")
|
|
905
|
+ with open(nfofile,"w") as f:
|
|
906
|
+ nfo_type,nfo = next(self.stream["nfo"].iteritems())
|
|
907
|
+ f.write("<%s>\n"%nfo_type.encode("utf8"))
|
|
908
|
+ for k,v in nfo.iteritems():
|
|
909
|
+ if isinstance(v,unicode): v = v.encode("utf8")
|
|
910
|
+ f.write(" <%s>%s</%s>\n"%(k.encode("utf8"), v, k.encode("utf8")))
|
|
911
|
+ f.write("</%s>\n"%nfo_type.encode("utf8"))
|
|
912
|
+ overwrite = config.plugins.playstream.overwrite_download.value
|
|
913
|
+ if not overwrite and os.path.exists(outputfile):
|
875
|
914
|
self.msg( _('Sorry, this file already exists:\n%s') % outputfile)
|
876
|
915
|
return False
|
877
|
916
|
#os.remove(outputfile)
|