You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

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 (AJW won't write this if delay is skipped)
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,GoToIf($["${EXTEN:-2}" > "19"]?9999)			# Make sure we don't exceed the actual number of tracks
same = n,GoTo(cart-player,*${EXTEN:-2},1)				# Pass the last two digits to cart-player as *ext
same = 9999,Playback(option-is-invalid)					# WRONG!
same = n,GoTo(examplejuke-main,s,1)						# Go back and try again

exten = _01XX,1,Set(aa=foobar/01album)					# Repeat for album leading 01
same = n,GoToIf($["${EXTEN:-2}" = "00"]?8track-player,*15,1)
same = n,GoToIf($["${EXTEN:-2}" > "19"]?9999)
same = n,GoTo(cart-player,*${EXTEN:-2},1)
same = 9999,Playback(option-is-invalid)					
same = n,GoTo(examplejuke-main,s,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}" > "19"]?9999)			# Make sure we don't exceed the actual number of tracks
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.
same = 9999,Playback(option-is-invalid)					# WRONG!
same = n,GoTo(examplejuke-main,s,1)						# Go back and try again

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. ##### Wait? What? This doesn't even make any sense now. I gotta stop writing stuff at 3AM.