diff --git a/README.org b/README.org index b29fb19..5476d44 100644 --- a/README.org +++ b/README.org @@ -3,7 +3,7 @@ *strm* is a small Bash script that lets you stream media files over SSH. No need for mounting and navigating through complex directory structures anymore. - Just provide a query and the media files are played locally via [[https://mpv.io/][mpv]]. + Just provide a query and the matching media files are played locally via [[https://mpv.io/][mpv]]. Here is an example.. let's assume you have the shortfilm [[https://www.dailydweebs.com/][The Daily Dweebs]] stored on a remote machine in the following directory structure: @@ -23,8 +23,11 @@ #+end_src Every argument which is not assigned to a flag is interpreted as part of the query. - The query arguments are then surrounded by wildcards (=*=) and the case gets ignored. - If every argument matches any filepath in the configured media directories, the matched filepaths are interpreted as result. + The query arguments are interpreted as [[https://en.wikipedia.org/wiki/Glob_(programming)][glob patterns]], additionally surrounded by wildcards (=*=). + If every pattern matches any filepath in the configured media directories, the matched filepaths are interpreted as result. + The =--or= flag can be set to get results which match at least one pattern. + Matchings are always done case-insensitive. + The shortfilm from the example above could have also been played with one of the following commands: #+begin_src sh @@ -70,21 +73,22 @@ ** Usage #+begin_src text - Usage: strm [OPTIONS] QUERY ... [OPTIONS] + Usage: strm [OPTIONS] QUERIES ... [OPTIONS] Stream media files over SSH. OPTIONS -h, --help Show this help message - -c, --config CONFIG_FILE Path to config file + -c, --config CONFIG_FILE Path to config file (default: ~/.config/strm/strm.config) -l, --list List files instead of playing -m, --media-directories MEDIA_DIRECTORIES Use given media directories, config is ignored + -o, --or Use a logical OR for queries (default: AND) -s, --shuffle Play files in random order EXAMPLES strm -l . # List all available files strm Elephants Dream # Play files whose path contain 'elephants' and 'dream' - strm e*phants # Play files whose path matches the wildcard 'e*phants' + strm e*phants # Play files whose path matches the glob pattern 'e*phants' #+end_src The usual [[https://mpv.io/manual/master/#interactive-control][mpv controls]] are available while playback. @@ -94,6 +98,7 @@ - =p= and =SPACE= :: Pause (pressing again unpauses). - =<= and =>= :: Go backward/forward in the playlist. - =q= :: Stop playing and quit. + - =Q= :: Like =q=, but store the current playback position. Playing the same file later will resume at the old playback position if possible. ** Configuration diff --git a/strm b/strm index 43609b2..a245704 100755 --- a/strm +++ b/strm @@ -5,21 +5,22 @@ text_reset="\e[0m" text_bold="\e[1m" function print_usage { - echo "Usage: strm [OPTIONS] QUERY ... [OPTIONS]" + echo "Usage: strm [OPTIONS] QUERIES ... [OPTIONS]" echo echo "Stream media files over SSH." echo echo "OPTIONS" echo " -h, --help Show this help message" - echo " -c, --config CONFIG_FILE Path to config file" + echo " -c, --config CONFIG_FILE Path to config file (default: ~/.config/strm/strm.config)" echo " -l, --list List files instead of playing" echo " -m, --media-directories MEDIA_DIRECTORIES Use given media directories, config is ignored" + echo " -o, --or Use a logical OR for queries (default: AND)" echo " -s, --shuffle Play files in random order" echo echo "EXAMPLES" echo " strm -l . # List all available files" echo " strm Elephants Dream # Play files whose path contain 'elephants' and 'dream'" - echo " strm e*phants # Play files whose path matches the wildcard 'e*phants'" + echo " strm e*phants # Play files whose path matches the glob pattern 'e*phants'" exit } @@ -41,8 +42,9 @@ fi # Set default values config="$HOME/.config/strm/strm.config" list=false +or=false shuffle=false -query=() +queries=() media_directories="" # Parse arguments @@ -71,6 +73,10 @@ while (( "$#" )); do error "Argument for $1 is missing" fi ;; + -o|--or) + or=true + shift + ;; -s|--shuffle) shuffle=true shift @@ -79,14 +85,14 @@ while (( "$#" )); do error "Unsupported flag $1" ;; *) - query+=("$1") + queries+=("$1") shift ;; esac done -# Print usage if no query was given -if [ "${#query[@]}" == 0 ]; then +# Print usage if no queries were given +if [ "${#queries[@]}" == 0 ]; then print_usage fi @@ -113,17 +119,17 @@ media_directories=${media_directories//[[:blank:]]/} IFS="," read -a media_directories <<< "$media_directories" # Construct find argument array -find_arguments=() -for i in "${!query[@]}"; do +# Ignore hidden files and directories and list only files and symlinks +find_arguments=("-not" "-path" "'*/\.*'" "-type" "f,l") +for i in "${!queries[@]}"; do - # If more than one query is given add a logical AND - if [ "$i" -ge 1 ]; then - find_arguments+=("-a") + # If -o flag is set and more than one query is given, add a logical OR + if [ "$or" == true ] && [ "$i" -ge 1 ]; then + find_arguments+=("-o" "-not" "-path" "'*/\.*'" "-type" "f,l") fi - # Use the ipath argument to search case-insensitive - find_arguments+=("-ipath") - find_arguments+=("'*${query[$i]}*'") + # Use the ipath argument to search case-insensitive and surround query with wildcards + find_arguments+=("-ipath" "'*${queries[$i]}*'") done # Initialize result arrays @@ -139,7 +145,7 @@ for media_directory in "${media_directories[@]}"; do # Get connection string and remote directory IFS="/" read -r connection_string directory <<< "$media_directory" - echo -ne "Fetching results from $text_bold$connection_string$text_reset\n" + echo -ne "Fetching results from $text_bold$(basename $directory)$text_reset on $text_bold$connection_string$text_reset\n" # Add leading and trailing slash to directory if missing [[ "$directory" != /*/ ]] && directory="/$directory/" @@ -147,7 +153,7 @@ for media_directory in "${media_directories[@]}"; do # Get search results from remote # Look for paths matching given queries in visible directories, listing only filenames and links - mapfile -t tmp_results < <(ssh -o ConnectTimeout=10 "$connection_string" find "$directory" -not -path \"*/\.*\" -type l,f "${find_arguments[@]}" | sort) + mapfile -t tmp_results < <(ssh -o ConnectTimeout=10 "$connection_string" find "$directory" "${find_arguments[@]}" | sort) # Build SFTP strings and printable strings for i in "${!tmp_results[@]}"; do @@ -192,8 +198,8 @@ if [ "$list" == false ]; then # Play all remote files if [ "$shuffle" == true ]; then - mpv --msg-level=all=error,statusline=status --term-status-msg='${playlist-pos-1}/${playlist-count} - ${time-pos}/${duration} - \e[1m${media-title}\e[0m' --shuffle "${sftp_results[@]}" + mpv --shuffle --msg-level=all=error,statusline=status --term-status-msg='${playlist-pos-1}/${playlist-count} - ${time-pos}/${duration} - \e[1m${metadata/artist:}${?metadata/artist: - }${metadata/title:}${!metadata/title:${filename/no-ext}}\e[0m' "${sftp_results[@]}" else - mpv --msg-level=all=error,statusline=status --term-status-msg='${playlist-pos-1}/${playlist-count} - ${time-pos}/${duration} - \e[1m${media-title}\e[0m' "${sftp_results[@]}" + mpv --msg-level=all=error,statusline=status --term-status-msg='${playlist-pos-1}/${playlist-count} - ${time-pos}/${duration} - \e[1m${metadata/artist:}${?metadata/artist: - }${metadata/title:}${!metadata/title:${filename/no-ext}}\e[0m' "${sftp_results[@]}" fi fi