Fix cartplayer extension fallthrough. Add HOWTHISWORKS.MD. Added ajw.sh

master
Jay 2 years ago
parent aad3b2aa18
commit 49316a7981

@ -0,0 +1,131 @@
# Asterisk Jukebox Theory of Operation & Explanation
## Welcome
This document will hopefully demystify just what an Asterisk Jukebox is and how it works. If you haven't guessed by the fact it's called a jukebox it plays music,
specially it can play full albums or a single track from an album in an almost-automatic fashion based on DTMF input from a user.
## Basic Explanation
The user dials the jukebox. They then punch in a 4 digit number; this corresponds to a format of the first two digits being the album, and last two being track number.
The user can enter a special track number of 00 to play a full album. Playback is controlled entirely through dialplan logic in a mostly automatic fashion; it increments
through tracks using a counter and ends when it hits the total number of tracks. This information is passed to the playback context from a setup context. These are placed
into to two files:
- tapecart-player.conf: Contains the playback logic shared among all jukeboxes. (It's the playback mechanism)
- $name-main.conf: Contains the dialplan to setup tapecart-player to play. (It stacks the records and hits play)
In order for this to work it requires you to not just pre-encode your files to a compatible format; but it also requires to you stick to a pre-set folder/filename convention.
This...conveniently...is simply jukeboxroot/albumfolder/(0)1-99.ulaw. The dialplan logic can be set to handle leading 0s for files under 10.
To aid in creation of a jukebox; the ajw.sh script will generate these for you given just a few options.
### #name-main.conf
The configuration context can be in a sperate file included in your extensions.conf; or copy pasted in to your extensions.conf. The main point is that Asterisk knows where to find
the context for configuration as well as the two for playback. These can be generated by hand, if you want; the copy/paste format is easy enough to do. But for large jukeboxes it
can get tedious, hence a script.
```
[examplejuke-main]
exten = s,1,Answer() # Answer the channel.
same = n,Set(VOLUME(TX)=-3) # Lower volume since that seems necessary.
same = n,Set(c=examplejuke-main) # Set the "c" variable so we can return to this context.
same = n(loop),Background(foobar/menu) # Label for "loop", plays the menu audio.
same = n,WaitExten(5) # Wait a few seconds
same = n,Set(m=$[${m} + 1]) # Increase "m" by one.
same = n,GoToIf($["${m}" < "5"]?loop) # Compare to "5", return to "loop" if true.
same = n,(goodbye)Background(foobar/bye) # It was false...good bye. "Goodbye" label.
same = n,Hangup() # SLAM
exten = _00XX,1,Set(aa=foobar/00album) # Set the aa variable to the album directory for leading 00
same = n,GoToIf($["${EXTEN:-2}" = "00"]?8track-player,*11,1) # Check last two dialed. If album playback, pass total tracks as extension.
same = n,GoTo(cart-player,*${EXTEN:-2},1) # Pass the last two digits to cart-player as *ext
exten = _01XX,1,Set(aa=foobar/01album) # Repeat for album leading 01
same = n,GoToIf($["${EXTEN:-2}" = "00"]?8track-player,*15,1)
same = n,GoTo(cart-player,*${EXTEN:-2},1)
exten = _02XX,1,Set(aa=foobar/02album) # Album 02 is different. Files do not have a leading 0.
same = n,GoToIf($["${EXTEN:-2}" = "00"]?8track-player,#12,1) # Pass last two to 8track-player's # pattern.
same = n,GoToIf($["${EXTEN:-2}" < "10"]?cart-player,#${EXTEN:-1},1) # If the last two are less than 10; pass to single digit to cart-player #ext
same = n,GoTo(cart-player,*${EXTEN:-2},1) # Use the "standard" call for tracks more than 10.
```
The setup for the jukeboxes has undergone about as much optimization as I think I can perform. I did trade a few variables for reducing the overall number of lines.
The need to set the home context is due to all the playback logic not being in the same context. The use of WhileLoops was eliminated entirely due to problems with
the inability to pop cleanly out of a loop. I was also looking to reduce how much you had to create for each jukebox; which allowed the script to do more automated
stuff like automagically counting albums, tracks, and leading zeros. They used to be twice the lines because I was setting total tracks to a variable.
### cart-player and 8track-player
Both of these live in a single file, tapecart-player.conf. They were not designed to be modified by a user and were designed to simply be included in such a way that
your jukebox dialplans can see them. It seemed stupid to constantly rewrite these playback routines every time. In fact I later went through and redid early pre-juke
album setups to use this same logic. Provided you can work with the requirement of number-only filenames it can be handy.
```
[cart-player]
exten = _#X,1,Wait(.25) # The # extensions are for non-leading zeros. Give DTMF time to shut-up.
same = n,Set(z=${EXTEN}) # Write extension to variable for recall later.
same= n,Background(${aa}/${EXTEN:-1}) # Pass the last digit as the file name to be played. (1.ulaw, 9.ulaw)
same = n,Goto(${c},s,return) # It's done. Go home.
exten = _*XX,1,Wait(.25) # All tracks over 10 or with leading zeros. Shut up DTMF.
same = n,Set(z=${EXTEN}) # Write extension to variable for recall later.
same= n,Background(${aa}/${EXTEN:-2}) # Pass last two of extension (the only two) as filename (01.ulaw ... 99.ulaw)
same = n,Goto(${c},s,return) # It's done. Go Home
exten = 2,1,Goto(cart-player,${z},1) # Start the song over.
exten = i,1,Goto(${c},s,return) # Press anything but 2 to go away at any time.
[8track-player]
exten = _*XX,1,Set(tt=${IF($[${EXTEN:-2} < 10]?${EXTEN:-1}:${EXTEN:-2})}) # Leading zeros. Check if album is less than 10 tracks. Set tt (total tracks).
same = n,Set(t=1) # Initialize track counter.
same = n,Set(p=*) # Set context prefix for controls use.
same = n(lead),GoToIf($[${t} = 10]?tenplus) # If we've crossed track 10, jump to "tenplus". Label for "lead".
same = n(hax),Background(${aa}/0${t}) # Prefix 0 to filename based on "t" for leading zeros. "hax" label.
same = n(next),Set(t=$[${t} + 1]) # "next" label. Increases track counter by one.
same = n,GoToIf($[${t} < ${tt}]?lead) # Compares track count to TT value. Loops back to "lead" if not met.
same = n,Goto(${c},s,goodbye) # We played all the tracks. Go back to main menu "goodbye".
same = n(tenplus),Set(p=#) # "tenplus" label. Change p from * to #.
same = n,GoTo(#00,hax) # Switch to the "hax" prority for #00 to continue double-digit file playback.
exten = _#XX,1,Set(tt=${IF($[${EXTEN:-2} < 10]?${EXTEN:-1}:${EXTEN:-2})}) # No Leading zero filenames. Checks for albums less than 10. Sets tt.
same = n,Set(t=1) # Initializes playback counter
same = n,Set(p=#) # Sets the P variable
same = n(hax),Background(${aa}/${t}) # Plays back file. Hax label. Entry point from * land.
same = n(next),Set(t=$[${t} + 1]) # Increase track count
same = n,GoToIf($[${t} < ${tt}]?hax) # Look at track count compared to total. Go back to hax if not done.
same = n,Goto(${c},s,goodbye) # Done. Stop wasting my money/
exten = 1,1,GoToIf($["${t}" = "1"]?wait) # Track back. Check to see if we can go back. Just skip if we can't.
same = n,Set(t=$[${t} - 1]) # Subtract 1 from T.
same = n(wait),Wait(.25) # Wait for DTMF to shut up.
same = n,Goto(${p}00,hax) # Go back from whatever extension branch we were one based on p to the hax label.
exten = 2,1,Wait(.25) # Wait.
same = n,Goto(${p}00,hax) # Just loop back to hax without changing track count.
exten = 3,1,Wait(.25) # Wait.
same = n,Goto(${p}00,next) # Jump to "next" in wherever the hell we are.
exten = 0,1,Goto(${c},s,return) # Press 0 to go home.
```
So the basic idea is that these dialplans either play back a single file, or play back an album. They do so without manaually coding a list of files by relying on the files to be
organized and named a specific way; then just using the basic logic functions of the dialplan. Name your files to track numbers; use a variable to count tracks; tell the program
to play the file that matches the number in the variable. Repeat this until you hit the end of the tracks.
The reality is you also have to tell it how many tracks you have and deal with a little issue of leading zeros. Here's the leading 0 issue in a nutshell:
- My files are name 01.ulaw, 02.ulaw, 03.ulaw, etc...
- I set T as 01 manually. Asterisk plays 01.ulaw.
- Track ends. Dialplan adds one to T.
- T is now 2. 2 != 02.
So why was this a problem? Why not just drop the leading zeros from the file name? Because I knew either way I'd have to add some logic. What I should have done is set the dialplans
to require # for entry; this would have allowed me to do 3 or 4 digit entries and not have any additional logic; other than the extra pattern matching. IF I kept the 4 digit entry,
I'd have to add logic to check for tracks less than 10 so i write the file variable properly. The logical solution was to add the extra logic and make it flexible. The script that
writes the jukebox dialplans handles whether or not we call a leading 0 extension. I wind up adding about the same amount of code for a fix but gain more in it's flexibility. In fact
the "hax" label was an early hold-over from testing the leading 0 routine; originally the playback routines were hard-coded in the jukebox dialplan.
Though we call specific extensions in the context; once we're in we don't. The number you pass as an extension just configures the number of tracks. Once we have that, we don't need
it. This is why the playback controls and "over 10" make a call to double-0...specifically double-zero hax label. We just need to get back in to the proper set of logic. Calling ext
00 from outside the playback context would likely result in the first file playing and then ending immedately. In fact...brainstorm. Pass the number of tracks and track selection as
a four digit extension. Set number of tracks to 00 with track number to get single track playback; pass number of tracks with track number 00 to play an album. That might be the next
major revision to the asterisk jukebox if I can figure out how to handle the leading 0 BS.

@ -8,10 +8,10 @@ as logic to perform this playback.
Asterisk Jukebox & Player consist of two basic dialplans:
```
a common set of logic for playback called from a jukebox interface
a jukebox interface dialplan for music/album selection
```
- a common set of logic for playback called from a jukebox interface
- a jukebox interface dialplan for music/album selection
There is no reason you cannot use the player outside of a jukebox, provided you
set all the variables and call the proper extensions in it's context.
@ -49,14 +49,14 @@ extensions.conf.
tapecart-player.conf provides two contexts:
[cart-player] - provides single track playback
[8track-player] - provides album playback
- [cart-player] - provides single track playback
- [8track-player] - provides album playback
For both contexts, the following variables will need to be set before sending a
channel to them:
c - the context you are sending from (used for returning from player)
aa - the path relative to your asterisk sounds directory your files live.
- c - the context you are sending from (used for returning from player)
- aa - the path relative to your asterisk sounds directory your files live.
Both contexts use pattern matching extensions to select behavior as well as
pass information.
@ -81,6 +81,8 @@ which is not equal to "02" and causes playback to fail. Some of the logic for
cart-player is done at the jukebox dialplan for dealing with lack of leading
zeros; because sometimes you EXTEN:-2 and sometimes you want to EXTEN:-1.
The ajw.sh script will generate the configuration dialplans for you.
## Using The Jukebox
@ -96,9 +98,9 @@ to enter a 4 digit code comprised of the album and track number:
Track number "00" is special and when entered, will play the entire album back
from the beginning. In album playback, the following controls affect playback:
1 - skips back a track
2 - repeats the current track
3 - skips ahead a track
- 1 - skips back a track
- 2 - repeats the current track
- 3 - skips ahead a track
At the end of the album, or at any time during playback; pressing 0 returns to
the main menu.
@ -109,55 +111,14 @@ pressing 0.
# History
```
05-MAY-2022: Initial Commit to self-hosted git.
14-AUG-2022: Fix cartplayer extension fallthrough. Add HOWTHISWORKS.MD. Added ajw.sh
06-MAY-2022: Update Readme. Add conf/examples.
05-MAY-2022: Initial Commit to self-hosted git.
```
# Explanation of Operation
Rather than just write a script to generate a massively large dialplan with
everything hard-coded; the playback logic was designed to be universal and
uses extensions to configure parts of it.
From your jukebox dialplan, the first two digits of entry are hard-coded and
set the folder location for those tracks. The last two digits are pattern
matched. If they're 00, it calls the appropiate extension 8track-player.
Otherwise it calls the proper extension for cart-player; using additional
logic for leading 0s.
For single track playback (cart-player context), two pattern matching
extensions are used:
```
#X - with X being 1 - 9 for files without leading zeros
*XX - with XX being all tracks > 10 or with leading zeros
```
The only difference between them is how many digits you send and how many it
pulls from the "dialed extension". Pound and asterisk are used as a pre-fix to
avoid conflict with 1,2,3, and 0 controls.
For album playback, the situation is quite similar:
```
#XX - with XX being the number of tracks plus one. files without leading 0.
*XX - with XX being the same as above, but files with leading 0.
```
When you call the aprpropiate extension, the player determines if the track
number is less than 10 so it can write that variable appropiately. It then sets
a variable to either `#` or `*`, depending which was used. This variable is
used for the playback controls.
If your files don't have the leading zero (sent to #), then the routine simply
plays a track, increments the counter, compares it to the track count, and then
sends it back to playback or not. For channels sent to \* because you have
leading zeros, a few additional steps are done. Rather than jump directly to
playback; we check to see if current track has hit ten. If not, continue as
usual. But when you do hit track 10, we jump to a couple of lines that change
the varible from pound to star, and then dump us in to the context at normal
playback. We then finish the remainder of the album looping through the pound
extension.
A full breakdown is in HOWTHISWORKS.MD

@ -0,0 +1,57 @@
#!/bin/bash
#ajw v1.02 - jukebox for asterisk wizard
#Jay Moore/NQ4T - https://git.pickmy.org/dewdude/ajw
#Twitter: @Music_OnHold
#Licensed under GPL-3.0-or-later
# Works like this:
# Put all your albums in your Asterisk sounds directory: /jukebox root/album/track#.ulaw
# Run script, enter prompts.
# Copy .conf, include in extensions.conf, assign extension.
setup() {
printf "[$name-main]\nexten = s,1,Answer()\nsame =n,Set(VOLUME(TX)=$vol)\nsame = n,Set(c=$name-main)\nsame = n(return),Set(m=1)\nsame = n(loop),Background($rootfolder/$introfile)\n"
[ "$delay" -ne 0 ] printf "same = n,WaitExten($delay)\n"
printf "same = n,Set(m=\$[\${m} + 1])\nsame = n,GoToIf(\$[\"\${m}\" > \"$loop\"]?loop)\nsame = n(goodbye),Background($rootfolder/$goodbye)\nsame = n,Hangup()\n\n"
} >> $name-juke.conf
album() {
printf "exten = _%02dXX,1,Set(aa=$rootfolder/$folder)\n" $a
[ "$lz" -eq 0 ] && printf "same = n,GoToIf(\$[\"\${EXTEN:-2}\" = \"00\"]?8track-player,#$tc,1)\n" || printf "same = n,GoToIf(\$[\"\${EXTEN:-2}\" = \"00\"]?8track-player,*$tc,1)\n"
[ "$lz" -eq 0 ] && printf "same = n,GoToIf(\$[\"\${EXTEN:-2}\" < \"10\"]?cart-player,#\${EXTEN:-1},1)\n"
printf "same = n,GoTo(cart-player,*\${EXTEN:-2},1)\n\n"
} >> $name-juke.conf
printf "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |a|j|w| - asterisk jukebox wizard\n version 1.02 - Jay Moore/NQ4T\n https://git.pickmy.org/dewdude/jaw\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n\n"
printf "Pick a name/identifier for this jukebox: "
read name
printf "\nEnter the root folder name of your jukebox: "
read rootfolder
printf "\nEnter the filename of your menu/intro: "
read introfile
printf "\nHow many times do you want it to play? "
read loop
printf "\nHow many seconds between intro play? (Enter 0 for no delay)"
read delay
printf "\nEnter the filename of your exit file: "
read goodbye
printf "\nEnter a channel volume (I recommend -3): "
read vol
printf "\nWriting Basic Configuration.\n\nAuto-Generating Albums\n\n"
setup;
asd=/var/lib/asterisk/sounds/en/astjuke
dir=$(ls $asd/$rootfolder -l | awk '/^d/ {print $9}')
a=0
for folder in $dir
do
tracks=$(ls $asd/$rootfolder/$folder -l | grep "ulaw" | wc -l)
tracks=$((tracks + 1))
tc=$(printf "%02d" $tracks)
ld=$(ls $asd/$rootfolder/$folder -l | grep "ulaw" | awk '{print $9}' | awk '/^0/')
[ -z "$ld" ] && lz=0 || lz=1
album;
a=$((a + 1))
done
printf "\n\nDone.\n\n\nYour jukebox is located at $name-juke.conf.\n"
printf "Make sure to include it and the player conf in your dial plan somewhere.\n\n\n\n"

@ -1,11 +1,20 @@
;tapeplayer.conf - Asterisk Jukebox - Version 1.something
;Jay Moore - NQ4T - Twitter: @Music_OnHold
;https://git.pickmy.org/dewdude/Asterisk_Jukebox
;https://git.pickmy.org/dewdude/ajw
[cart-player]
exten = _#X,1,Wait(.25)
same= n,Background(${aa}/${EXTEN:-1})
same = n,Set(z=${EXTEN})
same= n(replay),Background(${aa}/${EXTEN:-1})
same = n,Goto(${c},s,return)
exten = _*XX,1,Wait(.25)
same = n,Set(z=${EXTEN})
same= n,Background(${aa}/${EXTEN:-2})
same = n,Goto(${c},s,return)
exten = 0,1,Goto(${c},s,return)
exten = i,1,Goto(${c},s,return)
exten = 2,1,Goto(cart-player,${z},1)
[8track-player]
exten = _*XX,1,Set(tt=${IF($[${EXTEN:-2} < 10]?${EXTEN:-1}:${EXTEN:-2})})

Loading…
Cancel
Save