Ring Group Edit: Add text to speech option in greet and wait announcement (#8001)

* Ring Group Edit: Add text to speech option in greet and wait announcement

* Update ring_group_edit.php
This commit is contained in:
Alex
2026-05-28 09:17:29 -07:00
committed by GitHub
parent 2186fb939d
commit 232fe6ccff
2 changed files with 507 additions and 56 deletions
+215 -54
View File
@@ -1699,6 +1699,167 @@ $text['label-forwarding']['zh-cn'] = "转发";
$text['label-forwarding']['ja-jp'] = "転送";
$text['label-forwarding']['ko-kr'] = "전송";
$text['label-new']['en-us'] = "New";
$text['label-new']['en-gb'] = "New";
$text['label-new']['ar-eg'] = "جديدة";
$text['label-new']['de-at'] = "Neu";
$text['label-new']['de-ch'] = "Neu";
$text['label-new']['de-de'] = "Neu";
$text['label-new']['el-gr'] = "Νέος";
$text['label-new']['es-cl'] = "Nueva";
$text['label-new']['es-mx'] = "Nueva";
$text['label-new']['fr-ca'] = "Nouveau";
$text['label-new']['fr-fr'] = "Nouveau";
$text['label-new']['he-il'] = "חדש";
$text['label-new']['it-it'] = "Nuovo";
$text['label-new']['ka-ge'] = "ახალი";
$text['label-new']['nl-nl'] = "Nieuws";
$text['label-new']['pl-pl'] = "Nowy";
$text['label-new']['pt-br'] = "Nova";
$text['label-new']['pt-pt'] = "Nova";
$text['label-new']['ro-ro'] = "Nou";
$text['label-new']['ru-ru'] = "Новый";
$text['label-new']['sv-se'] = "Nytt";
$text['label-new']['uk-ua'] = "Нові";
$text['label-new']['tr-tr'] = "Yeni";
$text['label-new']['zh-cn'] = "新的";
$text['label-new']['ja-jp'] = "新しい";
$text['label-new']['ko-kr'] = "새로운";
$text['label-text_to_speech']['en-us'] = "Text to Speech";
$text['label-text_to_speech']['en-gb'] = "Text to Speech";
$text['label-text_to_speech']['ar-eg'] = "تحويل النص إلى كلام";
$text['label-text_to_speech']['de-at'] = "Text-to-Speech";
$text['label-text_to_speech']['de-ch'] = "Text-to-Speech";
$text['label-text_to_speech']['de-de'] = "Text-to-Speech";
$text['label-text_to_speech']['el-gr'] = "Κείμενο σε Ομιλία";
$text['label-text_to_speech']['es-cl'] = "Texto a voz";
$text['label-text_to_speech']['es-mx'] = "Texto a voz";
$text['label-text_to_speech']['fr-ca'] = "Synthèse vocale";
$text['label-text_to_speech']['fr-fr'] = "Synthèse vocale";
$text['label-text_to_speech']['he-il'] = "טקסט לדיבור";
$text['label-text_to_speech']['it-it'] = "Testo a voce";
$text['label-text_to_speech']['ka-ge'] = "ტექსტის ხმოვანი";
$text['label-text_to_speech']['nl-nl'] = "Tekst naar spraak";
$text['label-text_to_speech']['pl-pl'] = "Tekst na mowę";
$text['label-text_to_speech']['pt-br'] = "Texto para fala";
$text['label-text_to_speech']['pt-pt'] = "Texto para fala";
$text['label-text_to_speech']['ro-ro'] = "Text la voce";
$text['label-text_to_speech']['ru-ru'] = "Синтез речи";
$text['label-text_to_speech']['sv-se'] = "Text till tal";
$text['label-text_to_speech']['uk-ua'] = "Синтез мови";
$text['label-text_to_speech']['tr-tr'] = "Metinden Konuşmaya";
$text['label-text_to_speech']['zh-cn'] = "文字转语音";
$text['label-text_to_speech']['ja-jp'] = "テキスト読み上げ";
$text['label-text_to_speech']['ko-kr'] = "텍스트 음성 변환";
$text['label-message']['en-us'] = "Message";
$text['label-message']['en-gb'] = "Message";
$text['label-message']['ar-eg'] = "رسالة";
$text['label-message']['de-at'] = "Nachricht";
$text['label-message']['de-ch'] = "Nachricht";
$text['label-message']['de-de'] = "Nachricht";
$text['label-message']['el-gr'] = "Μήνυμα";
$text['label-message']['es-cl'] = "Mensaje";
$text['label-message']['es-mx'] = "Mensaje";
$text['label-message']['fr-ca'] = "Message";
$text['label-message']['fr-fr'] = "Message";
$text['label-message']['he-il'] = "הודעה";
$text['label-message']['it-it'] = "Messaggio";
$text['label-message']['ka-ge'] = "შეტყობინება";
$text['label-message']['nl-nl'] = "Boodschap";
$text['label-message']['pl-pl'] = "Wiadomość";
$text['label-message']['pt-br'] = "Mensagem";
$text['label-message']['pt-pt'] = "Mensagem";
$text['label-message']['ro-ro'] = "Mesaj";
$text['label-message']['ru-ru'] = "Сообщение";
$text['label-message']['sv-se'] = "Meddelande";
$text['label-message']['uk-ua'] = "Повідомлення";
$text['label-message']['zh-cn'] = "信息";
$text['label-message']['ja-jp'] = "メッセージ";
$text['label-message']['ko-kr'] = "메시지";
$text['label-speed']['en-us'] = "Speed";
$text['label-speed']['en-gb'] = "Speed";
$text['label-speed']['ar-eg'] = "سرعة";
$text['label-speed']['de-at'] = "Geschwindigkeit";
$text['label-speed']['de-ch'] = "Geschwindigkeit";
$text['label-speed']['de-de'] = "Geschwindigkeit";
$text['label-speed']['el-gr'] = "Ταχύτητα";
$text['label-speed']['es-cl'] = "Velocidad";
$text['label-speed']['es-mx'] = "Velocidad";
$text['label-speed']['fr-ca'] = "Vitesse";
$text['label-speed']['fr-fr'] = "Vitesse";
$text['label-speed']['he-il'] = "מהירות";
$text['label-speed']['it-it'] = "Velocità";
$text['label-speed']['ka-ge'] = "სიჩქარე";
$text['label-speed']['nl-nl'] = "Snelheid";
$text['label-speed']['pl-pl'] = "Prędkość";
$text['label-speed']['pt-br'] = "Velocidade";
$text['label-speed']['pt-pt'] = "Velocidade";
$text['label-speed']['ro-ro'] = "Viteză";
$text['label-speed']['ru-ru'] = "Скорость";
$text['label-speed']['sv-se'] = "Hastighet";
$text['label-speed']['uk-ua'] = "Швидкість";
$text['label-speed']['tr-tr'] = "Hız";
$text['label-speed']['zh-cn'] = "速度";
$text['label-speed']['ja-jp'] = "速度";
$text['label-speed']['ko-kr'] = "속도";
$text['label-voice']['en-us'] = "Voice";
$text['label-voice']['en-gb'] = "Voice";
$text['label-voice']['ar-eg'] = "صوت";
$text['label-voice']['de-at'] = "Stimme";
$text['label-voice']['de-ch'] = "Stimme";
$text['label-voice']['de-de'] = "Stimme";
$text['label-voice']['el-gr'] = "Φωνή";
$text['label-voice']['es-cl'] = "Voz";
$text['label-voice']['es-mx'] = "Voz";
$text['label-voice']['fr-ca'] = "Voix";
$text['label-voice']['fr-fr'] = "Voix";
$text['label-voice']['he-il'] = "קוֹל";
$text['label-voice']['it-it'] = "Voce";
$text['label-voice']['ka-ge'] = "ხმა";
$text['label-voice']['nl-nl'] = "Stem";
$text['label-voice']['pl-pl'] = "Głos";
$text['label-voice']['pt-br'] = "Voz";
$text['label-voice']['pt-pt'] = "Voz";
$text['label-voice']['ro-ro'] = "Voce";
$text['label-voice']['ru-ru'] = "Голос";
$text['label-voice']['sv-se'] = "Röst";
$text['label-voice']['uk-ua'] = "Голос";
$text['label-voice']['tr-tr'] = "Ses";
$text['label-voice']['zh-cn'] = "嗓音";
$text['label-voice']['ja-jp'] = "";
$text['label-voice']['ko-kr'] = "목소리";
$text['label-recording_name']['en-us'] = "Recording Name";
$text['label-recording_name']['en-gb'] = "Recording Name";
$text['label-recording_name']['ar-eg'] = "الاسم المسجل";
$text['label-recording_name']['de-at'] = "Name der Aufnahme";
$text['label-recording_name']['de-ch'] = "Name der Aufnahme";
$text['label-recording_name']['de-de'] = "Name der Aufnahme";
$text['label-recording_name']['el-gr'] = "Όνομα εγγραφής";
$text['label-recording_name']['es-cl'] = "Nombre de la grabación";
$text['label-recording_name']['es-mx'] = "Nombre de la grabación";
$text['label-recording_name']['fr-ca'] = "Nom de l'enregistrement";
$text['label-recording_name']['fr-fr'] = "Nom de l'enregistrement";
$text['label-recording_name']['he-il'] = "שם הקובץ מדיה";
$text['label-recording_name']['it-it'] = "Nome Registrazione";
$text['label-recording_name']['ka-ge'] = "ჩანაწერის სახელი";
$text['label-recording_name']['nl-nl'] = "Opnamenaam";
$text['label-recording_name']['pl-pl'] = "Nazwa nagrania";
$text['label-recording_name']['pt-br'] = "Nome da gravação";
$text['label-recording_name']['pt-pt'] = "Nome da gravação";
$text['label-recording_name']['ro-ro'] = "Nume înregistrare";
$text['label-recording_name']['ru-ru'] = "Название записи";
$text['label-recording_name']['sv-se'] = "Namn på inspelning";
$text['label-recording_name']['uk-ua'] = "Назва запису";
$text['label-recording_name']['tr-tr'] = "Kayıt Adı";
$text['label-recording_name']['zh-cn'] = "录音名称";
$text['label-recording_name']['ja-jp'] = "録音名";
$text['label-recording_name']['ko-kr'] = "녹음 이름";
$text['header-ring-group-forward']['en-us'] = "Ring Group Forward";
$text['header-ring-group-forward']['en-gb'] = "Ring Group Forward";
$text['header-ring-group-forward']['ar-eg'] = "فريق الرنين إلى الأمام";
@@ -1858,62 +2019,62 @@ $text['description-strategy']['sv-se'] = "Välj strategi för ringflöde.";
$text['description-strategy']['uk-ua'] = "Виберіть стратегію кільця.";
$text['description-strategy']['tr-tr'] = "Zil stratejisini seçin.";
$text['description-strategy']['zh-cn'] = "选择响铃策略。";
$text['description-strategy']['ja-jp'] = "リング戦略を選択します。";
$text['description-strategy']['ko-kr'] = "링 전략을 선택합니다.";
$text['description-strategy']['ja-jp'] = "リング戦略を選択します。";
$text['description-strategy']['ko-kr'] = "링 전략을 선택합니다.";
$text['description-wait_announcement']['en-us'] = "Select an audio file to play as an announcement while waiting.";
$text['description-wait_announcement']['en-gb'] = "Select an audio file to play as an announcement while waiting.";
$text['description-wait_announcement']['ar-eg'] = "حدد ملفًا صوتيًا ليتم تشغيله كإعلان أثناء الانتظار.";
$text['description-wait_announcement']['de-at'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['de-ch'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['de-de'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['el-gr'] = "Επιλέξτε ένα αρχείο ήχου για αναπαραγωγή ως ανακοίνωση κατά την αναμονή.";
$text['description-wait_announcement']['es-cl'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera.";
$text['description-wait_announcement']['es-mx'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera.";
$text['description-wait_announcement']['fr-ca'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente.";
$text['description-wait_announcement']['fr-fr'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente.";
$text['description-wait_announcement']['he-il'] = "בחר קובץ שמע שיושמע כהודעה בזמן ההמתנה.";
$text['description-wait_announcement']['it-it'] = "Seleziona un file audio da riprodurre come annuncio durante l'attesa.";
$text['description-wait_announcement']['ka-ge'] = "აირჩიეთ აუდიო ფაილი, რომელიც ლოდინის დროს გამოცხადებად დაკვრდება.";
$text['description-wait_announcement']['nl-nl'] = "Selecteer een audiobestand dat tijdens het wachten als aankondiging wordt afgespeeld.";
$text['description-wait_announcement']['pl-pl'] = "Wybierz plik audio, który ma być odtwarzany jako komunikat podczas oczekiwania.";
$text['description-wait_announcement']['pt-br'] = "Selecione um arquivo de áudio para ser reproduzido como anúncio durante a espera.";
$text['description-wait_announcement']['pt-pt'] = "Selecione um ficheiro de áudio para ser reproduzido como anúncio durante a espera.";
$text['description-wait_announcement']['ro-ro'] = "Selectați un fișier audio care să fie redat ca anunț în timpul așteptării.";
$text['description-wait_announcement']['ru-ru'] = "Выберите аудиофайл, который будет воспроизводиться как объявление во время ожидания.";
$text['description-wait_announcement']['sv-se'] = "Välj en ljudfil som ska spelas upp som meddelande under väntetiden.";
$text['description-wait_announcement']['uk-ua'] = "Виберіть аудіофайл, який відтворюватиметься як оголошення під час очікування.";
$text['description-wait_announcement']['tr-tr'] = "Bekleme sırasında anons olarak çalınacak bir ses dosyası seçin.";
$text['description-wait_announcement']['zh-cn'] = "选择一个音频文件,在等待时作为公告播放。";
$text['description-wait_announcement']['ja-jp'] = "待機中にアナウンスとして再生する音声ファイルを選択します。";
$text['description-wait_announcement']['ko-kr'] = "대기 중 안내 방송으로 재생할 오디오 파일을 선택하세요.";
$text['description-wait_announcement']['en-us'] = "Select an audio file to play as an announcement while waiting.";
$text['description-wait_announcement']['en-gb'] = "Select an audio file to play as an announcement while waiting.";
$text['description-wait_announcement']['ar-eg'] = "حدد ملفًا صوتيًا ليتم تشغيله كإعلان أثناء الانتظار.";
$text['description-wait_announcement']['de-at'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['de-ch'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['de-de'] = "Wählen Sie eine Audiodatei aus, die während der Wartezeit als Ansage abgespielt wird.";
$text['description-wait_announcement']['el-gr'] = "Επιλέξτε ένα αρχείο ήχου για αναπαραγωγή ως ανακοίνωση κατά την αναμονή.";
$text['description-wait_announcement']['es-cl'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera.";
$text['description-wait_announcement']['es-mx'] = "Seleccione un archivo de audio para reproducirlo como anuncio mientras espera.";
$text['description-wait_announcement']['fr-ca'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente.";
$text['description-wait_announcement']['fr-fr'] = "Sélectionnez un fichier audio à lire comme annonce pendant l'attente.";
$text['description-wait_announcement']['he-il'] = "בחר קובץ שמע שיושמע כהודעה בזמן ההמתנה.";
$text['description-wait_announcement']['it-it'] = "Seleziona un file audio da riprodurre come annuncio durante l'attesa.";
$text['description-wait_announcement']['ka-ge'] = "აირჩიეთ აუდიო ფაილი, რომელიც ლოდინის დროს გამოცხადებად დაკვრდება.";
$text['description-wait_announcement']['nl-nl'] = "Selecteer een audiobestand dat tijdens het wachten als aankondiging wordt afgespeeld.";
$text['description-wait_announcement']['pl-pl'] = "Wybierz plik audio, który ma być odtwarzany jako komunikat podczas oczekiwania.";
$text['description-wait_announcement']['pt-br'] = "Selecione um arquivo de áudio para ser reproduzido como anúncio durante a espera.";
$text['description-wait_announcement']['pt-pt'] = "Selecione um ficheiro de áudio para ser reproduzido como anúncio durante a espera.";
$text['description-wait_announcement']['ro-ro'] = "Selectați un fișier audio care să fie redat ca anunț în timpul așteptării.";
$text['description-wait_announcement']['ru-ru'] = "Выберите аудиофайл, который будет воспроизводиться как объявление во время ожидания.";
$text['description-wait_announcement']['sv-se'] = "Välj en ljudfil som ska spelas upp som meddelande under väntetiden.";
$text['description-wait_announcement']['uk-ua'] = "Виберіть аудіофайл, який відтворюватиметься як оголошення під час очікування.";
$text['description-wait_announcement']['tr-tr'] = "Bekleme sırasında anons olarak çalınacak bir ses dosyası seçin.";
$text['description-wait_announcement']['zh-cn'] = "选择一个音频文件,在等待时作为公告播放。";
$text['description-wait_announcement']['ja-jp'] = "待機中にアナウンスとして再生する音声ファイルを選択します。";
$text['description-wait_announcement']['ko-kr'] = "대기 중 안내 방송으로 재생할 오디오 파일을 선택하세요.";
$text['description-wait_interval']['en-us'] = "Interval in seconds between announcement plays. If blank, 30 will be used.";
$text['description-wait_interval']['en-gb'] = "Interval in seconds between announcement plays. If blank, 30 will be used.";
$text['description-wait_interval']['ar-eg'] = "الفاصل الزمني بالثواني بين تشغيل الإعلانات.";
$text['description-wait_interval']['de-at'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['de-ch'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['de-de'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['el-gr'] = "Διάστημα σε δευτερόλεπτα μεταξύ των αναπαραγωγών της ανακοίνωσης.";
$text['description-wait_interval']['es-cl'] = "Intervalo en segundos entre cada reproducción del anuncio.";
$text['description-wait_interval']['es-mx'] = "Intervalo en segundos entre cada reproducción del anuncio.";
$text['description-wait_interval']['fr-ca'] = "Intervalle en secondes entre les lectures de l'annonce.";
$text['description-wait_interval']['fr-fr'] = "Intervalle en secondes entre les lectures de l'annonce.";
$text['description-wait_interval']['he-il'] = "המרווח בשניות בין השמעות ההודעה.";
$text['description-wait_interval']['it-it'] = "Intervallo in secondi tra le riproduzioni dell'annuncio.";
$text['description-wait_interval']['ka-ge'] = "ინტერვალი წამებში განცხადებების დაკვრებს შორის.";
$text['description-wait_interval']['nl-nl'] = "Interval in seconden tussen het afspelen van de aankondiging.";
$text['description-wait_interval']['pl-pl'] = "Odstęp w sekundach między odtworzeniami komunikatu.";
$text['description-wait_interval']['pt-br'] = "Intervalo em segundos entre as reproduções do anúncio.";
$text['description-wait_interval']['pt-pt'] = "Intervalo em segundos entre as reproduções do anúncio.";
$text['description-wait_interval']['ro-ro'] = "Intervalul în secunde dintre redările anunțului.";
$text['description-wait_interval']['ru-ru'] = "Интервал в секундах между воспроизведениями объявления.";
$text['description-wait_interval']['sv-se'] = "Intervall i sekunder mellan uppspelningarna av meddelandet.";
$text['description-wait_interval']['uk-ua'] = "Інтервал у секундах між відтвореннями оголошення.";
$text['description-wait_interval']['tr-tr'] = "Anons çalmaları arasındaki saniye cinsinden aralık.";
$text['description-wait_interval']['zh-cn'] = "公告播放之间的间隔秒数。";
$text['description-wait_interval']['ja-jp'] = "アナウンス再生間の秒数です。";
$text['description-wait_interval']['ko-kr'] = "안내 방송 재생 사이의 간격(초)입니다.";
$text['description-wait_interval']['en-us'] = "Interval in seconds between announcement plays. If blank, 30 will be used.";
$text['description-wait_interval']['en-gb'] = "Interval in seconds between announcement plays. If blank, 30 will be used.";
$text['description-wait_interval']['ar-eg'] = "الفاصل الزمني بالثواني بين تشغيل الإعلانات.";
$text['description-wait_interval']['de-at'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['de-ch'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['de-de'] = "Intervall in Sekunden zwischen den Ansagen.";
$text['description-wait_interval']['el-gr'] = "Διάστημα σε δευτερόλεπτα μεταξύ των αναπαραγωγών της ανακοίνωσης.";
$text['description-wait_interval']['es-cl'] = "Intervalo en segundos entre cada reproducción del anuncio.";
$text['description-wait_interval']['es-mx'] = "Intervalo en segundos entre cada reproducción del anuncio.";
$text['description-wait_interval']['fr-ca'] = "Intervalle en secondes entre les lectures de l'annonce.";
$text['description-wait_interval']['fr-fr'] = "Intervalle en secondes entre les lectures de l'annonce.";
$text['description-wait_interval']['he-il'] = "המרווח בשניות בין השמעות ההודעה.";
$text['description-wait_interval']['it-it'] = "Intervallo in secondi tra le riproduzioni dell'annuncio.";
$text['description-wait_interval']['ka-ge'] = "ინტერვალი წამებში განცხადებების დაკვრებს შორის.";
$text['description-wait_interval']['nl-nl'] = "Interval in seconden tussen het afspelen van de aankondiging.";
$text['description-wait_interval']['pl-pl'] = "Odstęp w sekundach między odtworzeniami komunikatu.";
$text['description-wait_interval']['pt-br'] = "Intervalo em segundos entre as reproduções do anúncio.";
$text['description-wait_interval']['pt-pt'] = "Intervalo em segundos entre as reproduções do anúncio.";
$text['description-wait_interval']['ro-ro'] = "Intervalul în secunde dintre redările anunțului.";
$text['description-wait_interval']['ru-ru'] = "Интервал в секундах между воспроизведениями объявления.";
$text['description-wait_interval']['sv-se'] = "Intervall i sekunder mellan uppspelningarna av meddelandet.";
$text['description-wait_interval']['uk-ua'] = "Інтервал у секундах між відтвореннями оголошення.";
$text['description-wait_interval']['tr-tr'] = "Anons çalmaları arasındaki saniye cinsinden aralık.";
$text['description-wait_interval']['zh-cn'] = "公告播放之间的间隔秒数。";
$text['description-wait_interval']['ja-jp'] = "アナウンス再生間の秒数です。";
$text['description-wait_interval']['ko-kr'] = "안내 방송 재생 사이의 간격(초)입니다.";
$text['description-skip_active']['en-us'] = "Skip destinations with active calls.";
$text['description-skip_active']['en-gb'] = "Skip destinations with active calls.";
+292 -2
View File
@@ -68,6 +68,36 @@
$ring_group_follow_me_enabled = $settings->get('ring_group', 'follow_me_enabled', false);
$destination_delay_max = $settings->get('ring_group', 'destination_delay_max', '');
$destination_timeout_max = $settings->get('ring_group', 'destination_timeout_max', '');
$recording_name = '';
$recording_message = '';
$recording_description = '';
$recording_speed = '1.0';
$recording_uuid = '';
$speed_enabled = false;
$speed_options = [];
$translate_enabled = false;
$language_enabled = false;
//set speech enabled and engine variables
$speech_enabled = class_exists('speech') && $settings->get('speech', 'enabled', false);
$speech_engine = $settings->get('speech', 'engine', '');
//add the speech object and get the voices and languages arrays
if ($speech_enabled && !empty($speech_engine)) {
$speech = new speech($settings);
$voices = $speech->get_voices();
$recording_extension = $speech->get_format();
$speed_enabled = $speech->is_speed_enabled();
$speed_options = $speed_enabled ? $speech->get_speed_options() : [];
// Determine the aray type single, or multi
$voices_array_type = array_type($voices);
// Sort the array by language code keys alphabetically
if ($voices_array_type == 'multi') {
ksort($voices);
}
}
// Set variables from http GET parameters
$page = is_numeric($_GET['page'] ?? '') ? $_GET['page'] : 0;
@@ -529,6 +559,75 @@
$array["dialplans"][0]["dialplan_description"] = $ring_group_description;
$array["dialplans"][0]["app_uuid"] = "1d61fb65-1eec-bc73-a6ee-a6203b4fe6f2";
//build the recording array
$recording_types = ['greeting', 'wait_announcement'];
foreach ($recording_types as $x => $type) {
$recording_name = $_POST[$type]['recording_name'] ?? '';
$recording_voice = $_POST[$type]['recording_voice'] ?? '';
$recording_speed = $_POST[$type]['recording_speed'] ?? '1.0';
$recording_message = $_POST[$type]['recording_message'] ?? '';
$recording_desc = $_POST[$type]['recording_description'] ?? '';
if (permission_exists('recording_edit') && !empty($recording_message)) {
$recording_uuid = uuid();
if (empty($recording_name)) {
$recording_name = 'recording'.$ring_group_extension.($type == $recording_types[1] ? '-'.$type : null).'-'.str_pad(random_int(0, 9999), 4, '0', STR_PAD_LEFT);
}
//set the recording format for approved types
if (!in_array($recording_extension, ['mp3', 'wav'], true)) {
//default to wav
$recording_extension = 'wav';
}
//build the setting object and get the recording path
$recording_path = $settings->get('switch', 'recordings').'/'.$domain_name;
//create the file name
$recording_filename = empty($_POST[$type]['recording_filename'] ?? '') ? preg_replace('#[^a-zA-Z0-9_\-]#', '_', $recording_name) : $_POST[$type]['recording_filename'];
if (!str_ends_with($recording_filename, ".$recording_extension")) {
$recording_filename .= ".$recording_extension";
}
//text to audio - make a new audio file from the message
$speech->audio_path = $recording_path;
$speech->audio_filename = $recording_filename;
$speech->audio_voice = $recording_voice;
if ($speed_enabled) {
$speech->audio_speed = (float)$recording_speed;
}
$speech->audio_message = $recording_message;
$speech->speech();
//fix invalid riff & data header lengths in generated wave file
if ($speech_engine == 'openai') {
$recording_filename_temp = str_replace('.'.$recording_extension, '.tmp.'.$recording_extension, $recording_filename);
if (file_exists($recording_path.'/'.$recording_filename)) {
exec('sox --ignore-length '.escapeshellarg($recording_path.'/'.$recording_filename).' '.escapeshellarg($recording_path.'/'.$recording_filename_temp));
}
if (file_exists($recording_path.'/'.$recording_filename_temp)) {
recursive_delete($recording_path.'/'.$recording_filename);
exec('mv '.escapeshellarg($recording_path.'/'.$recording_filename_temp).' '.escapeshellarg($recording_path.'/'.$recording_filename));
}
unset($recording_filename_temp);
}
$array['recordings'][$x]['domain_uuid'] = $domain_uuid;
$array['recordings'][$x]['recording_uuid'] = $recording_uuid;
$array['recordings'][$x]['recording_filename'] = $recording_filename;
$array['recordings'][$x]['recording_name'] = $recording_name;
$array['recordings'][$x]['recording_voice'] = $speech_enabled ? $recording_voice : null;
$array['recordings'][$x]['recording_speed'] = ($speech_enabled && $speed_enabled) ? $recording_speed : null;
$array['recordings'][$x]['recording_message'] = $speech_enabled ? $recording_message : null;
$array['recordings'][$x]['recording_description'] = $recording_desc;
// Update ring group fields directly
$array['ring_groups'][0]["ring_group_{$type}"] = $recording_filename;
}
}
//add the dialplan permission
$p = permissions::new();
$p->add("dialplan_add", "temp");
@@ -837,6 +936,23 @@
echo "</td>\n";
echo "</tr>\n";
// Text-to-speech form styles
echo "<style>\n";
echo ".greeting_tts,\n";
echo ".wait_announcement_tts {\n";
echo " overflow: hidden;\n";
echo " max-height: 0;\n";
echo " opacity: 0;\n";
echo " transition: max-height 0.3s ease, opacity 0.3s ease;\n";
echo "}\n";
echo ".greeting_tts.animate-in,\n";
echo ".wait_announcement_tts.animate-in {\n";
echo " padding: 5px 0;\n";
echo " max-height: 500px;\n";
echo " opacity: 1;\n";
echo "}\n";
echo "</style>\n";
$instance_id = 'ring_group_greeting';
$instance_label = 'greeting';
$instance_value = $ring_group_greeting;
@@ -848,8 +964,13 @@
echo "</tr>\n";
echo "<tr>\n";
echo "<td class='vtable' align='left'>\n";
echo "<select name='".$instance_id."' id='".$instance_id."' class='formfld' ".(permission_exists('recording_play') || permission_exists('recording_download') ? "onchange=\"recording_reset('".$instance_id."'); set_playable('".$instance_id."', this.value, this.options[this.selectedIndex].parentNode.getAttribute('data-type'));\"" : null).">\n";
echo "<select name='".$instance_id."' id='".$instance_id."' class='formfld' onchange=\"".(permission_exists('recording_play') || permission_exists('recording_download') ? "recording_reset('".$instance_id."'); set_playable('".$instance_id."', this.value, this.options[this.selectedIndex].parentNode.getAttribute('data-type'));" : null)." if (this.options[this.selectedIndex].getAttribute('data-tts') == 'new') {document.querySelectorAll('.".$instance_label."_tts').forEach(el => { el.classList.add('animate-in'); });} else {document.querySelectorAll('.".$instance_label."_tts').forEach(el => { el.classList.remove('animate-in'); });}\">\n";
echo " <option value=''></option>\n";
if ($speech_enabled && !empty($speech_engine)) {
echo "<optgroup label='".$text['label-text_to_speech']."'>\n";
echo " <option value='' data-tts='new'>".$text['label-new']."</option>\n";
echo "</optgroup>\n";
}
$found = $playable = false;
if (!empty($audio_files) && is_array($audio_files) && @sizeof($audio_files) != 0) {
foreach ($audio_files as $key => $value) {
@@ -916,6 +1037,88 @@
unset($playable, $mime_type);
}
echo "<br />\n";
if ($speech_enabled && !empty($speech_engine)) {
echo "<div class='".$instance_label."_tts'>\n";
echo " <strong>".$text['label-recording_name']."</strong><br />\n";
echo " <input class='formfld' type='text' name='".$instance_label."[recording_name]' maxlength='255' value=\"".escape($recording_name)."\">\n";
echo " <br /><br />\n";
echo " <div style='display: flex; flex-wrap: wrap; column-gap: 10px; width: 400px;'>\n";
echo " <div style='flex: 1; min-width: 200px;'>\n";
echo " <strong>".$text['label-voice']."</strong>\n";
echo " </div>\n";
if ($speed_enabled) {
echo " <div style='flex: 1; min-width: 120px;'>\n";
echo " <strong>".$text['label-speed']."</strong>\n";
echo " </div>\n";
}
// Voice
echo " <div style='flex: 1; min-width: 200px;'>\n";
if (!empty($voices)) {
if ($voices_array_type == 'single') {
echo " <select class='formfld' name='".$instance_label."[recording_voice]' style='width: 100%;'>\n";
echo " <option value=''></option>\n";
foreach ($voices as $key => $voice) {
$recording_voice_selected = (!empty($recording_voice) && $key == $recording_voice) ? "selected='selected'" : null;
echo " <option value='".escape($key)."' $recording_voice_selected>".escape(ucwords($voice))."</option>\n";
}
echo " </select>\n";
}
if ($voices_array_type == 'multi') {
echo " <select class='formfld' id='recording_voice_source' name='".$instance_label."[recording_voice_source]' style='display: none;'>\n";
echo " <option value=''></option>\n";
foreach ($voices as $category => $sub_array) {
$category = $text['label-'.$category] ?? $category;
echo "<optgroup label='".$category."' data-type='".$category."'>\n";
foreach ($sub_array as $key => $voice) {
$recording_voice_selected = (!empty($recording_voice) && $key == $recording_voice) ? "selected='selected'" : null;
echo " <option value='".escape($key)."' $recording_voice_selected>".escape(ucwords($voice))."</option>\n";
}
echo "</optgroup>\n";
}
echo " </select>\n";
echo " <select class='formfld' id='recording_voice_group_select' style='width: 100%; margin-bottom: 5px;'>\n";
echo " <option value='' disabled='disabled' selected='selected'></option>\n";
echo " </select>\n";
echo " <select class='formfld' id='recording_voice_option_select' name='".$instance_label."[recording_voice]' style='width: 100%;' disabled='disabled'>\n";
echo " <option value='' disabled='disabled' selected='selected'></option>\n";
echo " </select>\n";
echo "<script>\n";
echo " select_group_option('recording_voice_source', 'recording_voice_group_select', 'recording_voice_option_select');\n";
echo "</script>\n";
}
} else {
echo " <input class='formfld' type='text' name='".$instance_label."[recording_voice]' maxlength='255' value=\"".escape($recording_voice)."\">\n";
}
echo " </div>\n";
// Speed
if ($speed_enabled) {
echo " <div style='flex: 1; min-width: 120px;'>\n";
echo " <select class='formfld' name='".$instance_label."[recording_speed]' style='width: 100%;'>\n";
foreach ($speed_options as $speed_value => $speed_label) {
$selected = (string)$recording_speed === $speed_value ? "selected='selected'" : '';
echo " <option value='".escape($speed_value)."' $selected>".escape($speed_label)."</option>\n";
}
echo " </select>\n";
echo " <br />\n";
echo " </div>\n";
}
echo " </div>\n";
echo " <br />\n";
echo " <strong>".$text['label-message']."</strong><br />\n";
echo " <textarea class='formfld' name='".$instance_label."[recording_message]' style='width: 300px; height: 150px;'></textarea>\n";
echo "</div>\n";
}
echo $text['description-'.$instance_label]."\n";
echo "</td>\n";
echo "</tr>\n";
@@ -931,8 +1134,13 @@
echo "</tr>\n";
echo "<tr>\n";
echo "<td class='vtable' align='left'>\n";
echo "<select name='".$instance_id."' id='".$instance_id."' class='formfld' ".(permission_exists('recording_play') || permission_exists('recording_download') ? "onchange=\"recording_reset('".$instance_id."'); set_playable('".$instance_id."', this.value, this.options[this.selectedIndex].parentNode.getAttribute('data-type'));\"" : null).">\n";
echo "<select name='".$instance_id."' id='".$instance_id."' class='formfld' onchange=\"".(permission_exists('recording_play') || permission_exists('recording_download') ? "recording_reset('".$instance_id."'); set_playable('".$instance_id."', this.value, this.options[this.selectedIndex].parentNode.getAttribute('data-type'));" : null)." if (this.options[this.selectedIndex].getAttribute('data-tts') == 'new') {document.querySelectorAll('.".$instance_label."_tts').forEach(el => { el.classList.add('animate-in'); });} else {document.querySelectorAll('.".$instance_label."_tts').forEach(el => { el.classList.remove('animate-in'); });}\">\n";
echo " <option value=''></option>\n";
if ($speech_enabled && !empty($speech_engine)) {
echo "<optgroup label='".$text['label-text_to_speech']."'>\n";
echo " <option value='' data-tts='new'>".$text['label-new']."</option>\n";
echo "</optgroup>\n";
}
$found = $playable = false;
if (!empty($audio_files) && is_array($audio_files) && @sizeof($audio_files) != 0) {
foreach ($audio_files as $key => $value) {
@@ -999,6 +1207,88 @@
unset($playable, $mime_type);
}
echo "<br />\n";
if ($speech_enabled && !empty($speech_engine)) {
echo "<div class='".$instance_label."_tts'>\n";
echo " <strong>".$text['label-recording_name']."</strong><br />\n";
echo " <input class='formfld' type='text' name='".$instance_label."[recording_name]' maxlength='255' value=\"".escape($recording_name)."\">\n";
echo " <br /><br />\n";
echo " <div style='display: flex; flex-wrap: wrap; column-gap: 10px; width: 400px;'>\n";
echo " <div style='flex: 1; min-width: 200px;'>\n";
echo " <strong>".$text['label-voice']."</strong>\n";
echo " </div>\n";
if ($speed_enabled) {
echo " <div style='flex: 1; min-width: 120px;'>\n";
echo " <strong>".$text['label-speed']."</strong>\n";
echo " </div>\n";
}
// Voice
echo " <div style='flex: 1; min-width: 200px;'>\n";
if (!empty($voices)) {
if ($voices_array_type == 'single') {
echo " <select class='formfld' name='".$instance_label."[recording_voice]' style='width: 100%;'>\n";
echo " <option value=''></option>\n";
foreach ($voices as $key => $voice) {
$recording_voice_selected = (!empty($recording_voice) && $key == $recording_voice) ? "selected='selected'" : null;
echo " <option value='".escape($key)."' $recording_voice_selected>".escape(ucwords($voice))."</option>\n";
}
echo " </select>\n";
}
if ($voices_array_type == 'multi') {
echo " <select class='formfld' id='recording_voice_source' name='".$instance_label."[recording_voice_source]' style='display: none;'>\n";
echo " <option value=''></option>\n";
foreach ($voices as $category => $sub_array) {
$category = $text['label-'.$category] ?? $category;
echo "<optgroup label='".$category."' data-type='".$category."'>\n";
foreach ($sub_array as $key => $voice) {
$recording_voice_selected = (!empty($recording_voice) && $key == $recording_voice) ? "selected='selected'" : null;
echo " <option value='".escape($key)."' $recording_voice_selected>".escape(ucwords($voice))."</option>\n";
}
echo "</optgroup>\n";
}
echo " </select>\n";
echo " <select class='formfld' id='recording_voice_group_select' style='width: 100%; margin-bottom: 5px;'>\n";
echo " <option value='' disabled='disabled' selected='selected'></option>\n";
echo " </select>\n";
echo " <select class='formfld' id='recording_voice_option_select' name='".$instance_label."[recording_voice]' style='width: 100%;' disabled='disabled'>\n";
echo " <option value='' disabled='disabled' selected='selected'></option>\n";
echo " </select>\n";
echo "<script>\n";
echo " select_group_option('recording_voice_source', 'recording_voice_group_select', 'recording_voice_option_select');\n";
echo "</script>\n";
}
} else {
echo " <input class='formfld' type='text' name='".$instance_label."[recording_voice]' maxlength='255' value=\"".escape($recording_voice)."\">\n";
}
echo " </div>\n";
// Speed
if ($speed_enabled) {
echo " <div style='flex: 1; min-width: 120px;'>\n";
echo " <select class='formfld' name='".$instance_label."[recording_speed]' style='width: 100%;'>\n";
foreach ($speed_options as $speed_value => $speed_label) {
$selected = (string)$recording_speed === $speed_value ? "selected='selected'" : '';
echo " <option value='".escape($speed_value)."' $selected>".escape($speed_label)."</option>\n";
}
echo " </select>\n";
echo " <br />\n";
echo " </div>\n";
}
echo " </div>\n";
echo " <br />\n";
echo " <strong>".$text['label-message']."</strong><br />\n";
echo " <textarea class='formfld' name='".$instance_label."[recording_message]' style='width: 300px; height: 150px;'></textarea>\n";
echo "</div>\n";
}
echo $text['description-wait_announcement']."\n";
echo "</td>\n";
echo "</tr>\n";