Switch to unified view

a/rdpl2stream/StreamDecoder.py b/rdpl2stream/StreamDecoder.py
...
...
17
# along with Radio Tray.  If not, see <http://www.gnu.org/licenses/>.
17
# along with Radio Tray.  If not, see <http://www.gnu.org/licenses/>.
18
#
18
#
19
##########################################################################
19
##########################################################################
20
from __future__ import print_function
20
from __future__ import print_function
21
21
22
import urllib2
23
import sys
22
import sys
23
24
PY3 = sys.version > '3'
25
if PY3:
26
    from urllib.request import Request as UrlRequest
27
    import urllib.request, urllib.error, urllib.parse
28
    from urllib.error import HTTPError as HTTPError
29
    from urllib.error import URLError as URLError
30
    from http.client import BadStatusLine as BadStatusLine
31
    from urllib.request import build_opener as urlBuild_opener
32
    from urllib.request import HTTPSHandler    
33
else:
34
    from urllib2 import Request as UrlRequest
35
    from urllib2 import HTTPError as HTTPError
36
    from urllib2 import URLError as URLError
37
    from urllib2 import build_opener as urlBuild_opener
38
    from urllib2 import HTTPSHandler
39
    class BadStatusLine:
40
        pass
24
import ssl
41
import ssl
25
42
26
from lib.common import USER_AGENT
43
from lib.common import USER_AGENT, Logger
27
from lib.DummyMMSHandler import DummyMMSHandler
44
from lib.DummyMMSHandler import DummyMMSHandler
28
from PlsPlaylistDecoder import PlsPlaylistDecoder
45
from PlsPlaylistDecoder import PlsPlaylistDecoder
29
from M3uPlaylistDecoder import M3uPlaylistDecoder
46
from M3uPlaylistDecoder import M3uPlaylistDecoder
30
from AsxPlaylistDecoder import AsxPlaylistDecoder
47
from AsxPlaylistDecoder import AsxPlaylistDecoder
31
from XspfPlaylistDecoder import XspfPlaylistDecoder
48
from XspfPlaylistDecoder import XspfPlaylistDecoder
32
from AsfPlaylistDecoder import AsfPlaylistDecoder
49
from AsfPlaylistDecoder import AsfPlaylistDecoder
33
from RamPlaylistDecoder import RamPlaylistDecoder
50
from RamPlaylistDecoder import RamPlaylistDecoder
34
from UrlInfo import UrlInfo
51
from UrlInfo import UrlInfo
35
52
36
class Logger:
37
    def mprint(self, m):
38
        #print("%s"%m, file=sys.stderr)
39
        pass
40
    def error(self, m):
41
        self.mprint(m)
42
    def warn(self, m):
43
        self.mprint(m)
44
    def info(self, m):
45
        self.mprint(m)
46
    def debug(self, m):
47
        self.mprint(m)
48
        
53
      
49
class StreamDecoder:
54
class StreamDecoder:
50
55
51
    def __init__(self, cfg_provider):
56
    def __init__(self, cfg_provider):
52
        plsDecoder = PlsPlaylistDecoder()
57
        plsDecoder = PlsPlaylistDecoder()
53
        m3uDecoder = M3uPlaylistDecoder()
58
        m3uDecoder = M3uPlaylistDecoder()
...
...
66
            self.url_timeout = cfg_provider.getConfigValue("url_timeout")
71
            self.url_timeout = cfg_provider.getConfigValue("url_timeout")
67
            if (self.url_timeout == None):
72
            if (self.url_timeout == None):
68
                self.log.warn("Couldn't find url_timeout configuration")
73
                self.log.warn("Couldn't find url_timeout configuration")
69
                self.url_timeout = 100
74
                self.url_timeout = 100
70
                cfg_provider.setConfigValue("url_timeout", str(self.url_timeout))
75
                cfg_provider.setConfigValue("url_timeout", str(self.url_timeout))
71
        except Exception, e:
76
        except Exception as e:
72
            self.log.warn("Couldn't find url_timeout configuration")
77
            self.log.warn("Couldn't find url_timeout configuration")
73
            self.url_timeout = 100
78
            self.url_timeout = 100
74
            cfg_provider.setConfigValue("url_timeout", str(self.url_timeout))
79
            cfg_provider.setConfigValue("url_timeout", str(self.url_timeout))
75
80
76
        self.log.info('Using url timeout = %s'% str(self.url_timeout))
81
        self.log.info('Using url timeout = %s'% str(self.url_timeout))
77
82
78
83
79
    def getMediaStreamInfo(self, url):
84
    def getMediaStreamInfo(self, url):
80
85
        if type(url) != type(u""):
86
            url = url.decode('utf-8')
81
        if url.startswith("http") == False:
87
        if url.startswith("http") == False:
82
            self.log.info('Not an HTTP url. Maybe direct stream...')
88
            self.log.info('Not an HTTP url. Maybe direct stream...')
83
            return UrlInfo(url, False, None)
89
            return UrlInfo(url, False, None)
84
90
85
        self.log.info('Requesting stream... %s'% url)
91
        self.log.info('Requesting stream... %s'% url)
86
        req = urllib2.Request(url)
92
        req = UrlRequest(url)
87
        req.add_header('User-Agent', USER_AGENT)
93
        req.add_header('User-Agent', USER_AGENT)
88
94
89
        try:
95
        try:
90
            opener = urllib2.build_opener(
96
            opener = urlBuild_opener(
91
                DummyMMSHandler(),
97
                DummyMMSHandler(),
92
                urllib2.HTTPSHandler(context =
98
                HTTPSHandler(context = ssl._create_unverified_context()))
93
                                     ssl._create_unverified_context()))
94
            f = opener.open(req, timeout=float(self.url_timeout))
99
            f = opener.open(req, timeout=float(self.url_timeout))
95
96
        except urllib2.HTTPError, e:
100
        except HTTPError as e:
97
            self.log.warn('HTTP Error: No radio stream found for %s - %s' %
101
            self.log.warn('HTTP Error for %s: %s' % (url, e))
98
                          (url, str(e)))
99
            return None
102
            return None
100
        except urllib2.URLError, e:
103
        except URLError as e:
101
            self.log.info('No radio stream found for %s'% url)
104
            self.log.info('URLError for %s: %s ' % (url, e))
102
            if str(e.reason).startswith('MMS REDIRECT'):
105
            if str(e.reason).startswith('MMS REDIRECT'):
103
                newurl = e.reason.split("MMS REDIRECT:",1)[1]
106
                newurl = e.reason.split("MMS REDIRECT:",1)[1]
104
                self.log.info('Found mms redirect for: %s' % newurl)
107
                self.log.info('Found mms redirect for: %s' % newurl)
105
                return UrlInfo(newurl, False, None)
108
                return UrlInfo(newurl, False, None)
106
            else:
109
            else:
107
                return None
110
                return None
111
        except BadStatusLine as e:
112
            if str(e).startswith('ICY 200'):
113
                self.log.info('Found ICY stream')
114
                return UrlInfo(url, False, None)
115
            else:
116
                return None
108
        except Exception, e:
117
        except Exception as e:
109
            self.log.warn('No radio stream found. Error: %s'% str(e))
118
            self.log.warn('%s: for %s: Error %s: %s' % (type(e), url, e))
110
            return None
119
            return None
111
120
112
        metadata = f.info()
121
        metadata = f.info()
113
        firstbytes = f.read(500)
122
        firstbytes = f.read(500)
114
        f.close()
123
        f.close()
115
        
124
116
        try:            
125
        try:            
117
            self.log.debug('Metadata obtained...')
118
            contentType = metadata["Content-Type"]
126
            contentType = metadata["content-type"]
119
            self.log.info('Content-Type: %s'% contentType)
127
            self.log.info('Content-Type: %s'% contentType)
120
            
121
122
        except Exception, e:
128
        except Exception as e:
123
            self.log.info("Couldn't read content-type. Maybe direct stream...")
129
            self.log.info("Couldn't read content-type. Maybe direct stream...")
124
            self.log.info('Error: %s'%e)
125
            return UrlInfo(url, False, None)
130
            return UrlInfo(url, False, None)
126
131
127
        for decoder in self.decoders:
132
        for decoder in self.decoders:
128
                
133
                
129
            self.log.info('Checking decoder')
134
            self.log.info('Checking decoder')
130
            if(decoder.isStreamValid(contentType, firstbytes)):
135
            if decoder.isStreamValid(contentType, firstbytes):
131
132
                return UrlInfo(url, True, contentType, decoder)
136
                return UrlInfo(url, True, contentType, decoder)
133
            
137
            
134
        # no playlist decoder found. Maybe a direct stream
138
        # no playlist decoder found. Maybe a direct stream
135
        self.log.info('No playlist decoder could handle the stream. Maybe direct stream...')
139
        self.log.info('No playlist decoder could handle the stream. Maybe direct stream...')
136
        return UrlInfo(url, False, contentType)
140
        return UrlInfo(url, False, contentType)
137
        
141
        
138
142
139
140
    def getPlaylist(self, urlInfo):
143
    def getPlaylist(self, urlInfo):
141
142
        return urlInfo.getDecoder().extractPlaylist(urlInfo.getUrl())
144
        return urlInfo.getDecoder().extractPlaylist(urlInfo.getUrl())
143
145