text: import sys
  import time
  import m3u8
  
  from Crypto.Cipher import AES
  
  # from fHDHR.exceptions import TunerError
  
  
  class Direct_M3U8_Stream():
  
      def __init__(self, fhdhr, stream_args, tuner):
          self.fhdhr = fhdhr
          self.stream_args = stream_args
          self.tuner = tuner
  
          self.chunksize = int(self.fhdhr.config.dict["direct_stream"]['chunksize'])
  
      def get(self):
  
          if not self.stream_args["duration"] == 0:
              self.stream_args["time_end"] = self.stream_args["duration"] + time.time()
  
          self.fhdhr.logger.info("Detected stream URL is m3u8: %s" % self.stream_args["true_content_type"])
  
          channelUri = self.stream_args["channelUri"]
          while True:
  
              self.fhdhr.logger.info("Opening m3u8 for reading %s" % channelUri)
              videoUrlM3u = m3u8.load(channelUri)
              if len(videoUrlM3u.playlists):
                  self.fhdhr.logger.info("%s m3u8 varients found" % len(videoUrlM3u.playlists))
                  channelUri = videoUrlM3u.playlists[0].absolute_uri
              else:
                  break
  
          def generate():
  
              try:
  
                  played_chunk_urls = []
  
                  while self.tuner.tuner_lock.locked():
  
                      playlist = m3u8.load(channelUri)
                      segments = playlist.segments
  
                      if len(played_chunk_urls):
                          newsegments = 0
                          for segment in segments:
                              if segment.absolute_uri not in played_chunk_urls:
                                  newsegments += 1
                          self.fhdhr.logger.info("Refreshing m3u8, Loaded %s new segments." % str(newsegments))
                      else:
                          self.fhdhr.logger.info("Loaded %s segments." % str(len(segments)))
  
                      if playlist.keys != [None]:
                          keys = [{"url": key.absolute_uri, "method": key.method, "iv": key.iv} for key in playlist.keys if key]
                      else:
                          keys = [None for i in range(0, len(segments))]
  
                      for segment, key in zip(segments, keys):
                          chunkurl = segment.absolute_uri
  
                          if chunkurl and chunkurl not in played_chunk_urls:
                              played_chunk_urls.append(chunkurl)
  
                              if (not self.stream_args["duration"] == 0 and
                                 not time.time() < self.stream_args["time_end"]):
                                  self.fhdhr.logger.info("Requested Duration Expired.")
                                  self.tuner.close()
  
                              chunk = self.fhdhr.web.session.get(chunkurl).content
                              if not chunk:
                                  break
                                  # raise TunerError("807 - No Video Data")
                              if key:
                                  if key["url"]:
                                      keyfile = self.fhdhr.web.session.get(key["url"]).content
                                      cryptor = AES.new(keyfile, AES.MODE_CBC, keyfile)
                                      self.fhdhr.logger.info("Decrypting Chunk #%s with key: %s" % (len(played_chunk_urls), key["url"]))
                                      chunk = cryptor.decrypt(chunk)
  
                              chunk_size = int(sys.getsizeof(chunk))
                              self.fhdhr.logger.info("Passing Through Chunk #%s with size %s: %s" % (len(played_chunk_urls), chunk_size, chunkurl))
                              yield chunk
                              self.tuner.add_downloaded_size(chunk_size)
  
                  self.fhdhr.logger.info("Connection Closed: Tuner Lock Removed")
  
              except GeneratorExit:
                  self.fhdhr.logger.info("Connection Closed.")
              except Exception as e:
                  self.fhdhr.logger.info("Connection Closed: " + str(e))
              finally:
                  self.fhdhr.logger.info("Connection Closed: Tuner Lock Removed")
                  self.tuner.close()
                  # raise TunerError("806 - Tune Failed")
  
          return generate()
  