[asterisk-commits] branch rizzo/base r13236 - in /team/rizzo/base: ./ agi/ apps/ cdr/ channels/ ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Thu Mar 16 09:04:05 MST 2006


Author: rizzo
Date: Thu Mar 16 10:03:38 2006
New Revision: 13236

URL: http://svn.digium.com/view/asterisk?rev=13236&view=rev
Log:
update to HEAD, and merge in the 'say' hooks


Added:
    team/rizzo/base/agi/jukebox.agi   (with props)
Modified:
    team/rizzo/base/CREDITS
    team/rizzo/base/Makefile
    team/rizzo/base/README
    team/rizzo/base/UPGRADE.txt
    team/rizzo/base/agi/Makefile
    team/rizzo/base/apps/app_dial.c
    team/rizzo/base/apps/app_externalivr.c
    team/rizzo/base/apps/app_meetme.c
    team/rizzo/base/apps/app_mixmonitor.c
    team/rizzo/base/apps/app_playback.c
    team/rizzo/base/apps/app_queue.c
    team/rizzo/base/apps/app_rpt.c
    team/rizzo/base/apps/app_sayunixtime.c
    team/rizzo/base/apps/app_voicemail.c
    team/rizzo/base/ast_expr2.fl
    team/rizzo/base/asterisk.c
    team/rizzo/base/cdr.c
    team/rizzo/base/cdr/cdr_sqlite.c
    team/rizzo/base/cdr/cdr_tds.c
    team/rizzo/base/channel.c
    team/rizzo/base/channels/chan_iax2.c
    team/rizzo/base/channels/chan_misdn.c
    team/rizzo/base/channels/chan_phone.c
    team/rizzo/base/channels/chan_sip.c
    team/rizzo/base/channels/chan_zap.c
    team/rizzo/base/channels/misdn/chan_misdn_config.h
    team/rizzo/base/channels/misdn/isdn_lib.c
    team/rizzo/base/channels/misdn/isdn_lib.h
    team/rizzo/base/channels/misdn/isdn_msg_parser.c
    team/rizzo/base/channels/misdn_config.c
    team/rizzo/base/codecs/gsm/Makefile
    team/rizzo/base/config.c
    team/rizzo/base/configs/cdr.conf.sample
    team/rizzo/base/configs/cdr_tds.conf.sample
    team/rizzo/base/configs/iax.conf.sample
    team/rizzo/base/configs/misdn.conf.sample
    team/rizzo/base/configs/zapata.conf.sample
    team/rizzo/base/contrib/utils/rawplayer.c
    team/rizzo/base/doc/asterisk-mib.txt
    team/rizzo/base/doc/billing.txt
    team/rizzo/base/doc/extconfig.txt
    team/rizzo/base/doc/misdn.txt
    team/rizzo/base/doc/realtime.txt
    team/rizzo/base/editline/np/vis.c
    team/rizzo/base/editline/readline.c
    team/rizzo/base/funcs/func_enum.c
    team/rizzo/base/include/asterisk.h
    team/rizzo/base/include/asterisk/config.h
    team/rizzo/base/include/asterisk/doxyref.h
    team/rizzo/base/include/asterisk/options.h
    team/rizzo/base/include/asterisk/say.h
    team/rizzo/base/include/asterisk/sched.h
    team/rizzo/base/jitterbuf.c
    team/rizzo/base/loader.c
    team/rizzo/base/pbx.c
    team/rizzo/base/res/Makefile
    team/rizzo/base/res/res_features.c
    team/rizzo/base/res/res_monitor.c
    team/rizzo/base/res/res_musiconhold.c
    team/rizzo/base/say.c
    team/rizzo/base/sched.c
    team/rizzo/base/utils.c

Modified: team/rizzo/base/CREDITS
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/CREDITS?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/CREDITS (original)
+++ team/rizzo/base/CREDITS Thu Mar 16 10:03:38 2006
@@ -83,6 +83,8 @@
 Michael Jerris - bug marshaling
 Leif Madsen, Jared Smith and Jim van Meggelen - the Asterisk book
 	available under a Creative Commons License at http://www.asteriskdocs.org
+Brian M. Clapper - poll.c emulation
+	This product includes software developed by Brian M. Clapper <bmc at clapper.org>
 
 === HOLD MUSIC ===
 Music provided by www.freeplaymusic.com

Modified: team/rizzo/base/Makefile
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/Makefile?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/Makefile (original)
+++ team/rizzo/base/Makefile Thu Mar 16 10:03:38 2006
@@ -379,7 +379,8 @@
 SUBDIRS=res channels pbx apps codecs formats agi cdr funcs utils stdtime configs
 
 OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
-	translate.o file.o say2.o pbx.o cli.o md5.o term.o \
+	translate.o file.o \
+	pbx.o cli.o md5.o term.o \
 	ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
 	cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \
 	dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
@@ -388,6 +389,11 @@
 	netsock.o \
 	ast_expr2.o ast_expr2f.o \
 	cryptostub.o sha1.o
+
+OBJS+= say.o
+#OBJS+=        say2.o
+
+OBJS+= stdtime/localtime.o
 
 # unused	slinfactory.o \
 

Modified: team/rizzo/base/README
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/README?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/README (original)
+++ team/rizzo/base/README Thu Mar 16 10:03:38 2006
@@ -51,13 +51,15 @@
 	* All Wildcard (tm) products from Digium (www.digium.com)
 	* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
 	* any full duplex sound card supported by ALSA or OSS
+	* any ISDN card supported by mISDN on Linux (BRI)
+	* The Xorcom AstriBank channel bank
         * VoiceTronix OpenLine products
 
 The are several drivers for ISDN BRI cards available from third party sources.
-Check the voip-info.org wiki for more information on chan_capi, chan_misdn and 
+Check the voip-info.org wiki for more information on chan_capi and 
 zaphfc.
 
-* UPGRADING FROM VERSION 1.0
+* UPGRADING FROM AN EARLIER VERSION
 
   If you are updating from a previous version of Asterisk, make sure you
 read the UPGRADE.txt file in the source directory. There are some files

Modified: team/rizzo/base/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/UPGRADE.txt?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/UPGRADE.txt (original)
+++ team/rizzo/base/UPGRADE.txt Thu Mar 16 10:03:38 2006
@@ -53,16 +53,26 @@
 * The ENUMLOOKUP() function with the 'c' option (for counting the number of records),
   but the lookup fails to match any records, the returned value will now be "0" instead of blank.
 
+The IAX2 channel:
+
+* The "mailboxdetail" option has been deprecated.  Previously, if this option
+  was not enabled, the 2 byte MSGCOUNT information element would be set to all
+  1's to indicate there there is some number of messages waiting.  With this
+  option enabled, the number of new messages were placed in one byte and the
+  number of old messages are placed in the other.  This is now the default
+  (and the only) behavior.
+
 The SIP channel:
 
 * The "incominglimit" setting is replaced by the "call-limit" setting in sip.conf.
 
 Installation:
 
-* On BSD systems, the installation directories have changed to more "FreeBSDish" directories. On startup, Asterisk will look for the main configuration in /usr7local/etc/asterisk/asterisk.conf
+* On BSD systems, the installation directories have changed to more "FreeBSDish" directories. On startup, Asterisk will look for the main configuration in /usr/local/etc/asterisk/asterisk.conf
 If you have an old installation, you might want to remove the binaries and move the configuration files to the new locations. The following directories are now default:
 	ASTLIBDIR	/usr/local/lib/asterisk
 	ASTVARLIBDIR	/usr/local/share/asterisk
 	ASTETCDIR	/usr/local/etc/asterisk
 	ASTBINDIR	/usr/local/bin/asterisk
 	ASTSBINDIR	/usr/local/sbin/asterisk
+

Modified: team/rizzo/base/agi/Makefile
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/agi/Makefile?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/agi/Makefile (original)
+++ team/rizzo/base/agi/Makefile Thu Mar 16 10:03:38 2006
@@ -11,7 +11,7 @@
 # the GNU General Public License
 #
 
-AGIS=agi-test.agi eagi-test eagi-sphinx-test
+AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi
 
 CFLAGS+=
 

Added: team/rizzo/base/agi/jukebox.agi
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/agi/jukebox.agi?rev=13236&view=auto
==============================================================================
--- team/rizzo/base/agi/jukebox.agi (added)
+++ team/rizzo/base/agi/jukebox.agi Thu Mar 16 10:03:38 2006
@@ -1,0 +1,488 @@
+#!/usr/bin/perl
+#
+# Jukebox 0.2
+#
+# A music manager for Asterisk.
+#
+# Copyright (C) 2005-2006, Justin Tunney
+#
+# Justin Tunney <jesuscyborg at gmail.com>
+#
+# This program is free software, distributed under the terms of the
+# GNU General Public License v2.
+#
+# Keep it open source pigs
+#
+# --------------------------------------------------------------------
+#
+# Uses festival to list off all your MP3 music files over a channel in
+# a hierarchical fashion.  Put this file in your agi-bin folder which
+# is located at: /var/lib/asterisk/agi-bin  Be sure to chmod +x it!
+#
+# Invocation Example:
+#   exten => 68742,1,Answer()
+#   exten => 68742,2,agi,jukebox.agi|/home/justin/Music
+#   exten => 68742,3,Hangup()
+#
+#   exten => 68742,1,Answer()
+#   exten => 68742,2,agi,jukebox.agi|/home/justin/Music|pm
+#   exten => 68742,3,Hangup()
+#
+# Options:
+#   p - Precache text2wave outputs for every possible filename.
+#       It is much better to set this option because if a caller
+#       presses a key during a cache operation, it will be ignored.
+#   m - Go back to menu after playing song
+#   g - Do not play the greeting message
+#
+# Usage Instructions:
+#   - Press '*' to go up a directory.  If you are in the root music
+#     folder you will be exitted from the script.
+#   - If you have a really long list of files, you can filter the list
+#     at any time by pressing '#' and spelling out a few letters you
+#     expect the files to start with.  For example, if you wanted to
+#     know what extension 'Requiem For A Dream' was, you'd type:
+#     '#737'.  Note, phone keypads don't include Q and Z.  Q is 7 and
+#     Z is 9.
+#
+# Notes:
+# - This AGI script uses the MP3Player command which uses the
+#   mpg123 Program.  Grab yourself a copy of this program by
+#   going to http://www.mpg123.de/cgi-bin/sitexplorer.cgi?/mpg123/
+#   Be sure to download mpg123-0.59r.tar.gz because it is known to
+#   work with Asterisk and hopefully isn't the release with that
+#   awful security problem.  If you're using Fedora Core 3 with
+#   Alsa like me, make linux-alsa isn't going to work.  Do make
+#   linux-devel and you're peachy keen.
+#
+# - You won't get nifty STDERR debug messages if you're using a
+#   remote asterisk shell.
+#
+# - For some reason, caching certain files will generate the
+#   error: 'using default diphone ax-ax for y-pau'.  Example:
+#   # echo "Depeche Mode - CUW - 05 - The Meaning of Love" | text2wave -o /var/jukeboxcache/jukeboxcache/Depeche_Mode/Depeche_Mode_-_CUW_-_05_-_The_Meaning_of_Love.mp3.ul -otype ulaw -
+#   The temporary work around is to just touch these files.
+#
+# - The background app doesn't like to get more than 2031 chars
+#   of input.
+#
+
+use strict;
+
+$|=1;
+
+# Setup some variables
+my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
+my @masterCacheList = ();
+my $maxNumber = 10;
+
+while (<STDIN>) {
+	chomp;
+	last unless length($_);
+	if (/^agi_(\w+)\:\s+(.*)$/) {
+		$AGI{$1} = $2;
+	}
+}
+
+# setup options
+my $SHOWGREET = 1;
+my $PRECACHE = 0;
+my $MENUAFTERSONG = 0;
+
+$PRECACHE = 1 if $ARGV[1] =~ /p/;
+$MENUAFTERSONG = 1 if $ARGV[1] =~ /m/;
+$SHOWGREET = 0 if $ARGV[1] =~ /g/;
+
+# setup folders
+my $MUSIC = $ARGV[0];
+$MUSIC = &rmts($MUSIC);
+my $FESTIVALCACHE = "/var/jukeboxcache";
+if (! -e $FESTIVALCACHE) {
+	`mkdir -p -m0776 $FESTIVALCACHE`;
+}
+
+# make sure we have some essential files
+if (! -e "$FESTIVALCACHE/jukebox_greet.ul") {
+	`echo "Welcome to the Asterisk Jukebox" | text2wave -o $FESTIVALCACHE/jukebox_greet.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_press.ul") {
+	`echo "Press" | text2wave -o $FESTIVALCACHE/jukebox_press.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_for.ul") {
+	`echo "For" | text2wave -o $FESTIVALCACHE/jukebox_for.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_toplay.ul") {
+	`echo "To play" | text2wave -o $FESTIVALCACHE/jukebox_toplay.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_nonefound.ul") {
+	`echo "There were no music files found in this folder" | text2wave -o $FESTIVALCACHE/jukebox_nonefound.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_percent.ul") {
+	`echo "Percent" | text2wave -o $FESTIVALCACHE/jukebox_percent.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_generate.ul") {
+	`echo "Please wait while Astrisk Jukebox cashes the files of your music collection" | text2wave -o $FESTIVALCACHE/jukebox_generate.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_invalid.ul") {
+	`echo "You have entered an invalid selection" | text2wave -o $FESTIVALCACHE/jukebox_invalid.ul -otype ulaw -`;
+}
+if (! -e "$FESTIVALCACHE/jukebox_thankyou.ul") {
+	`echo "Thank you for using Astrisk Jukebox, Goodbye" | text2wave -o $FESTIVALCACHE/jukebox_thankyou.ul -otype ulaw -`;
+}
+
+# greet the user
+if ($SHOWGREET) {
+	print "EXEC Playback \"$FESTIVALCACHE/jukebox_greet\"\n";
+	my $result = <STDIN>; &check_result($result);
+}
+
+# go through the directories
+music_dir_cache() if $PRECACHE;
+music_dir_menu('/');
+
+exit 0;
+
+##########################################################################
+
+sub music_dir_menu {
+	my $dir = shift;
+
+# generate a list of mp3's and directories and assign each one it's
+# own selection number.  Then make sure that we've got a sound clip
+# for the file name
+	if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
+		print STDERR "Failed to open music directory: $dir\n";
+		exit 1;
+	}
+	my @files = sort readdir THEDIR;
+	my $cnt = 1;
+	my @masterBgList = ();
+
+	foreach my $file (@files) {
+		chomp($file);
+		if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
+			my $real_version = &rmts($MUSIC.$dir).'/'.$file;
+			my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
+			my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
+			my $cache_version_esc = &clean_file($cache_version);
+			my $cache_version2_esc = &clean_file($cache_version2);
+
+			if (-d $real_version) {
+#		                                     0:id    1:type 2:text2wav-file      3:for-filtering             4:the-directory 5:text2wav echo
+				push(@masterBgList, [$cnt++, 1,     $cache_version2_esc, &remove_special_chars($file), $file,          "for the $file folder"]);
+			} elsif ($real_version =~ /\.mp3$/) {
+#		                                     0:id    1:type 2:text2wav-file      3:for-filtering             4:the-mp3
+				push(@masterBgList, [$cnt++, 2,     $cache_version2_esc, &remove_special_chars($file), $real_version,  "to play $file"]);
+			}
+		}
+	}
+	close(THEDIR);
+
+	my @filterList = @masterBgList;
+
+	if (@filterList == 0) {
+		print "EXEC Playback \"$FESTIVALCACHE/jukebox_nonefound\"\n";
+		my $result = <STDIN>; &check_result($result);
+		return 0;
+	}
+
+	for (;;) {
+MYCONTINUE:
+
+# play bg selections and figure out their selection
+		my $digit = '';
+		my $digitstr = '';
+		for (my $n=0; $n<@filterList; $n++) {
+			&cache_speech(&remove_file_extension($filterList[$n][5]), "$filterList[$n][2].ul") if ! -e "$filterList[$n][2].ul";
+			&cache_speech("Press $filterList[$n][0]", "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul") if ! -e "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul";
+			print "EXEC Background \"$filterList[$n][2]&$FESTIVALCACHE/jukebox_$filterList[$n][0]\"\n";
+			my $result = <STDIN>;
+			$digit = &check_result($result);
+			if ($digit > 0) {
+				$digitstr .= chr($digit);
+				last;
+			}
+		}
+		for (;;) {
+			print "WAIT FOR DIGIT 3000\n";
+			my $result = <STDIN>;
+			$digit = &check_result($result);
+			last if $digit <= 0;
+			$digitstr .= chr($digit);
+		}
+
+# see if it's a valid selection
+		print STDERR "Digits Entered: '$digitstr'\n";
+		exit 0 if $digitstr eq '';
+		my $found = 0;
+		goto EXITSUB if $digitstr =~ /\*/;
+
+# filter the list
+		if ($digitstr =~ /^\#\d+/) {
+			my $regexp = '';
+			for (my $n=1; $n<length($digitstr); $n++) {
+				my $d = substr($digitstr, $n, 1);
+				if ($d == 2) {
+					$regexp .= '[abc]';
+				} elsif ($d == 3) {
+					$regexp .= '[def]';
+				} elsif ($d == 4) {
+					$regexp .= '[ghi]';
+				} elsif ($d == 5) {
+					$regexp .= '[jkl]';
+				} elsif ($d == 6) {
+					$regexp .= '[mno]';
+				} elsif ($d == 7) {
+					$regexp .= '[pqrs]';
+				} elsif ($d == 8) {
+					$regexp .= '[tuv]';
+				} elsif ($d == 9) {
+					$regexp .= '[wxyz]';
+				}
+			}
+			@filterList = ();
+			for (my $n=1; $n<@masterBgList; $n++) {
+				push(@filterList, $masterBgList[$n]) if $masterBgList[$n][3] =~ /^$regexp/i;
+			}
+			goto MYCONTINUE;
+		}
+
+		for (my $n=0; $n<@masterBgList; $n++) {
+			if ($digitstr == $masterBgList[$n][0]) {
+				if ($masterBgList[$n][1] == 1) { # a folder
+					&music_dir_menu(rmts($dir).'/'.$masterBgList[$n][4]);
+					@filterList = @masterBgList;
+					goto MYCONTINUE;
+				} elsif ($masterBgList[$n][1] == 2) { # a file
+# because *'s scripting language is crunk and won't allow us to escape
+# funny filenames, we need to create a temporary symlink to the mp3
+# file
+					my $mp3 = &escape_file($masterBgList[$n][4]);
+					my $link = `mktemp`;
+					chomp($link);
+					$link .= '.mp3';
+					print STDERR "ln -s $mp3 $link\n";
+					my $cmdr = `ln -s $mp3 $link`;
+					chomp($cmdr);
+					print "Failed to create symlink to mp3: $cmdr\n" if $cmdr ne '';
+					
+					print "EXEC MP3Player \"$link\"\n";
+					my $result = <STDIN>; &check_result($result);
+
+					`rm $link`;
+					
+					if (!$MENUAFTERSONG) {
+						print "EXEC Playback \"$FESTIVALCACHE/jukebox_thankyou\"\n";
+						my $result = <STDIN>; &check_result($result);
+						exit 0;
+					} else {
+						goto MYCONTINUE;
+					}
+				}
+			}
+		}
+		print "EXEC Playback \"$FESTIVALCACHE/jukebox_invalid\"\n";
+		my $result = <STDIN>; &check_result($result);
+	}
+      EXITSUB:
+}
+
+sub cache_speech {
+	my $speech = shift;
+	my $file = shift;
+
+	my $theDir = extract_file_dir($file);
+	`mkdir -p -m0776 $theDir`;
+
+	print STDERR "echo \"$speech\" | text2wave -o $file -otype ulaw -\n";
+	my $cmdr = `echo "$speech" | text2wave -o $file -otype ulaw -`;
+	chomp($cmdr);
+	if ($cmdr =~ /using default diphone/) {
+# temporary bug work around....
+		`touch $file`;
+	} elsif ($cmdr ne '') {
+		print STDERR "Command Failed\n";
+		exit 1;
+	}
+}
+
+sub music_dir_cache {
+# generate list of text2speech files to generate
+	if (!music_dir_cache_genlist('/')) {
+		print STDERR "Horrible Dreadful Error: No Music Found in $MUSIC!";
+		exit 1;
+	}
+
+# add to list how many 'number' files we have to generate.  We can't
+# use the SayNumber app in Asterisk because we want to chain all
+# talking in one Background command.  We also want a consistent
+# voice...
+	for (my $n=1; $n<=$maxNumber; $n++) {
+		push(@masterCacheList, [3, "Press $n", "$FESTIVALCACHE/jukebox_$n.ul"]) if ! -e "$FESTIVALCACHE/jukebox_$n.ul";
+	}
+
+# now generate all these darn text2speech files
+	if (@masterCacheList > 5) {
+		print "EXEC Playback \"$FESTIVALCACHE/jukebox_generate\"\n";
+		my $result = <STDIN>; &check_result($result);
+	}
+	my $theTime = time();
+	for (my $n=0; $n < @masterCacheList; $n++) {
+		my $cmdr = '';
+		if ($masterCacheList[$n][0] == 1) { # directory
+			&cache_speech("for folder $masterCacheList[$n][1]", $masterCacheList[$n][2]);
+		} elsif ($masterCacheList[$n][0] == 2) { # file
+			&cache_speech("to play $masterCacheList[$n][1]", $masterCacheList[$n][2]);
+		} elsif ($masterCacheList[$n][0] == 3) { # number
+			&cache_speech($masterCacheList[$n][1], $masterCacheList[$n][2]);
+		}
+		if (time() >= $theTime + 30) {
+			my $percent = int($n / @masterCacheList * 100);
+			print "SAY NUMBER $percent \"\"\n";
+			my $result = <STDIN>; &check_result($result);
+			print "EXEC Playback \"$FESTIVALCACHE/jukebox_percent\"\n";
+			my $result = <STDIN>; &check_result($result);
+			$theTime = time();
+		}
+	}
+}
+
+# this function will fill the @masterCacheList of all the files that
+# need to have text2speeced ulaw files of their names generated
+sub music_dir_cache_genlist {
+	my $dir = shift;
+	if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
+		print STDERR "Failed to open music directory: $dir\n";
+		exit 1;
+	}
+	my @files = sort readdir THEDIR;
+	my $foundFiles = 0;
+	my $tmpMaxNum = 0;
+	foreach my $file (@files) {
+		chomp;
+		if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
+			my $real_version = &rmts($MUSIC.$dir).'/'.$file;
+			my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
+			my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
+			my $cache_version_esc = &clean_file($cache_version);
+			my $cache_version2_esc = &clean_file($cache_version2);
+
+			if (-d $real_version) {
+				if (music_dir_cache_genlist(rmts($dir).'/'.$file)) {
+					$tmpMaxNum++;
+					$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
+					push(@masterCacheList, [1, $file, $cache_version_esc]) if ! -e $cache_version_esc;
+					$foundFiles = 1;
+				}
+			} elsif ($real_version =~ /\.mp3$/) {
+				$tmpMaxNum++;
+				$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
+				push(@masterCacheList, [2, &remove_file_extension($file), $cache_version_esc]) if ! -e $cache_version_esc;
+				$foundFiles = 1;
+			}
+		}
+	}
+	close(THEDIR);
+	return $foundFiles;
+}
+
+sub rmts { # remove trailing slash
+	my $hog = shift;
+	$hog =~ s/\/$//;
+	return $hog;
+}
+
+sub extract_file_name {
+	my $hog = shift;
+	$hog =~ /\/?([^\/]+)$/;
+	return $1;
+}
+
+sub extract_file_dir {
+	my $hog = shift;
+	return $hog if ! ($hog =~ /\//);
+	$hog =~ /(.*)\/[^\/]*$/;
+	return $1;
+}
+
+sub remove_file_extension {
+	my $hog = shift;
+	return $hog if ! ($hog =~ /\./);
+	$hog =~ /(.*)\.[^.]*$/;
+	return $1;
+}
+
+sub clean_file {
+	my $hog = shift;
+	$hog =~ s/\\/_/g;
+	$hog =~ s/ /_/g;
+	$hog =~ s/\t/_/g;
+	$hog =~ s/\'/_/g;
+	$hog =~ s/\"/_/g;
+	$hog =~ s/\(/_/g;
+	$hog =~ s/\)/_/g;
+	$hog =~ s/&/_/g;
+	$hog =~ s/\[/_/g;
+	$hog =~ s/\]/_/g;
+	$hog =~ s/\$/_/g;
+	$hog =~ s/\|/_/g;
+	$hog =~ s/\^/_/g;
+	return $hog;
+}
+
+sub remove_special_chars {
+	my $hog = shift;
+	$hog =~ s/\\//g;
+	$hog =~ s/ //g;
+	$hog =~ s/\t//g;
+	$hog =~ s/\'//g;
+	$hog =~ s/\"//g;
+	$hog =~ s/\(//g;
+	$hog =~ s/\)//g;
+	$hog =~ s/&//g;
+	$hog =~ s/\[//g;
+	$hog =~ s/\]//g;
+	$hog =~ s/\$//g;
+	$hog =~ s/\|//g;
+	$hog =~ s/\^//g;
+	return $hog;
+}
+
+sub escape_file {
+	my $hog = shift;
+	$hog =~ s/\\/\\\\/g;
+	$hog =~ s/ /\\ /g;
+	$hog =~ s/\t/\\\t/g;
+	$hog =~ s/\'/\\\'/g;
+	$hog =~ s/\"/\\\"/g;
+	$hog =~ s/\(/\\\(/g;
+	$hog =~ s/\)/\\\)/g;
+	$hog =~ s/&/\\&/g;
+	$hog =~ s/\[/\\\[/g;
+	$hog =~ s/\]/\\\]/g;
+	$hog =~ s/\$/\\\$/g;
+	$hog =~ s/\|/\\\|/g;
+	$hog =~ s/\^/\\\^/g;
+	return $hog;
+}
+
+sub check_result {
+	my ($res) = @_;
+	my $retval;
+	$tests++;
+	chomp $res;
+	if ($res =~ /^200/) {
+		$res =~ /result=(-?\d+)/;
+		if (!length($1)) {
+			print STDERR "FAIL ($res)\n";
+			$fail++;
+			exit 1;
+		} else {
+			print STDERR "PASS ($1)\n";
+			return $1;
+		}
+	} else {
+		print STDERR "FAIL (unexpected result '$res')\n";
+		exit 1;
+	}
+}

Propchange: team/rizzo/base/agi/jukebox.agi
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/rizzo/base/agi/jukebox.agi
------------------------------------------------------------------------------
    svn:executable = *

Propchange: team/rizzo/base/agi/jukebox.agi
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/rizzo/base/agi/jukebox.agi
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/rizzo/base/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/apps/app_dial.c?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/apps/app_dial.c (original)
+++ team/rizzo/base/apps/app_dial.c Thu Mar 16 10:03:38 2006
@@ -1425,7 +1425,6 @@
 			}
 			ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
 			ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
-			peer->priority++;
 			ast_pbx_start(peer);
 			hanguptree(outgoing, NULL);
 			LOCAL_USER_REMOVE(u);

Modified: team/rizzo/base/apps/app_externalivr.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/apps/app_externalivr.c?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/apps/app_externalivr.c (original)
+++ team/rizzo/base/apps/app_externalivr.c Thu Mar 16 10:03:38 2006
@@ -65,7 +65,7 @@
 "will receive all DTMF events received on the channel, and notification\n"
 "if the channel is hung up. The application will not be forcibly terminated\n"
 "when the channel is hung up.\n"
-"See doc/README.externalivr for a protocol specification.\n";
+"See doc/externalivr.txt for a protocol specification.\n";
 
 /* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
 #define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)

Modified: team/rizzo/base/apps/app_meetme.c
URL: http://svn.digium.com/view/asterisk/team/rizzo/base/apps/app_meetme.c?rev=13236&r1=13235&r2=13236&view=diff
==============================================================================
--- team/rizzo/base/apps/app_meetme.c (original)
+++ team/rizzo/base/apps/app_meetme.c Thu Mar 16 10:03:38 2006
@@ -1,3 +1,4 @@
+
 /*
  * Asterisk -- An open source telephony toolkit.
  *
@@ -70,18 +71,18 @@
 static const char *synopsis3 = "MeetMe conference Administration";
 
 static const char *descrip =
-"  MeetMe([confno][,[options][,pin]]): Enters the user into a specified MeetMe conference.\n"
-"If the conference number is omitted, the user will be prompted to enter\n"
-"one. \n"
-"User can exit the conference by hangup, or if the 'p' option is specified, by pressing '#'.\n"
+"  MeetMe([confno][,[options][,pin]]): Enters the user into a specified MeetMe\n"
+"conference.  If the conference number is omitted, the user will be prompted\n"
+"to enter one.  User can exit the conference by hangup, or if the 'p' option\n"
+"is specified, by pressing '#'.\n"
 "Please note: A ZAPTEL INTERFACE MUST BE INSTALLED FOR CONFERENCING TO WORK!\n\n"
 
 "The option string may contain zero or more of the following characters:\n"
 "      'a' -- set admin mode\n"
 "      'A' -- set marked mode\n"
 "      'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n"
-"             Default: conf-background.agi\n"
-"             (Note: This does not work with non-Zap channels in the same conference)\n"
+"             Default: conf-background.agi  (Note: This does not work with\n"
+"             non-Zap channels in the same conference)\n"
 "      'c' -- announce user(s) count on joining a conference\n"
 "      'd' -- dynamically add conference\n"
 "      'D' -- dynamically add conference, prompting for a PIN\n"
@@ -90,31 +91,34 @@
 "      'i' -- announce user join/leave\n"
 "      'm' -- set monitor only mode (Listen only, no talking)\n"
 "      'M' -- enable music on hold when the conference has a single caller\n"
+"      'o' -- set talker optimization - treats talkers who aren't speaking as\n"
+"             being muted, meaning (a) No encode is done on transmission and\n"
+"             (b) Received audio that is not registered as talking is omitted\n"
+"             causing no buildup in background noise\n"
 "      'p' -- allow user to exit the conference by pressing '#'\n"
 "      'P' -- always prompt for the pin even if it is specified\n"
 "      'q' -- quiet mode (don't play enter/leave sounds)\n"
 "      'r' -- Record conference (records as ${MEETME_RECORDINGFILE}\n"
 "             using format ${MEETME_RECORDINGFORMAT}). Default filename is\n"
-"             meetme-conf-rec-${CONFNO}-${UNIQUEID} and the default format is wav.\n"
+"             meetme-conf-rec-${CONFNO}-${UNIQUEID} and the default format is\n"
+"             wav.\n"
 "      's' -- Present menu (user or admin) when '*' is received ('send' to menu)\n"
 "      't' -- set talk only mode. (Talk only, no listening)\n"
 "      'T' -- set talker detection (sent to manager interface and meetme list)\n"
-"      'o' -- set talker optimization - treats talkers who aren't speaking as\n"
-"             being muted, meaning (a) No encode is done on transmission and\n"
-"             (b) Received audio that is not registered as talking is omitted\n"
-"             causing no buildup in background noise\n"
 "      'v' -- video mode\n"
 "      'w' -- wait until the marked user enters the conference\n"
 "      'x' -- close the conference when last marked user exits\n"
 "      'X' -- allow user to exit the conference by entering a valid single\n"
 "             digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
-"             if that variable is not defined.\n";
+"             if that variable is not defined.\n"
+"      '1' -- do not play message when first person enters\n";
 
 static const char *descrip2 =
 "  MeetMeCount(confno[|var]): Plays back the number of users in the specified\n"
 "MeetMe conference. If var is specified, playback will be skipped and the value\n"
-"will be returned in the variable. Upon app completion, MeetMeCount will hangup the\n"
-"channel, unless priority n+1 exists, in which case priority progress will continue.\n"
+"will be returned in the variable. Upon app completion, MeetMeCount will hangup\n"
+"the channel, unless priority n+1 exists, in which case priority progress will\n"
+"continue.\n"
 "A ZAPTEL INTERFACE MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
 
 static const char *descrip3 = 
@@ -147,9 +151,10 @@
 	struct ast_conf_user *firstuser;	/* Pointer to the first user struct */
 	struct ast_conf_user *lastuser;		/* Pointer to the last user struct */
 	time_t start;				/* Start time (s) */
-	int recording;				/* recording status */
-	int isdynamic;				/* Created on the fly? */
-	int locked;				/* Is the conference locked? */
+	int refcount;				/* reference count of usage */
+	unsigned int recording:2;				/* recording status */
+	unsigned int isdynamic:1;				/* Created on the fly? */
+	unsigned int locked:1;				/* Is the conference locked? */
 	pthread_t recordthread;			/* thread for recording */
 	pthread_attr_t attr;			/* thread attribute */
 	const char *recordingfilename;		/* Filename to record the Conference into */
@@ -243,31 +248,33 @@
 #define CONFFLAG_ALWAYSPROMPT (1 << 21)
 #define CONFFLAG_ANNOUNCEUSERCOUNT (1 << 22)	/* If set, when user joins the conference, they will be told the number of users that are already in */
 #define CONFFLAG_OPTIMIZETALKER (1 << 23)	/* If set, treats talking users as muted users */
+#define CONFFLAG_NOONLYPERSON (1 << 24)		/* If set, won't speak the extra prompt when the first person enters the conference */
 
 
 AST_APP_OPTIONS(meetme_opts, {
+	AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
 	AST_APP_OPTION('a', CONFFLAG_ADMIN ),
+	AST_APP_OPTION('b', CONFFLAG_AGI ),
 	AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT ),
+	AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ),
+	AST_APP_OPTION('d', CONFFLAG_DYNAMIC ),
+	AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ),
+	AST_APP_OPTION('e', CONFFLAG_EMPTY ),
+	AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
+	AST_APP_OPTION('M', CONFFLAG_MOH ),
+	AST_APP_OPTION('m', CONFFLAG_MONITOR ),
+	AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ),
+	AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
+	AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ),
+	AST_APP_OPTION('q', CONFFLAG_QUIET ),
+	AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
+	AST_APP_OPTION('s', CONFFLAG_STARMENU ),
 	AST_APP_OPTION('T', CONFFLAG_MONITORTALKER ),
-	AST_APP_OPTION('o', CONFFLAG_OPTIMIZETALKER ),
-	AST_APP_OPTION('i', CONFFLAG_INTROUSER ),
-	AST_APP_OPTION('m', CONFFLAG_MONITOR ),
-	AST_APP_OPTION('p', CONFFLAG_POUNDEXIT ),
-	AST_APP_OPTION('s', CONFFLAG_STARMENU ),
 	AST_APP_OPTION('t', CONFFLAG_TALKER ),
-	AST_APP_OPTION('q', CONFFLAG_QUIET ),
-	AST_APP_OPTION('M', CONFFLAG_MOH ),
+	AST_APP_OPTION('w', CONFFLAG_WAITMARKED ),
+	AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
 	AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT ),
-	AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT ),
-	AST_APP_OPTION('A', CONFFLAG_MARKEDUSER ),
-	AST_APP_OPTION('b', CONFFLAG_AGI ),
-	AST_APP_OPTION('w', CONFFLAG_WAITMARKED ),
-	AST_APP_OPTION('r', CONFFLAG_RECORDCONF ),
-	AST_APP_OPTION('d', CONFFLAG_DYNAMIC ),
-	AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN ),
-	AST_APP_OPTION('e', CONFFLAG_EMPTY ),
-	AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN ),
-	AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT ),
+	AST_APP_OPTION('1', CONFFLAG_NOONLYPERSON ),
 });
 
 static char *istalking(int x)
@@ -452,7 +459,7 @@
 		ast_autoservice_stop(chan);
 }
 
-static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic)
+static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic, int refcount)
 {
 	struct ast_conference *cnf;
 	struct zt_confinfo ztc;
@@ -472,6 +479,7 @@
 			ast_copy_string(cnf->confno, confno, sizeof(cnf->confno));
 			ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
 			ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
+			cnf->refcount = 0;
 			cnf->markedusers = 0;
 			cnf->chan = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
 			if (cnf->chan) {
@@ -518,7 +526,7 @@
 			/* Fill the conference struct */
 			cnf->start = time(NULL);
 			cnf->zapconf = ztc.confno;
-			cnf->isdynamic = dynamic;
+			cnf->isdynamic = dynamic ? 1 : 0;
 			cnf->firstuser = NULL;
 			cnf->lastuser = NULL;
 			cnf->locked = 0;
@@ -528,6 +536,9 @@
 		} 
 	}
  cnfout:
+	if (cnf){ 
+		cnf->refcount += refcount;
+	}
 	AST_LIST_UNLOCK(&confs);
 	return cnf;
 }
@@ -845,12 +856,19 @@
 	char meetmesecs[30] = "";
 	char exitcontext[AST_MAX_CONTEXT] = "";
 	char recordingtmp[AST_MAX_EXTENSION] = "";
+	char members[10] = "";
 	int dtmf;
 	ZT_BUFFERINFO bi;
 	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
 	char *buf = __buf + AST_FRIENDLY_OFFSET;
 
 	if (!(user = ast_calloc(1, sizeof(*user)))) {
+		AST_LIST_LOCK(&confs);
+		conf->refcount--;
+		if (!conf->refcount){
+			conf_free(conf);
+		}
+		AST_LIST_UNLOCK(&confs);
 		return ret;
 	}
 
@@ -914,6 +932,10 @@
 	user->adminflags = 0;
 	user->talking = -1;
 	conf->users++;
+	/* Update table */
+	snprintf(members, sizeof(members), "%d", conf->users);
+	ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL);
+
 	ast_mutex_unlock(&conf->playlock);
 
 	if (confflags & CONFFLAG_EXIT_CONTEXT) {
@@ -932,7 +954,7 @@
 		ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL);
 	}
 
-	if (!(confflags & CONFFLAG_QUIET)) {
+	if ( !(confflags & (CONFFLAG_QUIET | CONFFLAG_NOONLYPERSON)) ) {
 		if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED))
 			if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
 				ast_waitstream(chan, "");
@@ -1659,11 +1681,17 @@
 		          "<no name>", hr, min, sec);
 
 		conf->users--;
+		conf->refcount--;
+		/* Update table */
+		snprintf(members, sizeof(members), "%d", conf->users);
+		ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL);
 		if (confflags & CONFFLAG_MARKEDUSER) 
 			conf->markedusers--;
 		if (!conf->users) {
-			/* No more users -- close this one out */
-			conf_free(conf);
+			/* close this one when no more users and no references*/
+			if (!conf->refcount){
+				conf_free(conf);
+			}
 		} else {
 			/* Remove the user struct */ 
 			if (user == conf->firstuser) {
@@ -1703,7 +1731,56 @@
 	return ret;
 }
 
-static struct ast_conference *find_conf(struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin)
+/*
+  This function looks for a conference via the RealTime module
+*/
+static struct ast_conference *find_conf_realtime(struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, int refcount)
+{
+
+	struct ast_variable *var;
+	struct ast_conference *cnf;
+
+	/* Check first in the conference list */
+	AST_LIST_LOCK(&confs);
+	AST_LIST_TRAVERSE(&confs, cnf, list) {
+		if (!strcmp(confno, cnf->confno)) 
+			break;
+	}
+	if (cnf){
+		cnf->refcount += refcount;
+	}
+	AST_LIST_UNLOCK(&confs);
+
+	if (!cnf) {
+		char *pin = NULL, *pinadmin = NULL; /* For temp use */
+
+		cnf = ast_calloc(1, sizeof(struct ast_conference));
+		if (!cnf) {
+			ast_log(LOG_ERROR, "Out of memory\n");
+			return NULL;
+		}
+
+		var = ast_load_realtime("meetme", "confno", confno, NULL);
+		while (var) {
+			if (!strcasecmp(var->name, "confno")) {
+				ast_copy_string(cnf->confno, var->value, sizeof(cnf->confno));
+			} else if (!strcasecmp(var->name, "pin")) {
+				pin = ast_strdupa(var->value);
+			} else if (!strcasecmp(var->name, "adminpin")) {
+				pinadmin = ast_strdupa(var->value);
+			}
+			var = var->next;
+		}
+		ast_variables_destroy(var);
+
+		cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount);
+	}
+
+	return cnf;
+}
+
+
+static struct ast_conference *find_conf(struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, int refcount)
 {
 	struct ast_config *cfg;
 	struct ast_variable *var;
@@ -1721,6 +1798,9 @@
 		if (!strcmp(confno, cnf->confno)) 
 			break;
 	}
+	if (cnf){
+		cnf->refcount += refcount;
+	}
 	AST_LIST_UNLOCK(&confs);
 
 	if (!cnf) {
@@ -1733,9 +1813,9 @@
 					if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, AST_MAX_EXTENSION - 1, 0) < 0)
 						return NULL;
 				}
-				cnf = build_conf(confno, dynamic_pin, "", make, dynamic);
+				cnf = build_conf(confno, dynamic_pin, "", make, dynamic, refcount);
 			} else {
-				cnf = build_conf(confno, "", "", make, dynamic);
+				cnf = build_conf(confno, "", "", make, dynamic, refcount);
 			}
 		} else {
 			/* Check the config */
@@ -1757,14 +1837,14 @@
 					/* Bingo it's a valid conference */
 					if (args.pin) {
 						if (args.pinadmin)
-							cnf = build_conf(args.confno, args.pin, args.pinadmin, make, dynamic);
+							cnf = build_conf(args.confno, args.pin, args.pinadmin, make, dynamic, refcount);
 						else
-							cnf = build_conf(args.confno, args.pin, "", make, dynamic);
+							cnf = build_conf(args.confno, args.pin, "", make, dynamic, refcount);
 					} else {
 						if (args.pinadmin)
-							cnf = build_conf(args.confno, "", args.pinadmin, make, dynamic);
+							cnf = build_conf(args.confno, "", args.pinadmin, make, dynamic, refcount);
 						else
-							cnf = build_conf(args.confno, "", "", make, dynamic);
+							cnf = build_conf(args.confno, "", "", make, dynamic, refcount);
 					}
 					break;
 				}
@@ -1813,7 +1893,7 @@
 
 	AST_STANDARD_APP_ARGS(args, localdata);
 	
-	conf = find_conf(chan, args.confno, 0, 0, NULL);
+	conf = find_conf(chan, args.confno, 0, 0, NULL, 0);
 	if (conf)
 		count = conf->users;
 	else
@@ -1999,7 +2079,10 @@
 		}
 		if (!ast_strlen_zero(confno)) {
 			/* Check the validity of the conference */
-			cnf = find_conf(chan, confno, 1, dynamic, the_pin);
+			cnf = find_conf(chan, confno, 1, dynamic, the_pin, 1);
+			if (!cnf) {
+				cnf = find_conf_realtime(chan, confno, 1, dynamic, the_pin, 1);
+			}
 			if (!cnf) {
 				res = ast_streamfile(chan, "conf-invalid", chan->language);
 				if (!res)
@@ -2040,8 +2123,15 @@
 								res = ast_streamfile(chan, "conf-invalidpin", chan->language);
 								if (!res)
 									ast_waitstream(chan, AST_DIGIT_ANY);
-								if (res < 0)
+								if (res < 0) {
+									AST_LIST_LOCK(&confs);
+									cnf->refcount--;
+									if (!cnf->refcount){
+										conf_free(cnf);
+									}
+									AST_LIST_UNLOCK(&confs);
 									break;
+								}
 								pin[0] = res;
 								pin[1] = '\0';
 								res = -1;
@@ -2054,8 +2144,9 @@
 							allowretry = 0;
 							/* see if we need to get rid of the conference */
 							AST_LIST_LOCK(&confs);

[... 3709 lines stripped ...]


More information about the asterisk-commits mailing list