0

I am a pipefitter working in a weld shop and need music as commercial radio is very repetitive. I went and bought a RPI3 and put Raspian Stretch Lite on it with the fm_transmitter program. I got the shell script far along enough that the radio works fine but sometimes I'll get a song to play again within a short time. This is just by chance as the RANDOM_FILE variable chooses from an entire directory. I have also gotten the script to log each song that is played in a text file. I would like to use tail and grep to search the text file for the current selected RANDOM_FILE and check if it is present within the last X number of songs in the log. I want the script to restart back at the top defining a new RANDOM_FILE if the RANDOM_FILE is present in the grep command. If it isn't present, I want the script to continue, allowing the RANDOM_FILE to play through the fm_transmitter program.

I would also like for someone to check that the string defining RANDOM_FILE is in fact, truly random and correct.

Below is the script in it's current form. I believe I am close, but am going wrong somewhere as I still am getting repeats. I need help with the "if" "then" "else" and "return" commands. I am hoping this is a quick and easy solution.

Thank you in advance to anyone that takes the time to help me out.

#!/bin/bash

while :
do
    files=(/home/pi/music/*.wav)
    RANDOM_FILE="${files[RANDOM % ${#files[@]}]}"

        if tail -n 25 /home/pi/transmit_log.txt | grep "$RANDOM_FILE" = true ; then
            echo -e "---SONG_SKIPPED---" >> /home/pi/transmit_log.txt ; return 7
        else

#            [ tail -n 25 /home/pi/transmit_log.txt | grep "$RANDOM_FILE" = false ] ; then
            return 22
        fi

    echo -e "$RANDOM_FILE" >> /home/pi/transmit_log.txt
    sox -v 3 "$RANDOM_FILE" -r 44100 -c 1 -b 16 -t wav - | sudo ./fm_transmitter -f 91.7 -
    sleep .5


done
codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 2
    It's a little unclear what your question is, or there are a lot of interrelated questions which are hard to answer. Unfortunately, [so] is a _terrible_ tutorial site, and an even worse debugger. You would do better just giving things a try and coming back with a specific question. One thing needs to be said, though: There is "random" and there is "random". Computers, especially little ones, are terrible at true randomness, so the best you can get is pseudo-random. –  Feb 21 '18 at 22:47
  • That being said, there are techniques for improving the apparent randomness -- often by reseeding the "random number generator", etc.What you are doing here is fine -- just ignoring the results if we have seen the same choice in the last N plays and trying again. –  Feb 21 '18 at 22:55
  • Ok, I think your main question is "why am I getting song repeats even if I ignore choices that match the last 25 plays"? This is where debugging comes into use. You are already logging skips and plays, so inspect the play log and see if your perception matches reality. Are you really getting duplicates? Are you getting any skips at all? This leads naturally to asking if the line that skips songs is doing what you think it is doing. I think your answer might be here: https://unix.stackexchange.com/a/48536/156990 –  Feb 21 '18 at 22:58
  • Also useful: https://stackoverflow.com/q/8988824/1531971 (See the answers, especially about using `/dev/urandom`) –  Feb 21 '18 at 23:04

2 Answers2

1

I don't believe you can return in the if/else statement like so. Return is used in a function to return a value. Instead, you can use continue, that will skip until the next iteration of the loop (and fix the test like suggested by codeforester):

#!/bin/bash
while :
do
    files=(/home/pi/music/*.wav)
    RANDOM_FILE="${files[RANDOM % ${#files[@]}]}"

    if tail -n 25 /home/pi/transmit_log.txt | grep -q "$RANDOM_FILE" ; then
        echo "---SONG_SKIPPED---" >> /home/pi/transmit_log.txt
        continue
    fi

    echo "$RANDOM_FILE" >> /home/pi/transmit_log.txt
    sox -v 3 "$RANDOM_FILE" -r 44100 -c 1 -b 16 -t wav - | sudo ./fm_transmitter -f 91.7 -
    sleep .5
done

Alternatively, it can be better to split your tests like shown below to make the if condition smaller and more readable:

already_played=$( tail -n 25 /home/pi/transmit_log.txt | grep "$RANDOM_FILE" )
if [ ! -z "$aldeady_played" ]; then
    ...
fi
Asct20
  • 84
  • 4
  • I can't think of any scenario in which `echo -e` would be more correct here than `echo` without the `-e`. (BTW, when you *do* need the behavior of expanding backslash-escape sequences, [the POSIX spec for `echo`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html) explicitly suggest using `printf %b` instead; see the APPLICATION USAGE section). – Charles Duffy Feb 21 '18 at 22:58
  • TheEmbeddedLab: I tried your first edit of the script and it appears to be working now. Thank you very much. – TheChopsChronicles Feb 21 '18 at 23:08
  • @CharlesDuffy You're right, I was basing this code off of the one TheChopsCronicles originally posted and didn't notice the -e. I'll edit my answer. – Asct20 Feb 21 '18 at 23:23
0

The issue is in this statement:

if tail -n 25 /home/pi/transmit_log.txt | grep "$RANDOM_FILE" = true; then ...

The right way to it is:

if tail -n 25 /home/pi/transmit_log.txt | grep -q "$RANDOM_FILE"; then ...

In your construct, = true would be passed as arguments to grep. That's not what you want, right? grep -q will return 0 (or true) if the pattern was found and I believe that is what you want.

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • Ok, the ----SONG_SKIPPED---- text is showing up in the transmit_log.txt file now, but an examination of the log shows that songs that are playing have been played in the previous 200 lines of the transmit_log.txt. (I edited the tail command to: tail -n 200 to increase the chance of having to skip a song) Is it that the script is not returning to the beginning of the script to start over? That the script is still allowing the supposedly skipped file to play as well as adding ----SONG_SKIPPED---- to the log? – TheChopsChronicles Feb 21 '18 at 22:48