<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hi,</div><div><br></div><div>I've been looking at pulseaudio modules and am not seeing the behavior of the hook called by PA_CORE_HOOK_SINK_INPUT_PUT that I'd expect. I've enclosed some code at the end of this message that essentially calls pa_log when any one of the sink-input hooks are called. </div><div><br></div><div>I think, from Lennarts suggestions earlier on the list that put should be called once a sink-input is finalised, but before streaming takes place. However what I'm seeing is different. I'm using 0.9.8, we plan to move to 0.9.10 in the coming few weeks, but I did try this with 0.9.10 and saw similar behavior.</div><div><br></div><div>Here's what I'm seeing: launch pulseaudio with logging</div><div><br></div><div>% pulseaudio --log-level=3</div><div><br></div><div>in pacmd load the module built from the attached code:</div><div><br></div><div>% pacmd</div><div>>>> load-module module-test-sink-input</div><div>>>></div><div><br></div><div>Now play a .wav file with paplay</div><div><br></div><div>% <span class="Apple-style-span" style="font-family: Verdana; "> paplay ~/Sony\ CD-ROM\ Test\ Disk\ Type\ 3.0/Cantibile-Op-17.wav <br></span><br></div><div>If you look at the log file output, you can see that the put message is output after sink-input is created. Now I'd expect the creation message to be output before my hook message in response to the put call being called, however what is unexpected is that the put call does not get called until after the file stops streaming. </div><div><br></div><div><!--StartFragment--><font face="Verdana, Helvetica, Arial"><span style="font-size:12.0px">I: module.c: Loaded "module-cli-protocol-unix" (index: #8; argument: "").<br>
I: client.c: Created 0 "UNIX socket client"<br>
E: > pa__init<br>
E: this version compiled - Jun 19 2008 13:22:31<br>
E: < pa__init<br>
I: module.c: Loaded "module-test-sink-input" (index: #9; argument: "").<br>
I: client.c: Created 1 "Native client (UNIX socket client)"<br>
I: protocol-native.c: Got credentials: uid=1000 gid=1000 success=1<br>
I: protocol-native.c: Enabled SHM for new connection<br>
I: client.c: Client 1 changed name from "Native client (UNIX socket client)" to "paplay"<br>
E: < sink_input_new_hook<br>
E: < sink_input_fixate_hook<br>
I: sink-input.c: Created input 0 "/home/nick/Sony CD-ROM Test Disk Type 3.0/Cantibile-Op-17.wav" on usbAudio with sample spec s16le 2ch 44100Hz and channel map front-left,front-right<br>
E: < sink_input_put_hook<br>
E: < sink_input_unlink_hook<br>
I: sink-input.c: Freeing output 0 "/home/nick/Sony CD-ROM Test Disk Type 3.0/Cantibile-Op-17.wav"<br>
I: client.c: Freed 1 "paplay"<br>
I: protocol-native.c: connection died.<br>
<br>
<span class="Apple-style-span" style="font-family: Helvetica; "><div>Should I expect put to be called on the sink input before the file is streamed to the output, or after?</div><div><br></div><div>Thanks</div><div><br></div><div>Nick</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></span>
</span></font>
<!--EndFragment-->
</div><div><!--StartFragment--><font face="Verdana, Helvetica, Arial"><span style="font-size:12.0px">/*<br>
* pulse module for stream routing to log hook calls for sink-inputs<br>
* Nick Thompson<br>
* 6/19/08<br>
*<br>
*/<br>
<br>
#include <pulsecore/config.h><br>
#include <pulsecore/module.h><br>
<br>
<br>
/* user data for the pulseaudio module, store this in init so that<br>
* stuff we need can be accessed when we get callbacks<br>
*/<br>
struct userdata {<br>
<br>
/* cached references to pulse internals */<br>
pa_core *core;<br>
pa_module *module;<br>
<br>
/* slots for our sink input hook functions */<br>
pa_hook_slot *sink_input_new_hook_callback ;<br>
pa_hook_slot *sink_input_fixate_hook_callback ;<br>
pa_hook_slot *sink_input_put_hook_callback ;<br>
pa_hook_slot *sink_input_unlink_hook_callback ;<br>
pa_hook_slot *sink_input_unlink_post_hook_callback ;<br>
pa_hook_slot *sink_input_move_hook_callback ;<br>
pa_hook_slot *sink_input_move_post_callback ;<br>
pa_hook_slot *sink_input_name_changed_hook_callback ;<br>
pa_hook_slot *sink_input_state_changed_hook_callback ;<br>
};<br>
<br>
<br>
static pa_hook_result_t sink_input_new_hook(pa_core *c,<br>
pa_sink_input_new_data *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_fixate_hook(pa_core *c,<br>
pa_sink_input_new_data *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_put_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_unlink_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_unlink_post_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_move_hook(pa_core *c,<br>
pa_sink_input_move_hook_data *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_move_post(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_name_changed_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
static pa_hook_result_t sink_input_state_changed_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u);<br>
<br>
<br>
<br>
<br>
PA_MODULE_AUTHOR("Nick Thompson") ;<br>
PA_MODULE_DESCRIPTION("Sniffer for sink input hook callbacks") ;<br>
PA_MODULE_VERSION(PACKAGE_VERSION) ;<br>
PA_MODULE_USAGE("Usage TBD" ) ;<br>
<br>
<br>
<br>
<br>
/* entry point for the module*/<br>
int pa__init(pa_module* m)<br>
{<br>
struct userdata *u = NULL;<br>
int i;<br>
<br>
pa_log("> pa__init");<br>
pa_log("this version compiled - %s %s",__DATE__,__TIME__);<br>
<br>
pa_assert(m);<br>
u = pa_xnew(struct userdata, 1);<br>
u->core = m->core;<br>
u->module = m;<br>
m->userdata = u;<br>
<br>
/* install hooks to allow us to maange an internal, to this module,<br>
* list of streams tied back to the originator sink of the stream<br>
* this will be used to implement the policy in place.<br>
*/<br>
u->sink_input_new_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW],<br>
(pa_hook_cb_t)sink_input_new_hook,<br>
u);<br>
<br>
<br>
u->sink_input_fixate_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE],<br>
(pa_hook_cb_t)sink_input_fixate_hook,<br>
u);<br>
<br>
<br>
u->sink_input_put_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT],<br>
(pa_hook_cb_t)sink_input_put_hook,<br>
u);<br>
<br>
<br>
u->sink_input_unlink_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK],<br>
(pa_hook_cb_t)sink_input_unlink_hook,<br>
u);<br>
<br>
<br>
u->sink_input_unlink_post_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST],<br>
(pa_hook_cb_t)sink_input_unlink_post_hook,<br>
u);<br>
<br>
<br>
u->sink_input_move_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE],<br>
(pa_hook_cb_t)sink_input_move_hook,<br>
u);<br>
<br>
<br>
u->sink_input_move_post_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_POST],<br>
(pa_hook_cb_t)sink_input_move_post,<br>
u);<br>
<br>
<br>
u->sink_input_name_changed_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED],<br>
(pa_hook_cb_t)sink_input_name_changed_hook,<br>
u);<br>
<br>
<br>
u->sink_input_state_changed_hook_callback = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED],<br>
(pa_hook_cb_t)sink_input_state_changed_hook,<br>
u);<br>
<br>
<br>
<br>
pa_log("< pa__init");<br>
return 0;<br>
<br>
fail:<br>
pa_log("< pa__init");<br>
return -1;<br>
}<br>
<br>
static pa_hook_result_t sink_input_new_hook(pa_core *c,<br>
pa_sink_input_new_data *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_new_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_fixate_hook(pa_core *c,<br>
pa_sink_input_new_data *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_fixate_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_put_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_put_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_unlink_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_unlink_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_unlink_post_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_unlink_post_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_move_hook(pa_core *c,<br>
pa_sink_input_move_hook_data *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_move_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_move_post(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_move_post");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_name_changed_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_name_changed_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
static pa_hook_result_t sink_input_state_changed_hook(pa_core *c,<br>
pa_sink_input *data,<br>
struct userdata *u){<br>
pa_log("< sink_input_state_changed_hook");<br>
return PA_HOOK_OK;<br>
}<br>
<br>
<br>
<br>
/* exit and cleanup */<br>
void pa__done(pa_module *m) {<br>
struct userdata *u ;<br>
<br>
<br>
pa_log("> pa__done");<br>
pa_assert(m) ;<br>
<br>
if (!(u = m->userdata))<br>
return;<br>
<br>
if(u->sink_input_new_hook_callback )<br>
pa_hook_slot_free(u->sink_input_new_hook_callback) ;<br>
if(u->sink_input_fixate_hook_callback )<br>
pa_hook_slot_free(u->sink_input_fixate_hook_callback) ;<br>
if(u->sink_input_put_hook_callback )<br>
pa_hook_slot_free(u->sink_input_put_hook_callback) ;<br>
if(u->sink_input_unlink_hook_callback )<br>
pa_hook_slot_free(u->sink_input_unlink_hook_callback) ;<br>
if(u->sink_input_unlink_post_hook_callback )<br>
pa_hook_slot_free(u->sink_input_unlink_post_hook_callback) ;<br>
if(u->sink_input_move_hook_callback )<br>
pa_hook_slot_free(u->sink_input_move_hook_callback) ;<br>
if(u->sink_input_move_post_callback )<br>
pa_hook_slot_free(u->sink_input_move_post_callback) ;<br>
if(u->sink_input_name_changed_hook_callback )<br>
pa_hook_slot_free(u->sink_input_name_changed_hook_callback) ;<br>
if(u->sink_input_state_changed_hook_callback )<br>
pa_hook_slot_free(u->sink_input_state_changed_hook_callback) ;<br>
<br>
<br>
pa_xfree(u);<br>
pa_log("< pa__done");<br>
}<br>
<br>
<br>
</span></font>
<!--EndFragment-->
</div></body></html>