Merge "res_musiconhold: Add new 'playlist' mode" into 16
This commit is contained in:
commit
1903dcb43d
|
@ -95,6 +95,7 @@
|
|||
;queue_rules => odbc,asterisk
|
||||
;acls => odbc,asterisk
|
||||
;musiconhold => mysql,general
|
||||
;musiconhold_entry => mysql,general
|
||||
;queue_log => mysql,general
|
||||
;
|
||||
;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
; valid mode options:
|
||||
; files -- read files from a directory in any Asterisk supported
|
||||
; media format
|
||||
; playlist -- provide a fixed list of filenames or URLs to play
|
||||
; quietmp3 -- default
|
||||
; mp3 -- loud
|
||||
; mp3nb -- unbuffered
|
||||
|
@ -44,6 +45,22 @@
|
|||
; this, res_musiconhold will skip the files it is not able to
|
||||
; understand when it loads.
|
||||
;
|
||||
; =========
|
||||
; Playlist (native) music on hold
|
||||
; =========
|
||||
;
|
||||
; This mode is similar to 'files' mode in that it plays through a list
|
||||
; of files, but instead of scanning a directory the files are
|
||||
; explicitly configured using one or more 'entry' options.
|
||||
;
|
||||
; Each entry must be one of:
|
||||
;
|
||||
; * An absolute path to the file to be played, without an extension.
|
||||
; * A URL
|
||||
;
|
||||
; The entries are played in the order in which they appear in the
|
||||
; configuration. The 'sort' option is not used for this mode.
|
||||
;
|
||||
|
||||
[default]
|
||||
mode=files
|
||||
|
@ -71,6 +88,12 @@ directory=moh
|
|||
;directory=moh
|
||||
;sort=alpha ; Sort the files in alphabetical order.
|
||||
|
||||
;[sales-queue-hold]
|
||||
;mode=playlist
|
||||
;entry=/var/lib/asterisk/sounds/en/yourcallisimportant
|
||||
;entry=http://example.local/sales-queue-hold-music.ulaw
|
||||
;entry=/var/lib/asterisk/moh/macroform-robot_dity
|
||||
|
||||
; =========
|
||||
; Other (non-native) playback methods
|
||||
; =========
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
"""add playlist to moh
|
||||
|
||||
Revision ID: fbb7766f17bc
|
||||
Revises: 3a094a18e75b
|
||||
Create Date: 2019-09-18 10:24:18.731798
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'fbb7766f17bc'
|
||||
down_revision = '3a094a18e75b'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def enum_update(table_name, column_name, enum_name, enum_values):
|
||||
if op.get_context().bind.dialect.name != 'postgresql':
|
||||
if op.get_context().bind.dialect.name == 'mssql':
|
||||
op.drop_constraint('ck_musiconhold_mode_moh_mode_values', 'musiconhold')
|
||||
op.alter_column(table_name, column_name,
|
||||
type_=sa.Enum(*enum_values, name=enum_name))
|
||||
return
|
||||
|
||||
# Postgres requires a few more steps
|
||||
tmp = enum_name + '_tmp'
|
||||
|
||||
op.execute('ALTER TYPE ' + enum_name + ' RENAME TO ' + tmp)
|
||||
|
||||
updated = sa.Enum(*enum_values, name=enum_name)
|
||||
updated.create(op.get_bind(), checkfirst=False)
|
||||
|
||||
op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name +
|
||||
' TYPE ' + enum_name + ' USING mode::text::' + enum_name)
|
||||
|
||||
op.execute('DROP TYPE ' + tmp)
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'musiconhold_entry',
|
||||
sa.Column('name', sa.String(80), primary_key=True, nullable=False),
|
||||
sa.Column('position', sa.Integer, primary_key=True, nullable=False),
|
||||
sa.Column('entry', sa.String(1024), nullable=False)
|
||||
)
|
||||
op.create_foreign_key('fk_musiconhold_entry_name_musiconhold', 'musiconhold_entry', 'musiconhold', ['name'], ['name'])
|
||||
enum_update('musiconhold', 'mode', 'moh_mode_values',
|
||||
['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3', 'playlist'])
|
||||
|
||||
|
||||
def downgrade():
|
||||
enum_update('musiconhold', 'mode', 'moh_mode_values',
|
||||
['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3'])
|
||||
op.drop_table('musiconhold_entry')
|
|
@ -0,0 +1,5 @@
|
|||
Subject: res_musiconhold
|
||||
|
||||
A new mode - playlist - has been added to res_musiconhold. This mode allows the
|
||||
user to specify the files (or URLs) to play explicitly by putting them directly
|
||||
in musiconhold.conf.
|
|
@ -1081,6 +1081,20 @@ static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclas
|
|||
ast_copy_string(mohclass->name, var->value, sizeof(mohclass->name));
|
||||
} else if (!strcasecmp(var->name, "mode")) {
|
||||
ast_copy_string(mohclass->mode, var->value, sizeof(mohclass->mode));
|
||||
} else if (!strcasecmp(var->name, "entry")) {
|
||||
if (ast_begins_with(var->value, "/") || ast_begins_with(var->value, "http://") || ast_begins_with(var->value, "https://")) {
|
||||
char *dup = ast_strdup(var->value);
|
||||
if (!dup) {
|
||||
continue;
|
||||
}
|
||||
if (ast_begins_with(dup, "/") && strrchr(dup, '.')) {
|
||||
ast_log(LOG_WARNING, "The playlist entry '%s' may include an extension, which could prevent it from playing.\n",
|
||||
dup);
|
||||
}
|
||||
AST_VECTOR_APPEND(&mohclass->files, dup);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Playlist entries must be a URL or absolute path, '%s' provided.\n", var->value);
|
||||
}
|
||||
} else if (!strcasecmp(var->name, "directory")) {
|
||||
ast_copy_string(mohclass->dir, var->value, sizeof(mohclass->dir));
|
||||
} else if (!strcasecmp(var->name, "application")) {
|
||||
|
@ -1130,6 +1144,8 @@ static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclas
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
AST_VECTOR_COMPACT(&mohclass->files);
|
||||
}
|
||||
|
||||
static int moh_scan_files(struct mohclass *class) {
|
||||
|
@ -1333,6 +1349,13 @@ static int _moh_register(struct mohclass *moh, int reload, int unref, const char
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(moh->mode, "playlist")) {
|
||||
if (!AST_VECTOR_SIZE(&moh->files)) {
|
||||
if (unref) {
|
||||
moh = mohclass_unref(moh, "unreffing potential new moh class (no playlist entries)");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(moh->mode, "mp3") || !strcasecmp(moh->mode, "mp3nb") ||
|
||||
!strcasecmp(moh->mode, "quietmp3") || !strcasecmp(moh->mode, "quietmp3nb") ||
|
||||
!strcasecmp(moh->mode, "httpmp3") || !strcasecmp(moh->mode, "custom")) {
|
||||
|
@ -1485,6 +1508,32 @@ static struct mohclass *_moh_class_malloc(const char *file, int line, const char
|
|||
static struct ast_variable *load_realtime_musiconhold(const char *name)
|
||||
{
|
||||
struct ast_variable *var = ast_load_realtime("musiconhold", "name", name, SENTINEL);
|
||||
|
||||
if (var) {
|
||||
const char *mode = ast_variable_find_in_list(var, "mode");
|
||||
if (ast_strings_equal(mode, "playlist")) {
|
||||
struct ast_variable *entries = ast_load_realtime("musiconhold_entry", "name", name, SENTINEL);
|
||||
struct ast_variable *cur = entries;
|
||||
size_t entry_count = 0;
|
||||
for (; cur; cur = cur->next) {
|
||||
if (!strcmp(cur->name, "entry")) {
|
||||
struct ast_variable *dup = ast_variable_new(cur->name, cur->value, "");
|
||||
if (dup) {
|
||||
entry_count++;
|
||||
ast_variable_list_append(&var, dup);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_variables_destroy(entries);
|
||||
|
||||
if (entry_count == 0) {
|
||||
/* Behave as though this class doesn't exist */
|
||||
ast_variables_destroy(var);
|
||||
var = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!var) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Music on Hold class '%s' not found in memory/database. "
|
||||
|
@ -1551,7 +1600,7 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
|
|||
ast_variables_destroy(var);
|
||||
|
||||
if (ast_strlen_zero(mohclass->dir)) {
|
||||
if (!strcasecmp(mohclass->mode, "custom")) {
|
||||
if (!strcasecmp(mohclass->mode, "custom") || !strcasecmp(mohclass->mode, "playlist")) {
|
||||
strcpy(mohclass->dir, "nodir");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
|
||||
|
@ -1605,6 +1654,11 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con
|
|||
}
|
||||
ast_set_flag(mohclass, MOH_RANDOMIZE);
|
||||
}
|
||||
} else if (!strcasecmp(mohclass->mode, "playlist")) {
|
||||
if (!AST_VECTOR_SIZE(&mohclass->files)) {
|
||||
mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (no playlist entries)");
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
|
||||
|
||||
if (!strcasecmp(mohclass->mode, "custom"))
|
||||
|
@ -1846,7 +1900,7 @@ static int load_moh_classes(int reload)
|
|||
ast_copy_string(class->name, cat, sizeof(class->name));
|
||||
|
||||
if (ast_strlen_zero(class->dir)) {
|
||||
if (!strcasecmp(class->mode, "custom")) {
|
||||
if (!strcasecmp(class->mode, "custom") || !strcasecmp(class->mode, "playlist")) {
|
||||
strcpy(class->dir, "nodir");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", class->name);
|
||||
|
|
Loading…
Reference in New Issue