]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/source-output.c
add makefiles to speex/ and ffmpeg/ to easy compilation from emacs
[pulseaudio] / src / pulsecore / source-output.c
index c3ecf3a2bb7f5820dccba8e9d7de093995b1515a..253224695220b869979b220178514c15f2e40d82 100644 (file)
@@ -76,9 +76,8 @@ pa_source_output* pa_source_output_new(
     pa_assert(core);
     pa_assert(data);
 
-    if (!(flags & PA_SOURCE_OUTPUT_NO_HOOKS))
-        if (pa_hook_fire(&core->hook_source_output_new, data) < 0)
-            return NULL;
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data) < 0)
+        return NULL;
 
     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
     pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name));
@@ -122,7 +121,8 @@ pa_source_output* pa_source_output_new(
                       core->mempool,
                       &data->source->sample_spec, &data->source->channel_map,
                       &data->sample_spec, &data->channel_map,
-                      data->resample_method))) {
+                      data->resample_method,
+                      !!(flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) {
             pa_log_warn("Unsupported resampling operation.");
             return NULL;
         }
@@ -135,7 +135,7 @@ pa_source_output* pa_source_output_new(
     o->parent.process_msg = pa_source_output_process_msg;
 
     o->core = core;
-    o->state = data->corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+    o->state = data->start_corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
@@ -187,21 +187,26 @@ void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
     pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT], o);
+    
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     pa_idxset_remove_by_data(o->source->outputs, o, NULL);
-    pa_source_output_unref(o);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
 
     source_output_set_state(o, PA_SOURCE_OUTPUT_DISCONNECTED);
     pa_source_update_status(o->source);
 
-    o->source = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], o);
+
+    o->source = NULL;
+    pa_source_output_unref(o);
 }
 
 static void source_output_free(pa_object* mo) {
@@ -225,10 +230,12 @@ static void source_output_free(pa_object* mo) {
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, pa_source_output_ref(o), 0, NULL, (pa_free_cb_t) pa_source_output_unref);
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
     pa_source_update_status(o->source);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
+
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
@@ -252,6 +259,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
     return r;
 }
 
+/* Called from thread context */
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
@@ -321,65 +329,78 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
 }
 
 int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
-/*     pa_source *origin; */
-/*     pa_resampler *new_resampler = NULL; */
+    pa_source *origin;
+    pa_resampler *new_resampler = NULL;
 
     pa_source_output_assert_ref(o);
     pa_source_assert_ref(dest);
+    
+    origin = o->source;
 
-    return -1;
+    if (dest == origin)
+        return 0;
 
-/*     origin = o->source; */
+    if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
+        pa_log_warn("Failed to move source output: too many outputs per source.");
+        return -1;
+    }
 
-/*     if (dest == origin) */
-/*         return 0; */
+    if (o->thread_info.resampler &&
+        pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
+        pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
 
-/*     if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { */
-/*         pa_log_warn("Failed to move source output: too many outputs per source."); */
-/*         return -1; */
-/*     } */
+        /* Try to reuse the old resampler if possible */
+        new_resampler = o->thread_info.resampler;
 
-/*     if (o->resampler && */
-/*         pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && */
-/*         pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) */
+    else if ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ||
+             !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
+             !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {
 
-/*         /\* Try to reuse the old resampler if possible *\/ */
-/*         new_resampler = o->resampler; */
+        /* Okey, we need a new resampler for the new source */
 
-/*     else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || */
-/*         !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { */
+        if (!(new_resampler = pa_resampler_new(
+                      dest->core->mempool,
+                      &dest->sample_spec, &dest->channel_map,
+                      &o->sample_spec, &o->channel_map,
+                      o->resample_method,
+                      !!(o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) {
+            pa_log_warn("Unsupported resampling operation.");
+            return -1;
+        }
+    }
 
-/*         /\* Okey, we need a new resampler for the new source *\/ */
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], o);
 
-/*         if (!(new_resampler = pa_resampler_new( */
-/*                       dest->core->mempool, */
-/*                       &dest->sample_spec, &dest->channel_map, */
-/*                       &o->sample_spec, &o->channel_map, */
-/*                       o->resample_method))) { */
-/*             pa_log_warn("Unsupported resampling operation."); */
-/*             return -1; */
-/*         } */
-/*     } */
+    /* Okey, let's move it */
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+    
+    pa_idxset_remove_by_data(origin->outputs, o, NULL);
+    pa_idxset_put(dest->outputs, o, NULL);
+    o->source = dest;
+
+    /* Replace resampler */
+    if (new_resampler != o->thread_info.resampler) {
+        if (o->thread_info.resampler)
+            pa_resampler_free(o->thread_info.resampler);
+        o->thread_info.resampler = new_resampler;
+    }
+
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
 
-/*     /\* Okey, let's move it *\/ */
-/*     pa_idxset_remove_by_data(origin->outputs, o, NULL); */
-/*     pa_idxset_put(dest->outputs, o, NULL); */
-/*     o->source = dest; */
+    pa_source_update_status(origin);
+    pa_source_update_status(dest);
 
-/*     /\* Replace resampler *\/ */
-/*     if (new_resampler != o->resampler) { */
-/*         if (o->resampler) */
-/*             pa_resampler_free(o->resampler); */
-/*         o->resampler = new_resampler; */
-/*     } */
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o);
 
-/*     /\* Notify everyone *\/ */
-/*     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); */
-/*     pa_source_notify(o->source); */
+    pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name);
 
-/*     return 0; */
+    /* Notify everyone */
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+
+    return 0;
 }
 
+/* Called from thread context */
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk* chunk) {
     pa_source_output *o = PA_SOURCE_OUTPUT(mo);