@ -149,6 +149,9 @@ struct mohclass {
int srcfd ;
int srcfd ;
/*! FD for timing source */
/*! FD for timing source */
int pseudofd ;
int pseudofd ;
/*! Number of users */
int inuse ;
unsigned int delete : 1 ;
AST_LIST_HEAD_NOLOCK ( , mohdata ) members ;
AST_LIST_HEAD_NOLOCK ( , mohdata ) members ;
AST_LIST_ENTRY ( mohclass ) list ;
AST_LIST_ENTRY ( mohclass ) list ;
} ;
} ;
@ -167,6 +170,8 @@ AST_RWLIST_HEAD_STATIC(mohclasses, mohclass);
# define MPG_123 " / usr / bin / mpg123"
# define MPG_123 " / usr / bin / mpg123"
# define MAX_MP3S 256
# define MAX_MP3S 256
static int ast_moh_destroy_one ( struct mohclass * moh ) ;
static int reload ( void ) ;
static void ast_moh_free_class ( struct mohclass * * mohclass )
static void ast_moh_free_class ( struct mohclass * * mohclass )
{
{
@ -209,6 +214,8 @@ static void moh_files_release(struct ast_channel *chan, void *data)
}
}
state - > save_pos = state - > pos ;
state - > save_pos = state - > pos ;
}
}
if ( state - > class - > delete & & ast_atomic_dec_and_test ( & state - > class - > inuse ) )
ast_moh_destroy_one ( state - > class ) ;
}
}
@ -713,6 +720,8 @@ static void moh_release(struct ast_channel *chan, void *data)
close ( moh - > pipe [ 0 ] ) ;
close ( moh - > pipe [ 0 ] ) ;
close ( moh - > pipe [ 1 ] ) ;
close ( moh - > pipe [ 1 ] ) ;
oldwfmt = moh - > origwfmt ;
oldwfmt = moh - > origwfmt ;
if ( moh - > parent - > delete & & ast_atomic_dec_and_test ( & moh - > parent - > inuse ) )
ast_moh_destroy_one ( moh - > parent ) ;
ast_free ( moh ) ;
ast_free ( moh ) ;
if ( chan ) {
if ( chan ) {
if ( oldwfmt & & ast_set_write_format ( chan , oldwfmt ) )
if ( oldwfmt & & ast_set_write_format ( chan , oldwfmt ) )
@ -871,8 +880,11 @@ static int moh_register(struct mohclass *moh, int reload)
# ifdef HAVE_ZAPTEL
# ifdef HAVE_ZAPTEL
int x ;
int x ;
# endif
# endif
struct mohclass * mohclass = NULL ;
AST_RWLIST_WRLOCK ( & mohclasses ) ;
AST_RWLIST_WRLOCK ( & mohclasses ) ;
if ( get_mohbyname ( moh - > name , 0 ) ) {
if ( ( mohclass = get_mohbyname ( moh - > name , 0 ) ) ) {
mohclass - > delete = 0 ;
if ( reload ) {
if ( reload ) {
ast_debug ( 1 , " Music on Hold class '%s' left alone from initial load. \n " , moh - > name ) ;
ast_debug ( 1 , " Music on Hold class '%s' left alone from initial load. \n " , moh - > name ) ;
} else {
} else {
@ -971,6 +983,8 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
mohclass = get_mohbyname ( interpclass , 1 ) ;
mohclass = get_mohbyname ( interpclass , 1 ) ;
if ( ! mohclass )
if ( ! mohclass )
mohclass = get_mohbyname ( " default " , 1 ) ;
mohclass = get_mohbyname ( " default " , 1 ) ;
if ( mohclass )
ast_atomic_fetchadd_int ( & mohclass - > inuse , + 1 ) ;
AST_RWLIST_UNLOCK ( & mohclasses ) ;
AST_RWLIST_UNLOCK ( & mohclasses ) ;
if ( ! mohclass )
if ( ! mohclass )
@ -1000,7 +1014,7 @@ static struct mohclass *moh_class_malloc(void)
{
{
struct mohclass * class ;
struct mohclass * class ;
if ( ( class = ast_calloc ( 1 , sizeof ( * class ) ) ) )
if ( ( class = ast_calloc ( 1 , sizeof ( * class ) ) ) )
class - > format = AST_FORMAT_SLINEAR ;
class - > format = AST_FORMAT_SLINEAR ;
return class ;
return class ;
@ -1020,6 +1034,14 @@ static int load_moh_classes(int reload)
if ( cfg = = NULL | | cfg = = CONFIG_STATUS_FILEUNCHANGED )
if ( cfg = = NULL | | cfg = = CONFIG_STATUS_FILEUNCHANGED )
return 0 ;
return 0 ;
if ( reload ) {
AST_RWLIST_WRLOCK ( & mohclasses ) ;
AST_RWLIST_TRAVERSE ( & mohclasses , class , list ) {
class - > delete = 1 ;
}
AST_RWLIST_UNLOCK ( & mohclasses ) ;
}
cat = ast_category_browse ( cfg , NULL ) ;
cat = ast_category_browse ( cfg , NULL ) ;
for ( ; cat ; cat = ast_category_browse ( cfg , cat ) ) {
for ( ; cat ; cat = ast_category_browse ( cfg , cat ) ) {
/* These names were deprecated in 1.4 and should not be used until after the next major release. */
/* These names were deprecated in 1.4 and should not be used until after the next major release. */
@ -1082,16 +1104,12 @@ static int load_moh_classes(int reload)
return numclasses ;
return numclasses ;
}
}
static void ast_moh_destroy ( void )
static int ast_moh_destroy_one ( struct mohclass * moh )
{
{
struct mohclass * moh ;
char buff [ 8192 ] ;
char buff [ 8192 ] ;
int bytes , tbytes = 0 , stime = 0 , pid = 0 ;
int bytes , tbytes = 0 , stime = 0 , pid = 0 ;
ast_verb ( 2 , " Destroying musiconhold processes \n " ) ;
if ( moh ) {
AST_RWLIST_WRLOCK ( & mohclasses ) ;
while ( ( moh = AST_RWLIST_REMOVE_HEAD ( & mohclasses , list ) ) ) {
if ( moh - > pid > 1 ) {
if ( moh - > pid > 1 ) {
ast_debug ( 1 , " killing %d! \n " , moh - > pid ) ;
ast_debug ( 1 , " killing %d! \n " , moh - > pid ) ;
stime = time ( NULL ) + 2 ;
stime = time ( NULL ) + 2 ;
@ -1112,33 +1130,27 @@ static void ast_moh_destroy(void)
}
}
ast_moh_free_class ( & moh ) ;
ast_moh_free_class ( & moh ) ;
}
}
AST_RWLIST_UNLOCK ( & mohclasses ) ;
return 0 ;
}
}
static void moh_on_off( int on )
static void ast_moh_destroy( void )
{
{
struct ast_channel * chan = NULL ;
struct mohclass * moh ;
while ( ( chan = ast_channel_walk_locked ( chan ) ) ! = NULL ) {
ast_verb ( 2 , " Destroying musiconhold processes \n " ) ;
if ( ast_test_flag ( chan , AST_FLAG_MOH ) ) {
if ( on )
AST_RWLIST_WRLOCK ( & mohclasses ) ;
local_ast_moh_start ( chan , NULL , NULL ) ;
while ( ( moh = AST_RWLIST_REMOVE_HEAD ( & mohclasses , list ) ) ) {
else
ast_moh_destroy_one ( moh ) ;
ast_deactivate_generator ( chan ) ;
}
ast_channel_unlock ( chan ) ;
}
}
AST_RWLIST_UNLOCK ( & mohclasses ) ;
}
}
static int moh_cli ( int fd , int argc , char * argv [ ] )
static int moh_cli ( int fd , int argc , char * argv [ ] )
{
{
int x ;
reload ( ) ;
moh_on_off ( 0 ) ;
ast_moh_destroy ( ) ;
x = load_moh_classes ( 1 ) ;
moh_on_off ( 1 ) ;
ast_cli ( fd , " \n %d class%s reloaded. \n " , x , x = = 1 ? " " : " es " ) ;
return 0 ;
return 0 ;
}
}
@ -1170,6 +1182,7 @@ static int moh_classes_show(int fd, int argc, char *argv[])
ast_cli ( fd , " Class: %s \n " , class - > name ) ;
ast_cli ( fd , " Class: %s \n " , class - > name ) ;
ast_cli ( fd , " \t Mode: %s \n " , S_OR ( class - > mode , " <none> " ) ) ;
ast_cli ( fd , " \t Mode: %s \n " , S_OR ( class - > mode , " <none> " ) ) ;
ast_cli ( fd , " \t Directory: %s \n " , S_OR ( class - > dir , " <none> " ) ) ;
ast_cli ( fd , " \t Directory: %s \n " , S_OR ( class - > dir , " <none> " ) ) ;
ast_cli ( fd , " \t Use Count: %d \n " , class - > inuse ) ;
if ( class - > digit )
if ( class - > digit )
ast_cli ( fd , " \t Digit: %c \n " , class - > digit ) ;
ast_cli ( fd , " \t Digit: %c \n " , class - > digit ) ;
if ( ast_test_flag ( class , MOH_CUSTOM ) )
if ( ast_test_flag ( class , MOH_CUSTOM ) )
@ -1204,10 +1217,15 @@ static int init_classes(int reload)
return 0 ; /* Return if nothing is found */
return 0 ; /* Return if nothing is found */
AST_RWLIST_WRLOCK ( & mohclasses ) ;
AST_RWLIST_WRLOCK ( & mohclasses ) ;
AST_RWLIST_TRAVERSE ( & mohclasses , moh , list ) {
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & mohclasses , moh , list ) {
if ( moh - > total_files )
if ( reload & & moh - > delete ) {
AST_RWLIST_REMOVE_CURRENT ( & mohclasses , list ) ;
if ( ! moh - > inuse )
ast_moh_destroy_one ( moh ) ;
} else if ( moh - > total_files )
moh_scan_files ( moh ) ;
moh_scan_files ( moh ) ;
}
}
AST_RWLIST_TRAVERSE_SAFE_END
AST_RWLIST_UNLOCK ( & mohclasses ) ;
AST_RWLIST_UNLOCK ( & mohclasses ) ;
return 1 ;
return 1 ;