LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Is this feasible (https://www.linuxquestions.org/questions/linux-newbie-8/is-this-feasible-658532/)

greengrocer 07-27-2008 07:00 AM

Is this feasible
 
Hello all,

I am considering an attempt to make some kind of bash script which can fetch a random entry from a playlist, invoke xine to play the entry from the play list and set a volume level accordingly.

To do this, I would need to make a list of entries which would have a parameter, separated by a comma at the begining of each row, which represents a playback volume. The list would need a row count at the beginning of the file too, perhaps.

That of course is the easy bit.

I have thought this through a little bit and I think I would need a script to perform the following tasks

- Script to read first row of list which will set a variable representing the row count.

- Script to choose a random number between 1 and the "row count" found in the list.

- Script to use the random number to find a row number in the list and fetch the data from that row

- Script then sets a variable representing the volume

- Script sets a variable representing the path to a file to be played

- Script invokes xine by way of xine -f -g -S --session 0,volume=<$VOL>,mrl=<$PATH>


Not being all that familiar with BASH scripts, I was wondering if this idea was a little too ambitious or not. Can this actually be achieved with a BASH script I guess is what I am wondering?


Regards,
Greenie

unSpawn 07-27-2008 08:00 AM

Definately not hard. Might think about chars encountered in paths and filenames and the separator you use.

arizonagroovejet 07-27-2008 10:20 AM

That's totally doable. You only need one script, not the 6 you list. Random numbers, or at least random enough for your purposes, are trivial.
Code:

$ let foo=$RANDOM
if you want a number between 0 and 99
Code:

$ let foo=$RANDOM%100
Look at the wc command for getting a line count of a file. cut, head and tail will probably all be useful. There are lots of useful little commands like those that can all be stuck together to achieve all kinds of things.

greengrocer 08-02-2008 08:12 AM

Why does:

Code:

echo $[($RANDOM % 10) + 1]
produce:

random_script.sh: 5: Syntax error: "(" unexpected

???

I got the example from:

http://linuxtechsupport.blogspot.com...om-number.html

pixellany 08-02-2008 08:23 AM

This works:

echo $(($(($RANDOM % 10)) + 1))

I'm sure there's a more elegant notation somewhere....

greengrocer 08-02-2008 08:26 AM

Quote:

Originally Posted by pixellany (Post 3234267)
This works:

echo $(($(($RANDOM % 10)) + 1))

I'm sure there's a more elegant notation somewhere....


I get:

Code:

random_script.sh: 5: arithmetic expression: syntax error: "( % 10) + 1"

pixellany 08-02-2008 08:46 AM

Works here....
Try using cut and paste to avoid typos?

Also, test things like this in pieces. For example, does this work?

echo $(($((4567 % 10)) + 1))

This?

echo $((4567 % 10))

greengrocer 08-02-2008 09:00 AM

Quote:

Originally Posted by pixellany (Post 3234288)
Works here....
Try using cut and paste to avoid typos?

Also, test things like this in pieces. For example, does this work?

echo $(($((4567 % 10)) + 1))

This?

echo $((4567 % 10))


That works, but if I replace the 4567 with $RANDOM, I then get:

random_script.sh: 5: arithmetic expression: syntax error: "( % 10) + 1"


BTW, I always copy+paste, re-typing is too slow, easier to copy+paste.

greengrocer 08-02-2008 09:12 AM

If I do:

Code:

echo $RANDOM
Actually the above works.

But this doesn't:

Code:

number=$RANDOM
  echo $number

above code gives me a blank line.

arizonagroovejet 08-02-2008 10:48 AM

What shell are you using?

Code:

mike@continuity:~$ echo $0
/bin/bash
mike@continuity:~$ echo $RANDOM
32275
mike@continuity:~$ number=$RANDOM
mike@continuity:~$ echo $number
13029
mike@continuity:~$


greengrocer 08-02-2008 11:23 AM

user@edgy:~$ echo $0
bash
user@edgy:~$

arizonagroovejet 08-02-2008 11:27 AM

Hmmmm. Try

Code:

mike@continuity:~$ bash --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.


smoked kipper 08-02-2008 11:59 AM

Quote:

Originally Posted by pixellany (Post 3234267)
This works:

echo $(($(($RANDOM % 10)) + 1))

I'm sure there's a more elegant notation somewhere....

There certainly is, no need for so much nesting:

Code:

echo $(( (RANDOM % 10) + 1))
No need for a $ to dereference RANDOM either, it is implied inside $(( )).

unSpawn 08-02-2008 12:12 PM

Quote:

Originally Posted by greengrocer (Post 3234270)
Code:

random_script.sh: 5: arithmetic expression: syntax error: "( % 10) + 1"

I can reproduce that using 'jsh' which behaves as strict as the "true" Bourne Shell.


Moving ahead of schedule slightly here's a quick idea for creating a dirlisting with sequence number, volume, filename:
Code:

createListing() { [ -d "$1" ] || exit 1; SEP=' '; N=0; VOL=90; find "$1" -type f -iname \*.avi \
-printf "\"%p\"\n"|while read LINE; do ((N++)); echo "${N}|${VOL}|${LINE}"; done|while \
read LINE; do ARRAY=(${LINE//|/  }); echo -en "${ARRAY[0]}${SEP}${ARRAY[1]}${SEP}";
unset ARRAY[0] ARRAY[1]; echo "${ARRAY[*]}${SEP}"; done; }


smoked kipper 08-02-2008 12:22 PM

As arizonagroovejet mentioned earlier, there's no point have a row count, just use wc to count the number of lines.

Do you need a seperate volume level for each file? Won't one do? If the files have different volumes, you could normalize them.

If you do need seperate volumes, you could read the file into two arrays, one for filenames one for volumes, then pick one to play.

E.g.

Code:

#/bin/sh

volumes=()
files=()

# Assume whitespace seperator. Uncomment if fields are comma seperated.
# In that case, you might want to save and restore IFS.
#IFS=,

while read filename volume; do
    files=("${files[@]}" "$filename")
    volumes=(${volumes[*]} $volume)
done < "$1"

len=${#files[*]}

while true; do # use whatever condition you want
    n=$(( RANDOM % len ))
    xine -f -g -S --session 0,volume=${volumes[$n]},mrl=${files[$n]}
done

Of course, that will just loop indefinitely until you break it.

If you want a limited number of plays, how do want to do it? Just play N files or do you want to play them all? I.e. if you play files at random, it's obviously unlikely you'd play them all without repeating any. If you want to make sure the're all played, you'll have to keep track of what's been played. You could remove a file from the list once it's played, then when the list is empty, it's finished. E.g.

Code:

while [[ -n "$files" ]]; do
    n=$(( RANDOM % len ))
    xine -f -g -S --session 0,volume=${volumes[$n]},mrl="${files[$n]}"
    unset files[$n]
    unset volumes[$n]
done



All times are GMT -5. The time now is 05:27 AM.