Skip to content

Commit

Permalink
issue #213 - add --play-token-resume option
Browse files Browse the repository at this point in the history
  • Loading branch information
jrnewell committed May 3, 2016
1 parent 84c79a3 commit d244962
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
5 changes: 4 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ Command Line
[--grouping GROUPING] [--id3-v23] [-k KEY] [-u USER]
[-p PASSWORD] [-l] [-L LOG] [--pcm] [--mp4]
[--normalize] [-na] [-o] [--opus]
[--partial-check {none,weak,strict}] [--playlist-m3u]
[--partial-check {none,weak,strict}]
[--play-token-resume RESUME_AFTER] [--playlist-m3u]
[--playlist-wpl] [--playlist-sync] [-q VBR]
[-Q {160,320,96}] [--remove-offline-cache]
[--resume-after RESUME_AFTER] [-R REPLACE [REPLACE ...]]
Expand Down Expand Up @@ -157,6 +158,8 @@ Command Line
--opus Rip songs to Opus encoding instead of MP3
--partial-check {none,weak,strict}
Check for and overwrite partially ripped files. "weak" will err on the side of not re-ripping the file if it is unsure, whereas "strict" will re-rip the file [Default=weak]
--play-token-resume RESUME_AFTER
If the 'play token' is lost to a different device using the same Spotify account, the script will wait a speficied amount of time before restarting. This argument takes the same values as --resume-after [Default=abort]
--playlist-m3u create a m3u file when ripping a playlist
--playlist-wpl create a wpl file when ripping a playlist
--playlist-sync Sync playlist songs (rename and remove old songs)
Expand Down
17 changes: 14 additions & 3 deletions spotify_ripper/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ def load_config(defaults):
"comment", "cover_file", "cover_file_and_embed", "directory",
"fail_log", "format", "genres", "grouping", "key", "user",
"password", "log", "artist_album_type", "replace", "partial_check",
"artist_album_market"]
"artist_album_market", "play_token_resume", "stop_after",
"resume_after"]

# coerce boolean and none types
config_items_new = {}
Expand Down Expand Up @@ -272,6 +273,12 @@ def main(prog_args=sys.argv[1:]):
help='Check for and overwrite partially ripped files. "weak" will '
'err on the side of not re-ripping the file if it is unsure, '
'whereas "strict" will re-rip the file [Default=weak]')
parser.add_argument(
'--play-token-resume', nargs=1, metavar="RESUME_AFTER",
help='If the \'play token\' is lost to a different device using '
'the same Spotify account, the script will wait a speficied '
'amount of time before restarting. This argument takes the same '
'values as --resume-after [Default=abort]')
parser.add_argument(
'--playlist-m3u', action='store_true',
help='create a m3u file when ripping a playlist')
Expand All @@ -292,7 +299,7 @@ def main(prog_args=sys.argv[1:]):
help='Remove libspotify\'s offline cache directory after the rip'
'is complete to save disk space')
parser.add_argument(
'--resume-after',
'--resume-after', nargs=1,
help='Resumes script after a certain amount of time has passed '
'after stopping (e.g. 1h30m). Alternatively, accepts a specific '
'time in 24hr format to start after (e.g 03:30, 16:15). '
Expand All @@ -310,7 +317,7 @@ def main(prog_args=sys.argv[1:]):
'--stereo-mode', choices=['j', 's', 'f', 'd', 'm', 'l', 'r'],
help='Advanced stereo settings for Lame MP3 encoder only')
parser.add_argument(
'--stop-after',
'--stop-after', nargs=1,
help='Stops script after a certain amount of time has passed '
'(e.g. 1h30m). Alternatively, accepts a specific time in 24hr '
'format to stop after (e.g 03:30, 16:15)')
Expand Down Expand Up @@ -480,6 +487,10 @@ def unicode_support_str():
parse_time_str(args.resume_after) is None:
print(Fore.RED + "--resume-after option is not valid" + Fore.RESET)
sys.exit(1)
if args.play_token_resume is not None and \
parse_time_str(args.play_token_resume) is None:
print(Fore.RED + "--play_token_resume option is not valid" + Fore.RESET)
sys.exit(1)

print(Fore.YELLOW + " Unicode support:\t" +
Fore.RESET + unicode_support_str())
Expand Down
30 changes: 25 additions & 5 deletions spotify_ripper/ripper.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Ripper(threading.Thread):
finished = threading.Event()
abort = threading.Event()
skip = threading.Event()
play_token_resume = threading.Event()

def __init__(self, args):
threading.Thread.__init__(self)
Expand Down Expand Up @@ -301,7 +302,9 @@ def get_tracks_from_uri(uri):
"ripping track")

if self.skip.is_set():
print("\n" + Fore.YELLOW +
extra_line = "" if self.play_token_resume.is_set() \
else "\n"
print(extra_line + Fore.YELLOW +
"User skipped track... " + Fore.RESET)
self.session.player.play(False)
self.post.clean_up_partial()
Expand Down Expand Up @@ -361,6 +364,10 @@ def get_tracks_from_uri(uri):
def check_stop_time(self):
args = self.args

def wait_for_resume(resume_time):
while datetime.now() < resume_time and not self.abort.is_set():
time.sleep(1)

def stop_time_triggered():
print(Fore.YELLOW + "Stop time of " +
self.stop_time.strftime("%H:%M") +
Expand All @@ -370,8 +377,7 @@ def stop_time_triggered():
resume_time = parse_time_str(args.resume_after)
print(Fore.YELLOW + "Script will resume at " +
resume_time.strftime("%H:%M") + Fore.RESET)
while datetime.now() < resume_time:
time.sleep(60)
wait_for_resume(resume_time)
self.stop_time = None
else:
self.abort.set()
Expand All @@ -385,6 +391,14 @@ def stop_time_triggered():
if self.stop_time < datetime.now():
stop_time_triggered()

# we also wait if the "play token" was lost
elif self.play_token_resume.is_set():
resume_time = parse_time_str(args.play_token_resume[0])
print(Fore.YELLOW + "Script will resume at " +
resume_time.strftime("%H:%M") + Fore.RESET)
wait_for_resume(resume_time)
self.play_token_resume.clear()

def load_link(self, uri):
# ignore if the uri is just blank (e.g. from a file)
if not uri:
Expand Down Expand Up @@ -544,8 +558,14 @@ def on_logged_in(self, session, error):
self.logged_in.set()

def play_token_lost(self, session):
print("\n" + Fore.RED + "Play token lost, aborting..." + Fore.RESET)
self.abort_rip()
if self.args.play_token_resume is not None:
print("\n" + Fore.RED + "Play token lost, waiting " +
self.args.play_token_resume[0] + " to resume..." + Fore.RESET)
self.play_token_resume.set()
self.skip.set()
else:
print("\n" + Fore.RED + "Play token lost, aborting..." + Fore.RESET)
self.abort_rip()

def on_end_of_track(self, session):
self.session.player.play(False)
Expand Down

0 comments on commit d244962

Please sign in to comment.