def stream(self): self.logn("Starting stream") segnum = self._segnum+1 bitrate = None self.logn("Queuing segments", 1) while segnum < self._segcount: segment = self.segments[segnum] self.server.add_segment(segment, segnum) segnum += 1 while self._segnum < self._segcount: segnum = self._segnum+1 while True: data = self.server.get_segment(segnum, 2) if not data: self.display_progress() continue ret = self.rs.read(data) if not bitrate: bitrate = self.current_file.get_bitrate() if bitrate: self.logn("Bitrate is %s" % nntp.sizeof_fmt(bitrate), 2) self.logn("Setting download throttle to ~%s" % nntp.sizeof_fmt(bitrate*BITRATE_STREAM_MULT), 2) self.server.set_throttle(bitrate*BITRATE_STREAM_MULT) self.display_progress() if self.current_file.complete: self.logn("\nStream complete!") return break self._segnum = segnum
def main(file_name, nntp_kwargs, max_bitrate=None, do_verify=True): nzb_file = None nzb = None rs = None server = None media_file = None bitrate = None # Listen for exit def signal_handler(signal, frame): sys.stdout.write("\nStopping threads...") sys.stdout.flush() if server: server.quit() sys.stdout.write("done\n") sys.exit(0) # TODO: Listen to other signals signal.signal(signal.SIGINT, signal_handler) mgr = manager.Manager(file_name, nntp_kwargs, max_bitrate, do_verify) if not mgr.initialize(): print "[Error] Manager failed to initialize" return if not mgr.verify(): print "[Error] Verification failed" return mgr.stream() return print "Parsing NZB: %s" % file_name nzb = pynzb.nzb_parser.parse(nzb_file.read()) print "Looking for rar archives" rs = rar.RarSet(nzb) print " Found %d rars" % len(rs.rars) if do_verify: print "Verifying all rar segments are available" # TODO: Verify print "Connecting to server" server = nntp.NNTP(**nntp_kwargs) print "Starting stream" num_segments = 0 for rarfile in rs.rars: for segment in rarfile.segments: server.add_segment(segment, num_segments) num_segments += 1 log.debug("Queued %d segments" % num_segments) for segment in range(num_segments): while True: data = server.get_segment(segment, timeout=2) if not data: log.debug("Segment %d not downloaded...waiting" % segment) continue ret = rs.read(data) if ret: if media_file is None and rs._file_name is not None: media_file = rs._file_name print "Found media file: ", media_file if bitrate is None: bitrate = rs._fd.get_bitrate() if bitrate: print " Bitrate: %s" % nntp.sizeof_fmt(bitrate) if max_bitrate is not None and max_bitrate > bitrate: print " Bitrate exceeds user-defined max (%s)" return current_bytes, total_bytes = ret # TODO: Write data to enable resuming sys.stdout.write("\rProgress: %3.2f%%, Speed: %10s" % (float(current_bytes)/total_bytes*100, server.get_speed(True))) sys.stdout.flush() if current_bytes == total_bytes: print "Stream completed" break
def verify(self): """ Attempts to verify that this file is capable of being streamed. The following items are always checked: * Rar files do not use compression. * Rar files contain a media file These checks are optional: * If ``do_verify`` is True, a check will be made to ensure that every segment of every rar file is available on the news server. * Media file bitrate is equal to or below the user-defined ``max_bitrate``. """ self.logn("Verifying stream") # Let's first check that the rar files do not use compression self.logn("Looking for rar header", 1) while True: data = self.next_segment() # Parse the data self.rs.read(data) if self.rs.current_file: if self.rs.current_file != self.current_file: self.current_file = self.rs.current_file self.logn("Found file: %s" % self.rs.current_file.filename, 2) if self.current_file.is_media(): self.logn("File is a valid media type") else: self.logn("File is not a valid media type") continue # See if we need to check the bitrate if self.max_bitrate is not None: self.logn("Checking bitrate", 2) bitrate = self.current_file.get_bitrate() while not bitrate: segment = self.next_segment() if not segment: self.logn("[Error] Couldn't find segment", 2) return False self.rs.read(data) bitrate = self.rs.current_file.get_bitrate() self.logn("Bitrate is %s" % nntp.sizeof_fmt(bitrate), 3) if self.max_bitrate < bitrate: self.logn("[Error] Bitrate exceeds user-defined max of %s" % nntp.sizeof_fmt(self.max_bitrate), 3) return False self.logn("Bitrate is <= %s" % nntp.sizeof_fmt(self.max_bitrate), 3) break break if self.do_verify: self.logn('Verifying rar segments...', 1) # TODO: Verify segments are available on the server pass return True