Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 117 additions & 2 deletions pjsip-apps/src/pjsua/pjsua_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,56 @@ static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
pjsip_endpt_cancel_timer(endpt, &cd->timer);
}

/* Rewind play file when hangup automatically,
/* Rewind play file when hangup automatically,
* since file is not looped
*/
if (app_config.auto_play_hangup)
pjsua_player_set_pos(app_config.wav_id, 0);

/* Cleanup dynamic playback if attached to this call */
if (app_config.dyn_player_active &&
app_config.dyn_player_call == call_id)
{
PJ_LOG(3, (THIS_FILE, "Call ended, stopping playback"));

/* Disconnect and destroy player if created */
if (app_config.dyn_player_id != PJSUA_INVALID_ID) {
/* Destroy player (connections to call's slot will be cleaned
* up automatically as the call is terminating) */
pjsua_player_destroy(app_config.dyn_player_id);
}

/* Reset state */
app_config.dyn_player_id = PJSUA_INVALID_ID;
app_config.dyn_player_port = PJSUA_INVALID_ID;
app_config.dyn_player_call = PJSUA_INVALID_ID;
app_config.dyn_player_active = PJ_FALSE;
app_config.dyn_play_filename[0] = '\0';
}

/* Cleanup dynamic recording if attached to this call */
if (app_config.dyn_rec_active &&
app_config.dyn_rec_call == call_id)
{
PJ_LOG(3, (THIS_FILE, "Call ended, stopping recording"));

/* Disconnect and destroy recorder if created */
if (app_config.dyn_rec_id != PJSUA_INVALID_ID) {
/* Disconnect microphone from recorder (mic is always slot 0)
* (call's slot is being torn down, so that disconnects automatically) */
pjsua_conf_disconnect(0, app_config.dyn_rec_port);

/* Destroy recorder */
pjsua_recorder_destroy(app_config.dyn_rec_id);
}

/* Reset state */
app_config.dyn_rec_id = PJSUA_INVALID_ID;
app_config.dyn_rec_port = PJSUA_INVALID_ID;
app_config.dyn_rec_call = PJSUA_INVALID_ID;
app_config.dyn_rec_active = PJ_FALSE;
app_config.dyn_rec_filename[0] = '\0';
}

PJ_LOG(3,(THIS_FILE, "Call %d is DISCONNECTED [reason=%d (%.*s)]",
call_id,
Expand Down Expand Up @@ -423,6 +467,41 @@ static void on_call_audio_state(pjsua_call_info *ci, unsigned mi,
pjsua_conf_connect(call_conf_slot, app_config.rec_port);
}

/* Dynamic recording - start if queued */
if (app_config.dyn_rec_active &&
app_config.dyn_rec_id == PJSUA_INVALID_ID &&
app_config.dyn_rec_filename[0] != '\0')
{
pj_status_t status;
pjsua_recorder_id rec_id;
pjsua_conf_port_id rec_port;
pj_str_t rec_file;

/* Create recorder */
rec_file = pj_str(app_config.dyn_rec_filename);
status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id);
if (status == PJ_SUCCESS) {
rec_port = pjsua_recorder_get_conf_port(rec_id);

/* Connect call to recorder */
pjsua_conf_connect(call_conf_slot, rec_port);

/* Connect microphone to recorder */
pjsua_conf_connect(0, rec_port);

/* Save state */
app_config.dyn_rec_id = rec_id;
app_config.dyn_rec_port = rec_port;
app_config.dyn_rec_call = ci->id;

PJ_LOG(3, (THIS_FILE, "Dynamic recording auto-started"));
} else {
PJ_LOG(2, (THIS_FILE, "Failed to auto-start recording: %d", status));
app_config.dyn_rec_active = PJ_FALSE;
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When auto-start of recording fails and dyn_rec_active is set to FALSE (line 500), the dyn_rec_filename is not cleared. This creates an inconsistent state. The filename should be cleared along with the active flag to maintain consistency.

Suggested change
app_config.dyn_rec_active = PJ_FALSE;
app_config.dyn_rec_active = PJ_FALSE;
app_config.dyn_rec_filename[0] = '\0';

Copilot uses AI. Check for mistakes.
app_config.dyn_rec_filename[0] = '\0';
}
}

/* Record audio into AVI, if desired */
if (app_config.avi_auto_rec && app_config.avi_rec_audio &&
app_config.avi_aud_slot != PJSUA_INVALID_ID)
Expand All @@ -431,13 +510,49 @@ static void on_call_audio_state(pjsua_call_info *ci, unsigned mi,
}

/* Stream a file, if desired */
if ((app_config.auto_play || app_config.auto_play_hangup) &&
if ((app_config.auto_play || app_config.auto_play_hangup) &&
app_config.wav_port != PJSUA_INVALID_ID)
{
pjsua_conf_connect(app_config.wav_port, call_conf_slot);
connect_sound = PJ_FALSE;
}

/* Dynamic playback - start if queued */
if (app_config.dyn_player_active &&
app_config.dyn_player_id == PJSUA_INVALID_ID &&
app_config.dyn_play_filename[0] != '\0')
{
pj_status_t status;
pjsua_player_id player_id;
pjsua_conf_port_id player_port;
pj_str_t play_file;

/* Create player */
play_file = pj_str(app_config.dyn_play_filename);
status = pjsua_player_create(&play_file, 0, &player_id);
if (status == PJ_SUCCESS) {
player_port = pjsua_player_get_conf_port(player_id);

/* Connect player to call */
pjsua_conf_connect(player_port, call_conf_slot);

/* Disconnect microphone (like auto-play) */
pjsua_conf_disconnect(0, call_conf_slot);

/* Save state */
app_config.dyn_player_id = player_id;
app_config.dyn_player_port = player_port;
app_config.dyn_player_call = ci->id;

PJ_LOG(3, (THIS_FILE, "Dynamic playback auto-started"));
connect_sound = PJ_FALSE;
} else {
PJ_LOG(2, (THIS_FILE, "Failed to auto-start playback: %d", status));
app_config.dyn_player_active = PJ_FALSE;
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When auto-start of playback fails and dyn_player_active is set to FALSE (line 550), the dyn_play_filename is not cleared. This creates an inconsistent state similar to the recording case. The filename should be cleared along with the active flag to maintain consistency.

Suggested change
app_config.dyn_player_active = PJ_FALSE;
app_config.dyn_player_active = PJ_FALSE;
app_config.dyn_play_filename[0] = '\0';

Copilot uses AI. Check for mistakes.
app_config.dyn_play_filename[0] = '\0';
}
}

/* Stream AVI, if desired */
if (app_config.avi_auto_play &&
app_config.avi_def_idx != PJSUA_INVALID_ID &&
Expand Down
Loading
Loading