PBToolboxAI v5 ← Site

soundplayer — n_pbt_soundplayer #

← Referencia de componentes · Índice de la guía

Reproduce un sonido o una música — un archivo del equipo o una URL — de forma asíncrona (eventos) o síncrona (la llamada vuelve cuando el sonido termina), y un pitido puro sin ningún archivo. Todos los formatos que el motor WebView2 decodifica: mp3, wav, ogg, opus, flac, aac, m4a, mp4, webm. Sin DLL de terceros, sin PlaySound limitado a wav.

▶ Verlo en vivo — Aplicación de demostración, mosaico Sound player: los sonidos, el código que los reproduce y esta página, lado a lado.


En resumen #

Objeto no visualn_pbt_soundplayer
Sirve paraUn carillón antes de un mensaje, una alerta, una música de espera, un mp3 elegido por el usuario, un flujo de Internet
PrincipioUna página oculta lleva un reproductor; of_play vuelve enseguida y los eventos cuentan el resto, of_play_sync espera el final del sonido
DependenciaEl runtime WebView2, ya requerido por la biblioteca — nada más

Inicio rápido #

// In the window : the object
n_pbt_soundplayer inv_sound
inv_sound = create n_pbt_soundplayer

// Synchronous : the next line runs after the chime
inv_sound.of_play_sync(/*source*/ "C:\Windows\Media\chimes.wav")
MessageBox("Orders", "Order 4152 shipped.")

// Asynchronous : a music from the Internet, the window stays alive
inv_sound.ii_volume = 60
inv_sound.of_play(/*source*/ "https://example.org/music/lobby.mp3")

// When the window closes : the hidden player goes with the object
destroy inv_sound

Los eventos ue_* se entregan por sí solos — el componente los recoge él mismo mientras el reproductor está abierto y los lanza en el componente: nada que cablear, ni receptor ni temporizador.

Dónde escribir los eventos #

Un objeto creado por create n_pbt_soundplayer sirve muy bien para los sonidos síncronos y para los que se lanzan sin esperar noticias — es lo que hace el inicio rápido —, pero sus eventos no tienen ningún script: PowerBuilder no permite escribir ue_ended en un objeto creado en un script. Para reaccionar a los eventos, dos vías:

No destruya el reproductor desde uno de sus propios eventos: of_close basta, y la destrucción del objeto lo hace por usted.


Archivo o URL, y por qué una pieza larga empieza enseguida #


Propiedades #

PropiedadTipoPredeterminadoFunción
ii_volumeinteger100Volumen en porcentaje, de 0 a 100, entregado con el verbo que lanza un sonido — y es el volumen de ESE sonido: of_play, of_play_sync y of_crossfade ajustan el sonido principal; of_play_over, of_beep y of_play_named reproducen el suyo a ese volumen sin tocar el sonido principal (una alerta a 100 sobre un fondo bajado a 20); un sonido puesto en cola por of_enqueue lo conserva para su turno. Cambiado mientras suena un sonido, espera al verbo siguiente — solo of_fade_to cambia el sonido en curso
ib_loopbooleanfalseVerdadero para repetir el sonido en bucle hasta of_stop — un timbre, una música de fondo. Se entrega con el sonido siguiente. of_play_sync lo ignora: un sonido síncrono suena una vez, un bucle no tiene final que esperar. Un sonido en bucle nunca termina: la cola (of_enqueue) espera detrás de él hasta of_stop, of_next u of_stop_sound
il_timeout_mslong300000La duración máxima de un sonido síncrono (of_play_sync, of_beep_sync, of_play_named_sync); cinco minutos por defecto. Pasado ese plazo la llamada devuelve -4 y ese sonido se corta (sigue ue_stopped) — solo él: un fondo, las superposiciones y la cola continúan. 0 o menos: 24 horas
ii_rateinteger100Velocidad en porcentaje (25 a 400), entregada con el verbo que lanza un sonido, para ESE sonido: el sonido principal, o una superposición (of_play_over) sin cambiar el principal
ii_paninteger0Balance del sonido PRINCIPAL, de -100 (izquierda) a 100 (derecha), entregado con of_play, of_play_sync u of_crossfade, para ARCHIVOS; una URL suena sin balance
il_fade_mslong0Fundido en milisegundos (10 000 como máximo): cada inicio sube desde el silencio, cada of_stop o pausa se apaga, una reanudación vuelve a subir; ue_stopped llega igualmente enseguida
ib_gapless_loopbooleanfalseCon ib_loop, un archivo CORTO del equipo se repite sin cortes: decodificado una vez, se encadena sin costuras — un timbre, un fondo musical. 4 MB y 60 segundos como máximo (más allá, ue_failed con REASON_TOO_LONG); una URL se repite de la forma ordinaria. Se entrega con el verbo, como ib_loop
ib_mutedbooleanfalseTodos los sonidos del reproductor en silencio al instante — el sonido principal, las superposiciones, los pitidos, los sonidos con nombre — ii_volume conservado: false devuelve el sonido al mismo nivel. En directo
ib_queue_repeatbooleanfalseLa cola (of_enqueue) vuelve a empezar tras su último sonido, una y otra vez; of_next tras el último va al primero, of_previous antes del primero al último. Una cola cuyos sonidos fallan todos se detiene igualmente. En directo
ipo_ownerpowerobjectnullEl objeto visual para el que trabaja este reproductor: la licencia se comprueba en su clase. Necesario solo en la aplicación de demostración; una clave de desarrollo o de ejecución desbloquea el reproductor sin él. Sin desbloquear, el reproductor está en modo demo — solo se reproducen los 10 primeros segundos de un sonido

Métodos #

MétodoFunción
of_get_last_error ( ) → stringPor qué falló la última llamada: archivo ausente, formato no decodificable, dirección http://, URL muda, sin salida de audio, número de un sonido que ya no está en curso. Rellenado también por ue_failed y tras cada -5. Tras un of_play_sync que devolvió 0: "stopped" si el sonido fue cortado en lugar de sonar hasta el final
of_open ( ) → longCrea el reproductor. Opcional — cada método lo hace — pero llamarlo al abrir la ventana paga el coste una vez. Devuelve el handle (> 0), o -2 si el reproductor no pudo crearse (of_get_last_error() dice por qué)
of_is_open ( ) → booleanVerdadero en cuanto existe el reproductor
of_play (string as_source {, long al_start_ms}) → longReproduce sin esperar: un archivo del equipo o una URL https, el final llega por ue_ended. al_start_ms hace empezar el sonido en ese punto (en modo demo, nunca más allá de los 10 primeros segundos). El sonido principal en curso se sustituye, sin evento; un pitido o un sonido con nombre continúa. Devuelve 0 una vez lanzado, -5 si la fuente se rechaza de entrada — vacía, una dirección http://, una dirección file:// mal formada, un formato rechazado por su nombre: of_get_last_error() dice cuál, el sonido en curso continúa y no sigue ningún ue_failed —, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_play_sync (string as_source) → longReproduce y espera el final: la llamada vuelve cuando el sonido termina (o se detiene). La ventana sigue repintándose, pero pasados 250 ms todos los componentes PBToolboxAI de la aplicación muestran el reloj de arena e ignoran el ratón hasta el retorno: resérvelo para sonidos cortos. Suena una vez, diga lo que diga ib_loop. Devuelve 0 una vez terminado el sonido (of_get_last_error() = "stopped" si fue cortado), -2 si el reproductor no pudo crearse, -4 si no pudo sonar, si il_timeout_ms venció (solo ese sonido se corta) o si otro sonido síncrono ya espera
of_beep (long al_hz, long al_ms) → longUn tono puro sin archivo: al_hz (20 a 20 000) durante al_ms milisegundos (10 a 5 000), al volumen ii_volume; un valor más allá de un límite se lleva a él. Un canal aparte: of_play no lo corta, of_stop sí. Vuelve enseguida; sigue ue_ended. Devuelve 0 una vez lanzado, -5 si al_hz o al_ms vale 0 o menos (una variable sin inicializar no suena un pitido por defecto), -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_beep_sync (long al_hz, long al_ms) → longEl mismo tono, y la llamada vuelve cuando termina: dos seguidos forman una señal de dos notas. Devuelve 0, -5 si al_hz o al_ms vale 0 o menos, -2 si el reproductor no pudo crearse, o -4 sin salida de audio, si il_timeout_ms venció (solo se corta el pitido) o si otro sonido síncrono ya espera (of_get_last_error())
of_stop ( ) → longDetiene todo lo que suena el reproductor — el sonido, un pitido, un sonido con nombre, las superposiciones, un fundido encadenado — y vacía la cola; sigue un ue_stopped, enseguida. Con il_fade_ms, el sonido principal se apaga durante ese tiempo en lugar de pararse en seco Devuelve 0 una vez hecho.
of_pause ( ) → longSuspende el sonido donde está (sobre il_fade_ms); of_resume lo retoma. Devuelve 0 una vez hecho, -5 si no hay nada que suspender — ningún sonido principal, o ya en pausa; un pitido o una superposición no se suspenden —, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_resume ( ) → longRetoma el sonido donde of_pause lo dejó. Devuelve 0 una vez hecho, -5 si ningún sonido está en pausa, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_seek (long al_ms) → longSe coloca en una posición del sonido, en milisegundos desde su inicio. En modo demo, nunca más allá de los 10 primeros segundos. Para EMPEZAR en una posición, of_play acepta una: el reproductor no guarda ningún sonido detenido en el que moverse. Devuelve 0 una vez hecho, -5 si no suena ningún sonido (nada que mover), -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_is_playing ( ) → booleanVerdadero mientras un sonido, un pitido, un sonido con nombre o una superposición está en curso — un sonido en pausa cuenta, no ha terminado
of_is_paused ( ) → booleanVerdadero mientras el sonido está suspendido por of_pause
of_duration ( ) → longLa longitud del sonido en milisegundos, 0 mientras se desconoce; ue_started también la lleva
of_position ( ) → longDónde va el sonido, en milisegundos — léalo desde un timer para mover una barra de progreso suya
of_source ( ) → stringLo que of_play recibió por última vez, tal cual
of_play_over (string as_source) → longReproduce un sonido ENCIMA de lo que suena, sin cortarlo, a ii_volume e ii_rate — los suyos: el fondo conserva los suyos (un fondo bajado por of_fade_to sigue bajo bajo una alerta a 100); of_stop_sound lo detiene solo, of_stop con el resto. Devuelve el número del sonido (> 0) — sus eventos lo llevan, dos superposiciones del mismo archivo se distinguen por él —, -5 si la fuente se rechaza de entrada, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_enqueue (string as_source) → longPone un sonido en COLA: suena enseguida si el reproductor está libre, tras el sonido (o el pitido, o el sonido con nombre) en curso si no, nunca cortado. El sonido en cola conserva ii_volume, ii_rate e ib_loop tal como están en la llamada, para su turno; un sonido en bucle nunca termina, la cola espera detrás de él. Un sonido que no puede sonar lanza ue_failed en su turno y la cola continúa. La cola guarda lo que ha sonado: of_next, of_previous. Devuelve el número del sonido (> 0), -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_clear_queue ( ) → longOlvida la cola — los sonidos en espera y los que ya ha sonado —, sin cortar el que suena; ue_queue_done sigue igualmente a su final. Devuelve 0 una vez hecho, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_queue_count ( ) → longDevuelve el número de sonidos aún en espera
of_preload (string as_source) → longCarga un sonido sin reproducirlo: el primer of_play de esa fuente arranca al instante. Un archivo que resulta ilegible lo señala ese of_play, mediante ue_failed. Devuelve 0 una vez hecho, -5 si la fuente se rechaza de entrada (of_get_last_error() dice por qué), -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_fade_to (integer ai_volume, long al_ms) → longLleva el volumen a ai_volume (0 a 100) en al_ms ms sobre el sonido que suena; el objetivo pasa a ser ii_volume, y un sonido reproducido encima mientras tanto no interrumpe el fundido. Devuelve 0 una vez hecho, -2 si el reproductor no pudo crearse
of_play_named (string as_name) → longUn sonido SINTETIZADO, sin archivo, al volumen ii_volume: SOUND_SUCCESS, SOUND_ERROR, SOUND_WARNING, SOUND_INFO, SOUND_NOTIFY. Un canal aparte: of_play no lo corta, of_stop sí. Devuelve 0 una vez lanzado, -2 si el reproductor no pudo crearse; un nombre desconocido llega por ue_failed (REASON_UNKNOWN)
of_play_named_sync (string as_name) → longEl mismo sonido, y la llamada vuelve a su final. Devuelve 0, -2 si el reproductor no pudo crearse, -4 con un nombre desconocido, sin salida de audio o si otro sonido síncrono ya espera (of_get_last_error())
of_has_output ( ) → booleanVerdadero si el equipo tiene salida de audio: a preguntar ANTES de una alerta. El sonido va siempre a la salida por defecto de Windows
of_equalizer (boolean ab_on {, integer ai_gains[]}) → longEcualizador de 5 bandas (60 / 230 / 910 / 3600 / 14000 Hz, of_eq_frequencies da los centros), ganancia en dB de -24 a 24 (un valor fuera se lleva al límite más cercano); la sobrecarga pone todas las ganancias (una banda que el array no alcanza vuelve a 0), of_equalizer_band una en directo. Archivos LOCALES. Devuelve 0 una vez hecho, -2 si el reproductor no pudo crearse
of_equalizer_band (integer ai_band, integer ai_gain) → longEstablece la ganancia de UNA banda (ai_band de 1 a 5, ai_gain en dB, de -24 a 24) y la aplica al instante al sonido que suena — un cursor suyo movido en directo; las demás bandas conservan su ganancia. Devuelve 0, -5 si la banda está fuera de rango, -2 si el reproductor no pudo crearse
of_eq_frequencies (ref long al_freqs[]) → longRellena al_freqs con la frecuencia central de cada banda, en Hz y en orden (60, 230, 910, 3600, 14000) — lo que muestra una etiqueta de banda propia. Devuelve el número de bandas, 5
of_meter (boolean ab_on {, integer ai_bars}) → longEnciende un vúmetro / analizador: consulte luego of_level (0 a 100) y of_spectrum (ai_bars barras) desde un temporizador para dibujar su propio visualizador. Archivos LOCALES. Devuelve 0 una vez hecho, -5 si ai_bars sale de 1 a 64 (nada cambia), -2 si el reproductor no pudo crearse
of_level ( ) → longDevuelve el nivel sonoro del instante, 0 a 100, leído en vivo — la aguja de un vúmetro; 0 cuando el medidor (of_meter) está apagado o nada suena. Sondéelo desde un temporizador
of_spectrum (ref long al_bars[]) → longRellena al_bars con el espectro, leído en vivo: tantos valores como pidió of_meter, 0 a 100 cada uno, graves primero — las barras de un analizador propio. Devuelve el número de barras, 0 con el medidor apagado
of_crossfade (string as_source, long al_ms) → longFundido encadenado: el sonido actual se apaga en al_ms (10 000 como máximo) mientras la nueva fuente sube — un cambio de pista sin corte; 0 cambia al instante. El nuevo sonido toma ii_volume, ii_rate, ii_pan e ib_loop, y un of_fade_to durante la subida toma el control. of_stop durante el fundido detiene ambos, y un of_play_sync que esperaba el primer sonido vuelve; el sonido sustituido no lanza nada. Devuelve 0 una vez lanzado, -5 si la fuente se rechaza de entrada — el sonido en curso sigue entonces, intacto —, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_play_range (string as_source, long al_from_ms, long al_to_ms) → longReproduce un SEGMENTO de un archivo, de al_from_ms a al_to_ms — un banco de sonidos cortos en un solo archivo, cada uno reproducido por sus límites. Sustituye el sonido principal como of_play, con sus ajustes; con ib_loop el segmento vuelve a sonar desde su inicio. ue_ended a su final. Devuelve 0 una vez lanzado, -5 si al_from_ms es negativo, al_to_ms no va después, o la fuente se rechaza de entrada, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_stop_sound (long al_sound) → longDetiene UN sonido por su número (of_play_over y of_enqueue lo devuelven, los eventos lo llevan): una superposición — las demás continúan —, el sonido principal (sobre il_fade_ms, la cola pasando al siguiente), un pitido, un sonido con nombre; sigue un ue_stopped. Un sonido aún EN ESPERA se retira de la cola, sin evento. Devuelve 0 una vez hecho, -5 si ningún sonido lleva ahora ese número, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_next ( ) → longReproduce al instante el sonido SIGUIENTE de la cola — el sonido en curso se sustituye, sin evento; con ib_queue_repeat, tras el último viene el primero. ue_source_changed dice dónde está la cola. Devuelve 0 una vez hecho, -5 si no hay sonido siguiente, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_previous ( ) → longReproduce el sonido ANTERIOR al que suena en la cola — la cola guarda lo que ha sonado; con la cola en reposo, el último sonado de nuevo. Con ib_queue_repeat, antes del primero viene el último. Devuelve 0 una vez hecho, -5 si no lo hay, -2 si el reproductor no pudo crearse, -4 si la página no respondió
of_queue_index ( ) → longDevuelve el lugar en la cola (1 = el primer sonido puesto en cola) del sonido que suena, 0 cuando ese sonido no viene de la cola o nada suena
of_is_buffering ( ) → booleanVerdadero mientras el sonido avanza pero espera sus datos — el tiempo que anunció ue_buffering: un flujo de Internet que se detiene, un salto lejos en un archivo leído de una URL. Un archivo del equipo nunca espera
of_process_events ( )Vacía la cola de eventos y los lanza en el objeto. El pump interno del componente lo llama por usted mientras el reproductor está abierto — usted nunca lo llama
of_close ( ) → longLibera el reproductor, deteniendo primero el sonido, al instante (sin fundido): un sonido que sonaba termina con su ue_stopped, lanzado antes del retorno; se hace por usted al destruir el objeto. No destruya el reproductor desde uno de sus eventos: of_close basta Devuelve 0 una vez hecho.
of_reset ( ) → longDetiene el sonido y devuelve cada ajuste a su valor por defecto Devuelve 0 una vez hecho.

Eventos #

EventoCuándo
ue_started (string as_source, long al_duration_ms, long al_sound)El sonido empieza de verdad — una URL, cuando han llegado datos suficientes. al_duration_ms es la longitud cuando el archivo la indica, 0 si no; al_sound es el número del sonido
ue_ended (string as_source, boolean ab_truncated, long al_sound)El sonido terminó por sí mismo. ab_truncated es verdadero cuando el límite demo lo cortó, nunca con licencia. Un sonido en bucle no termina: se detiene. Un sonido principal SUSTITUIDO por otro (of_play, of_crossfade, of_next…) no lanza nada: lo sustituyó su script
ue_failed (string as_source, string as_message, string as_reason, long al_sound)El sonido no pudo sonar — una fuente rechazada de entrada por un método es su -5, no este evento. as_reason es una palabra que comprobar, una constante REASON_*: REASON_INSECURE (dirección http://), REASON_FORMAT (formato rechazado por su nombre), REASON_UNSUPPORTED (archivo ausente, dirección file:// mal formada), REASON_NETWORK, REASON_DECODE, REASON_NO_SOURCE, REASON_UNKNOWN (sonido con nombre inexistente), REASON_UNAVAILABLE (sin salida de audio), REASON_TOO_LONG (un bucle sin cortes de un archivo demasiado largo), REASON_FAILED (lo demás, un error de script de la página incluido); as_message es la frase que mostrar, en el idioma de visualización; al_sound el número del sonido. Un sonido de la cola que falla no detiene la cola
ue_stopped ( )Lanzado una vez cuando of_stop (o of_close, of_stop_sound, o el fin de il_timeout_ms para el sonido de esa llamada) cortó lo que sonaba — no cuando un sonido termina solo, eso es ue_ended
ue_paused ( ) / ue_resumed ( )El sonido se suspende, luego se reanuda
ue_progress (long al_position_ms, long al_duration_ms)Una vez por segundo de reloj durante la reproducción, sea cual sea ii_rate: posición y duración
ue_queue_done ( )El último sonido de la cola (of_enqueue) ha terminado — nunca con ib_queue_repeat, la cola vuelve a empezar
ue_buffering (boolean ab_on)ab_on verdadero: el sonido avanza pero espera sus datos — un flujo de Internet que se detiene, un salto lejos en un archivo leído de una URL; falso: vuelve a avanzar (o se pausa, se detiene, se sustituye, falla). Una espera de menos de un cuarto de segundo no dice nada
ue_source_changed (long al_index, string as_source)La cola pasa a uno de sus sonidos — por sí misma, por of_next, of_previous o ib_queue_repeat: al_index es su lugar en la cola (1 = el primer sonido puesto en cola), as_source lo que se puso en cola

Varios sonidos, fundidos, cola #

// A background in a loop, faded in ; an alert over it, the background lowered meanwhile
inv_sound.il_fade_ms = 1500
inv_sound.ib_loop = true
inv_sound.of_play(/*source*/ "C:\Windows\Media\Ring05.wav")
inv_sound.of_fade_to(/*volume*/ 20, /*ms*/ 500)

// The alert has its own volume : the background stays at 20
inv_sound.ii_volume = 100
inv_sound.of_play_over(/*source*/ "C:\Windows\Media\Alarm01.wav")

// Announcements in a row : each one waits for the previous
inv_sound.of_enqueue(/*source*/ "order-4152.mp3")
inv_sound.of_enqueue(/*source*/ "order-4153.mp3")

// A confirmation with no file at all
inv_sound.of_play_named(/*name*/ n_pbt_soundplayer.SOUND_SUCCESS)
// Local variables
long ll_first

// Two alerts of the same file : each one has its own number
ll_first = inv_sound.of_play_over(/*source*/ "C:\Windows\Media\Alarm01.wav")
inv_sound.of_play_over(/*source*/ "C:\Windows\Media\Alarm01.wav")

// Later : the first one stopped alone, the other goes on
inv_sound.of_stop_sound(/*sound*/ ll_first)

// A queue that starts over after its last sound, and the next sound right now
inv_sound.ib_queue_repeat = true
inv_sound.of_next()

// A ring that loops without a gap, then everything silent for a moment
inv_sound.ib_loop = true
inv_sound.ib_gapless_loop = true
inv_sound.of_play(/*source*/ "C:\Windows\Media\Ring05.wav")
inv_sound.ib_muted = true

Ejemplos #

Una señal de dos notas, sin ningún archivo #

// Each call waits for its tone : the second starts when the first is over
inv_sound.of_beep_sync(/*hz*/ 660, /*ms*/ 180)
inv_sound.of_beep_sync(/*hz*/ 990, /*ms*/ 220)

Un mp3 elegido por el usuario, con una barra de progreso #

// Local variables
string ls_path, ls_file
constant unsignedlong OFN_EXPLORER = 2
constant unsignedlong OFN_NOCHANGEDIR = 64

// Let the user pick a music file - in the Explorer style, without moving the current folder of the application - then play it
if GetFileOpenName("Music", ls_path, ls_file, "mp3", "Music (*.mp3;*.wav;*.flac),*.mp3;*.wav;*.flac", /*initdir*/ "", OFN_EXPLORER + OFN_NOCHANGEDIR) = 1 then
	inv_sound.of_play(/*source*/ ls_path)          // returns at once ; ue_started brings the length
	Timer(0.5)                         // in the window's timer event :
end if

// event timer of the window
if inv_sound.of_is_playing() then
	hpb_progress.Position = inv_sound.of_position() * 100 / Max(inv_sound.of_duration(), 1)
end if

Un timbre en bucle hasta que el usuario actúe #

// A ring at 40 %, in a loop until it is stopped
inv_sound.ii_volume = 40
inv_sound.ib_loop = true
inv_sound.of_play(/*source*/ "C:\Windows\Media\Ring01.wav")

// ... later, in the button that acknowledges the call :
inv_sound.of_stop()

Buenas prácticas #

← Referencia de componentes · Índice de la guía