<s> from __future__ import unicode_literals <EOL> from colorama import Cursor <EOL> from spotify_ripper . utils import * <EOL> import os <EOL> import sys <EOL> import time <EOL> import schedule <EOL> import spotify <EOL> try : <EOL> from fcntl import ioctl <EOL> from array import array <EOL> import termios <EOL> except ImportError : <EOL> pass <EOL> class Progress ( object ) : <EOL> current_track = None <EOL> song_position = <NUM_LIT:0> <EOL> song_duration = <NUM_LIT:0> <EOL> show_total = False <EOL> skipped_tracks = <NUM_LIT:0> <EOL> track_idx = <NUM_LIT:0> <EOL> total_tracks = <NUM_LIT:0> <EOL> total_position = <NUM_LIT:0> <EOL> total_duration = <NUM_LIT:0> <EOL> total_size = <NUM_LIT:0> <EOL> ema_rate = None <EOL> stat_prev = None <EOL> song_eta = None <EOL> total_eta = None <EOL> move_cursor = False <EOL> term_width = <NUM_LIT> <EOL> def __init__ ( self , args , ripper ) : <EOL> self . args = args <EOL> self . ripper = ripper <EOL> if not self . args . has_log : <EOL> schedule . every ( <NUM_LIT:2> ) . seconds . do ( self . eta_calc ) <EOL> def calc_total ( self , track_pairs ) : <EOL> if len ( track_pairs ) <= <NUM_LIT:1> : <EOL> return <EOL> self . show_total = True <EOL> self . track_idx = <NUM_LIT:0> <EOL> self . total_tracks = <NUM_LIT:0> <EOL> self . total_duration = <NUM_LIT:0> <EOL> self . total_size = <NUM_LIT:0> <EOL> for pair in track_pairs : <EOL> try : <EOL> track = pair [ <NUM_LIT:0> ] <EOL> track . load ( ) <EOL> if track . availability != <NUM_LIT:1> : <EOL> self . skipped_tracks += <NUM_LIT:1> <EOL> continue <EOL> audio_file = pair [ <NUM_LIT:1> ] <EOL> if not self . args . overwrite and path_exists ( audio_file ) and not is_partial ( audio_file , track ) : <EOL> self . skipped_tracks += <NUM_LIT:1> <EOL> continue <EOL> self . total_tracks += <NUM_LIT:1> <EOL> self . total_duration += track . duration <EOL> file_size = calc_file_size ( track ) <EOL> self . total_size += file_size <EOL> except spotify . Error as e : <EOL> continue <EOL> def eta_calc ( self ) : <EOL> def calc_rate ( rate , avg_rate , smoothing_factor ) : <EOL> if avg_rate is None : <EOL> return rate <EOL> else : <EOL> return ( smoothing_factor * rate ) + ( ( <NUM_LIT:1.0> - smoothing_factor ) * avg_rate ) <EOL> def calc ( pos , dur , rate , old_eta ) : <EOL> new_eta = ( dur - pos ) / rate <EOL> if old_eta is None or abs ( new_eta - old_eta ) >= <NUM_LIT:5> : <EOL> r = new_eta % <NUM_LIT:5> <EOL> new_eta += ( ( <NUM_LIT:5> - r ) if r >= <NUM_LIT:3> else ( <NUM_LIT:0> - r ) ) <EOL> return new_eta <EOL> return old_eta <EOL> if self . ripper . ripping : <EOL> if self . stat_prev is not None : <EOL> rate = ( self . song_position - self . stat_prev [ <NUM_LIT:0> ] ) / ( time . time ( ) - self . stat_prev [ <NUM_LIT:1> ] ) <EOL> if rate > <NUM_LIT> : <EOL> self . ema_rate = calc_rate ( rate , self . ema_rate , <NUM_LIT> ) <EOL> self . song_eta = calc ( <EOL> self . song_position , self . song_duration , <EOL> self . ema_rate , self . song_eta ) <EOL> if self . show_total : <EOL> total_position = ( <EOL> self . total_position + self . song_position ) <EOL> self . total_eta = calc ( <EOL> total_position , self . total_duration , <EOL> self . ema_rate , self . total_eta ) <EOL> self . stat_prev = ( self . song_position , time . time ( ) ) <EOL> def handle_resize ( self , signum = None , frame = None ) : <EOL> try : <EOL> _to_ascii = lambda s : s . encode ( <EOL> "<STR_LIT:ascii>" , "<STR_LIT:ignore>" ) if sys . version_info < ( <NUM_LIT:3> , <NUM_LIT:0> ) else s <EOL> h = _to_ascii ( "<STR_LIT:h>" ) <EOL> null_str = _to_ascii ( "<STR_LIT>" * <NUM_LIT:8> ) <EOL> h , w = array ( <EOL> h , ioctl ( sys . stdout , termios . TIOCGWINSZ , null_str ) ) [ : <NUM_LIT:2> ] <EOL> self . term_width = w <EOL> except ( NameError , IOError ) : <EOL> self . term_width = int ( os . environ . get ( '<STR_LIT>' , <NUM_LIT> ) ) - <NUM_LIT:1> <EOL> def prepare_track ( self , track ) : <EOL> self . song_position = <NUM_LIT:0> <EOL> self . song_duration = track . duration <EOL> self . move_cursor = False <EOL> self . current_track = track <EOL> self . track_idx += <NUM_LIT:1> <EOL> def end_track ( self , show_end = True ) : <EOL> if show_end : <EOL> self . end_progress ( ) <EOL> self . stat_prev = None <EOL> self . song_eta = None <EOL> self . total_eta = None <EOL> self . total_position += self . current_track . duration <EOL> self . current_track = None <EOL> def update_progress ( self , num_frames , sample_rate ) : <EOL> if self . args . has_log : <EOL> return <EOL> def output_what_fits ( init , output_strings ) : <EOL> print_str ( init ) <EOL> w = <NUM_LIT:0> <EOL> for _str in output_strings : <EOL> _len = len ( _str ) <EOL> if w + _len >= ( self . term_width - <NUM_LIT:1> ) : <EOL> return <EOL> print_str ( _str ) <EOL> w += _len <EOL> if self . term_width < <NUM_LIT> : <EOL> prog_width = <NUM_LIT:10> <EOL> elif self . term_width < <NUM_LIT:100> : <EOL> prog_width = <NUM_LIT> - ( <NUM_LIT:100> - self . term_width ) <EOL> else : <EOL> prog_width = <NUM_LIT> <EOL> if num_frames > <NUM_LIT:0> and sample_rate > <NUM_LIT:0> : <EOL> self . song_position += ( num_frames * <NUM_LIT:1000> ) / sample_rate <EOL> pos_seconds = self . song_position // <NUM_LIT:1000> <EOL> dur_seconds = self . song_duration // <NUM_LIT:1000> <EOL> pct = int ( self . song_position * <NUM_LIT:100> // self . song_duration ) if self . song_duration > <NUM_LIT:0> else <NUM_LIT:0> <EOL> x = int ( pct * prog_width // <NUM_LIT:100> ) <EOL> if self . show_total : <EOL> if self . move_cursor : <EOL> print ( Cursor . UP ( <NUM_LIT:2> ) ) <EOL> else : <EOL> self . move_cursor = True <EOL> output_strings = [ <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" + ( "<STR_LIT:=>" * x ) + ( "<STR_LIT:U+0020>" * ( prog_width - x ) ) + "<STR_LIT:]>" , <EOL> "<STR_LIT:U+0020>" + format_time ( pos_seconds , dur_seconds ) <EOL> ] <EOL> if self . song_eta is not None : <EOL> _spaces = max ( <NUM_LIT> - len ( output_strings [ <NUM_LIT:2> ] ) , <NUM_LIT:1> ) * "<STR_LIT:U+0020>" <EOL> output_strings . append ( _spaces ) <EOL> _str = "<STR_LIT>" + format_time ( self . song_eta , short = True ) + "<STR_LIT>" <EOL> output_strings . append ( _str ) <EOL> output_what_fits ( "<STR_LIT>" , output_strings ) <EOL> if self . show_total : <EOL> total_position = self . total_position + self . song_position <EOL> total_pos_seconds = total_position // <NUM_LIT:1000> <EOL> total_dur_seconds = self . total_duration // <NUM_LIT:1000> <EOL> total_pct = int ( total_position * <NUM_LIT:100> // self . total_duration ) if self . total_duration > <NUM_LIT:0> else <NUM_LIT:0> <EOL> total_x = int ( total_pct * prog_width // <NUM_LIT:100> ) <EOL> output_strings = [ <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" + ( "<STR_LIT:=>" * total_x ) + <EOL> ( "<STR_LIT:U+0020>" * ( prog_width - total_x ) ) + "<STR_LIT:]>" , <EOL> "<STR_LIT:U+0020>" + format_time ( total_pos_seconds , total_dur_seconds ) <EOL> ] <EOL> if self . total_eta is not None : <EOL> _spaces = max ( <NUM_LIT> - len ( output_strings [ <NUM_LIT:2> ] ) , <NUM_LIT:1> ) * "<STR_LIT:U+0020>" <EOL> output_strings . append ( _spaces ) <EOL> _str = "<STR_LIT>" + format_time ( self . total_eta , short = True ) + "<STR_LIT>" <EOL> output_strings . append ( _str ) <EOL> output_what_fits ( "<STR_LIT>" , output_strings ) <EOL> def end_progress ( self ) : <EOL> self . song_position = self . song_duration <EOL> self . eta_calc ( ) <EOL> self . update_progress ( <NUM_LIT:0> , None ) <EOL> print_str ( "<STR_LIT:\n>" ) </s>
