#!/usr/bin/env python import sys, os import argparse, json import random, re, subprocess, time """ " CLI """ parser = argparse.ArgumentParser( prog='wallpaper', description='Cycle through wallpapers' ) parser.add_argument( '--config', required=True, help='{"": { "find": "", "exclude": "" }, "":...}' ) parser.add_argument( '--interval', default=600 ) parser.add_argument( '--unique', default=False ) args = parser.parse_args() config = json.loads(args.config) """ " Program """ # set variables for --unique flag already_selected_file_paths = {} if args.unique: for weight, config_item in config.items(): config[weight]['id'] = hash(json.dumps(config_item, sort_keys=True)) already_selected_file_paths[config_item['id']] = [] # run the loop running_bg_process = None while True: probability_number = random.randrange(start=1, stop=100, step=1) # select config to use based on args.config # see https://stackoverflow.com/questions/16489449/select-element-from-array-with-probability-proportional-to-its-value/16490300#16490300 selected_config = {} accumulative = 0 for weight, config_item in config.items(): lower_bound = accumulative accumulative += int(weight) upper_bound = accumulative if lower_bound <= probability_number and probability_number <= upper_bound: selected_config = config_item break # build list of file paths to choose from found_file_paths = [] for dirpath, dirnames, filenames in os.walk(os.path.expandvars(selected_config['find'])): for filename in filenames: found_file_paths.append(f'{dirpath}/{filename}') if 'exclude' in selected_config.keys(): found_file_paths = list(filter( lambda file_path: (not re.match(os.path.expandvars(selected_config['exclude']), file_path)), found_file_paths )) if args.unique: # filter file paths from already selected paths filtered_file_paths = [ item for item in found_file_paths if item not in already_selected_file_paths[selected_config['id']] ] # if we cycled through all of them, repeat if not filtered_file_paths: filtered_file_paths = found_file_paths already_selected_file_paths[selected_config['id']] = [] found_file_paths = filtered_file_paths # select file selected_file_path = random.choice(found_file_paths) if args.unique: already_selected_file_paths[selected_config['id']].append(selected_file_path) # run swaybg swaybg_cmd = ['swaybg', '-i', selected_file_path, '-m', 'fill'] replacing_process = subprocess.Popen(swaybg_cmd) # wait until new instance of swaybg has booted up properly time.sleep(5) # kill the previous process # the new swaybg process takes its place automatically if running_bg_process: running_bg_process.terminate() # set running process for next iteration running_bg_process = replacing_process # wait $INTERVAL seconds time.sleep(int(args.interval))