36675c3a02cbbb32a4c266c64504a846a24b4d6d
[platform/core/multimedia/pulseaudio-modules-tizen.git] / src / module-tizenaudio-sink2.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <unistd.h>
30
31 #include <pulse/rtclock.h>
32 #include <pulse/timeval.h>
33 #include <pulse/xmalloc.h>
34 #include <pulse/util.h>
35
36 #include <pulsecore/i18n.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/sink.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/modargs.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/thread.h>
44 #include <pulsecore/thread-mq.h>
45 #include <pulsecore/rtpoll.h>
46 #include <pulsecore/poll.h>
47
48 #include "hal-interface.h"
49 #include "echo-cancel/echo-cancel-def.h"
50
51 PA_MODULE_AUTHOR("Tizen");
52 PA_MODULE_DESCRIPTION("Tizen Audio Sink2");
53 PA_MODULE_VERSION(PACKAGE_VERSION);
54 PA_MODULE_LOAD_ONCE(false);
55 PA_MODULE_USAGE(
56         "sink_name=<name of sink> "
57         "sink_properties=<properties for the sink> "
58         "device=<device to use, card comma device (e.g. 0,0)> "
59         "format=<sample format> "
60         "rate=<sample rate> "
61         "channels=<number of channels> "
62         "channel_map=<channel map>"
63         "fragments=<number of fragments> "
64         "fragment_size=<fragment size> ");
65
66 #define DEFAULT_SINK_NAME "tizenaudio-sink2"
67
68 #define DEVICE_NAME_MAX                     30
69 #define DEFAULT_FRAGMENT_MSEC               20
70 #define DEFAULT_FRAGMENTS                    4
71
72 struct userdata {
73     pa_core *core;
74     pa_module *module;
75     pa_sink *sink;
76
77     pa_thread *thread;
78     pa_thread_mq thread_mq;
79     pa_rtpoll *rtpoll;
80     pa_usec_t timestamp;
81
82     void *pcm_handle;
83     uint32_t nfrags;
84     uint32_t frag_size;
85
86     char* card;
87     char* device;
88     bool first;
89     bool echo_on;
90
91     pa_rtpoll_item *rtpoll_item;
92
93     uint64_t write_count;
94     pa_hal_interface *hal_interface;
95
96     pa_msgobject *ec_object;
97     pa_asyncmsgq *ec_asyncmsgq;
98     pa_rtpoll_item *ec_poll_item;
99 };
100
101 static const char* const valid_modargs[] = {
102     "sink_name",
103     "sink_properties",
104     "device",
105     "format",
106     "rate",
107     "channels",
108     "channel_map",
109     "fragments",
110     "fragment_size",
111     NULL
112 };
113
114 static int build_pollfd(struct userdata *u) {
115     int32_t ret;
116     struct pollfd *pollfd;
117     int fd = -1;
118
119     pa_assert(u);
120     pa_assert(u->pcm_handle);
121     pa_assert(u->rtpoll);
122
123     if (u->rtpoll_item)
124         pa_rtpoll_item_free(u->rtpoll_item);
125
126     u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
127     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
128     ret = pa_hal_interface_pcm_get_fd(u->hal_interface, u->pcm_handle, &fd);
129     if (ret < 0 || fd < 0) {
130         pa_log_error("Failed to get fd(%d) of PCM device %d", fd, ret);
131         return -1;
132     }
133     pollfd->fd = fd;
134     pollfd->events = POLLOUT | POLLERR | POLLNVAL;
135
136     return 0;
137 }
138
139 /* Called from IO context */
140 static int suspend(struct userdata *u) {
141     int32_t ret;
142     pa_assert(u);
143     pa_assert(u->pcm_handle);
144
145     ret = pa_hal_interface_pcm_close(u->hal_interface, u->pcm_handle);
146     if (ret) {
147         pa_log_error("Error closing PCM device %x", ret);
148     }
149     u->pcm_handle = NULL;
150
151     if (u->rtpoll_item) {
152         pa_rtpoll_item_free(u->rtpoll_item);
153         u->rtpoll_item = NULL;
154     }
155
156     pa_log_info("Device suspended...");
157
158     return 0;
159 }
160
161 /* Called from IO context */
162 static int unsuspend(struct userdata *u) {
163     pa_sample_spec sample_spec;
164     int32_t ret;
165     size_t frame_size;
166
167     pa_assert(u);
168     pa_assert(!u->pcm_handle);
169
170     pa_log_info("Trying resume...");
171
172     sample_spec = u->sink->sample_spec;
173     frame_size = pa_frame_size(&sample_spec);
174     if (frame_size == 0) {
175         pa_log_error("Unexpected frame size zero!");
176         goto fail;
177     }
178
179     ret = pa_hal_interface_pcm_open(u->hal_interface,
180               u->card,
181               u->device,
182               DIRECTION_OUT,
183               &sample_spec,
184               u->frag_size / frame_size,
185               u->nfrags,
186               (void **)&u->pcm_handle);
187     if (ret) {
188         pa_log_error("Error opening PCM device %x", ret);
189         goto fail;
190     }
191
192     if (build_pollfd(u) < 0)
193         goto fail;
194
195     u->write_count = 0;
196     u->first = true;
197     u->timestamp = pa_rtclock_now();
198
199     pa_log_info("Resumed successfully...");
200
201     return 0;
202
203 fail:
204     if (u->pcm_handle) {
205         pa_hal_interface_pcm_close(u->hal_interface, u->pcm_handle);
206         u->pcm_handle = NULL;
207     }
208     return -PA_ERR_IO;
209 }
210
211 /* Called from the IO thread. */
212 static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
213     struct userdata *u;
214     int r;
215
216     pa_assert(s);
217     pa_assert_se(u = s->userdata);
218
219     /* It may be that only the suspend cause is changing, in which case there's
220      * nothing to do. */
221     if (new_state == s->thread_info.state)
222         return 0;
223
224     switch (new_state) {
225         case PA_SINK_SUSPENDED: {
226             pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
227             if ((r = suspend(u)) < 0)
228                 return r;
229             break;
230         }
231
232         case PA_SINK_IDLE:
233         case PA_SINK_RUNNING: {
234             if (s->thread_info.state == PA_SINK_INIT) {
235                 if (build_pollfd(u) < 0)
236                     return -PA_ERR_IO;
237             }
238
239             if (s->thread_info.state == PA_SINK_SUSPENDED) {
240                 if ((r = unsuspend(u)) < 0)
241                     return r;
242             }
243             break;
244         }
245
246         case PA_SINK_UNLINKED:
247         case PA_SINK_INIT:
248         case PA_SINK_INVALID_STATE:
249             break;
250     }
251
252     return 0;
253 }
254
255 static int sink_process_msg(
256         pa_msgobject *o,
257         int code,
258         void *data,
259         int64_t offset,
260         pa_memchunk *chunk) {
261
262     struct userdata *u = PA_SINK(o)->userdata;
263
264     switch (code) {
265         case PA_SINK_MESSAGE_SET_AEC_STATE: {
266             u->echo_on = !!data;
267             pa_log_info("EC state changed (%d)", u->echo_on);
268             return 0;
269         }
270         case PA_SINK_MESSAGE_GET_LATENCY: {
271             int64_t r = 0;
272
273             if (u->pcm_handle)
274                 r = u->timestamp + pa_bytes_to_usec(u->write_count, &u->sink->sample_spec) - pa_rtclock_now();
275
276             *((int64_t *) data) = r;
277
278             return 0;
279         }
280         case PA_SINK_MESSAGE_REBUILD_RTPOLL: {
281             struct arguments {
282                 pa_msgobject *o;
283                 pa_asyncmsgq *q;
284             } *args;
285
286             args = (struct arguments *)data;
287
288             if (args) {
289                 u->ec_object = args->o;
290                 u->ec_asyncmsgq = args->q;
291                 u->ec_poll_item = pa_rtpoll_item_new_asyncmsgq_write(u->rtpoll, PA_RTPOLL_EARLY, args->q);
292             } else {
293                 pa_rtpoll_item_free(u->ec_poll_item);
294                 u->ec_poll_item = NULL;
295                 u->ec_object = NULL;
296             }
297
298             return 0;
299         }
300     }
301
302     return pa_sink_process_msg(o, code, data, offset, chunk);
303 }
304
305 static void process_rewind(struct userdata *u) {
306 #if 1
307     /* Rewind not supported */
308     pa_sink_process_rewind(u->sink, 0);
309 #else
310     size_t rewind_nbytes, in_buffer;
311     pa_usec_t delay;
312
313     pa_assert(u);
314
315     rewind_nbytes = u->sink->thread_info.rewind_nbytes;
316
317     if (!PA_SINK_IS_OPENED(u->sink->thread_info.state) || rewind_nbytes <= 0)
318         goto do_nothing;
319
320     pa_log_debug("Requested to rewind %lu bytes.", (unsigned long)rewind_nbytes);
321
322     if (u->timestamp <= now)
323         goto do_nothing;
324
325     delay = u->timestamp - now;
326     in_buffer = pa_usec_to_bytes(delay, &u->sink->sample_spec);
327
328     if (in_buffer <= 0)
329         goto do_nothing;
330
331     if (rewind_nbytes > in_buffer)
332         rewind_nbytes = in_buffer;
333
334     pa_sink_process_rewind(u->sink, rewind_nbytes);
335     u->timestamp -= pa_bytes_to_usec(rewind_nbytes, &u->sink->sample_spec);
336
337     pa_log_debug("Rewound %lu bytes.", (unsigned long)rewind_nbytes);
338     return;
339
340 do_nothing:
341     pa_sink_process_rewind(u->sink, 0);
342 #endif
343 }
344
345 static int process_render(struct userdata *u) {
346     void *p;
347     size_t frame_size = pa_frame_size(&u->sink->sample_spec);
348     size_t frames_to_write = u->frag_size / frame_size;
349     uint32_t avail = 0;
350     pa_memchunk chunk;
351
352     pa_assert(u);
353
354     pa_hal_interface_pcm_available(u->hal_interface, u->pcm_handle, &avail);
355
356     if (frames_to_write > avail)
357         return 0;
358
359     pa_sink_render_full(u->sink, u->frag_size, &chunk);
360     p = pa_memblock_acquire(chunk.memblock);
361
362     if (pa_hal_interface_pcm_write(u->hal_interface, u->pcm_handle, (const char*)p + chunk.index, (uint32_t)frames_to_write)) {
363         pa_log_error("failed to write pcm. p(%p), size(%zu)", p, frames_to_write);
364         return -1;
365     }
366
367     pa_memblock_release(chunk.memblock);
368
369     if (u->echo_on) {
370         pa_asyncmsgq_post(u->ec_asyncmsgq, u->ec_object,
371                             PA_ECHO_CANCEL_MESSAGE_PUSH_ECHO, NULL, 0, &chunk, NULL);
372     }
373
374     pa_memblock_unref(chunk.memblock);
375
376     u->write_count += chunk.length;
377
378     return 0;
379 }
380
381 static void thread_func(void *userdata) {
382     struct userdata *u = userdata;
383     unsigned short revents = 0;
384
385     pa_assert(u);
386
387     pa_log_debug("Thread starting up");
388
389     if (u->core->realtime_scheduling)
390         pa_thread_make_realtime(u->core->realtime_priority);
391
392     pa_thread_mq_install(&u->thread_mq);
393
394     u->timestamp = pa_rtclock_now();
395
396     for (;;) {
397         int ret;
398
399         if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
400             process_rewind(u);
401
402         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
403             if (process_render(u))
404                 goto fail;
405
406             if (u->first) {
407                 pa_log_info("Starting playback.");
408                 pa_hal_interface_pcm_start(u->hal_interface, u->pcm_handle);
409                 u->first = false;
410             }
411         }
412
413         /* Hmm, nothing to do. Let's sleep */
414         if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
415             goto fail;
416
417         if (ret == 0)
418             goto finish;
419
420         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
421             struct pollfd *pollfd;
422             if (u->rtpoll_item) {
423                 pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
424                 revents = pollfd->revents;
425                 if (revents & ~POLLOUT) {
426                     pa_log_debug("Poll error 0x%x occured, try recover.", revents);
427                     pa_hal_interface_pcm_recover(u->hal_interface, u->pcm_handle, revents);
428                     u->first = true;
429                     revents = 0;
430                 }
431             }
432         }
433     }
434
435 fail:
436     pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
437     pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
438
439 finish:
440     pa_log_debug("Thread shutting down");
441 }
442
443 static int parse_to_get_card(const char *modarg_device, char *card) {
444     const char *name_p;
445     char *card_p;
446
447     if (!strchr(modarg_device, ',')) {
448         pa_log_error("Failed to parse device argument : no comma");
449         return -1;
450     }
451
452     name_p = modarg_device;
453     card_p = card;
454     while (*name_p != ',')
455         *(card_p++) = *(name_p++);
456     *card_p = '\0';
457
458     return 0;
459 }
460
461 static int parse_to_get_device(const char *modarg_device, char *device) {
462     const char *comma_p;
463     char *device_p;
464
465     if (!(comma_p = strchr(modarg_device, ','))) {
466         pa_log_error("Failed to parse device argument : no comma");
467         return -1;
468     }
469
470     comma_p++;
471     device_p = device;
472     while (*comma_p != '\0')
473         *(device_p++) = *(comma_p++);
474     *device_p = '\0';
475
476     return 0;
477 }
478
479 int pa__init(pa_module*m) {
480     struct userdata *u = NULL;
481     pa_sample_spec ss;
482     pa_channel_map map;
483     pa_modargs *ma = NULL;
484     pa_sink_new_data data;
485     uint32_t alternate_sample_rate;
486     const char *modarg_device;
487     char card[DEVICE_NAME_MAX];
488     char device[DEVICE_NAME_MAX];
489     size_t frame_size, buffer_size, period_frames, buffer_frames;
490
491     pa_assert(m);
492
493     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
494         pa_log_error("Failed to parse module arguments.");
495         goto fail;
496     }
497
498     ss = m->core->default_sample_spec;
499     map = m->core->default_channel_map;
500     if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
501         pa_log_error("Invalid sample format specification or channel map");
502         goto fail;
503     }
504
505     alternate_sample_rate = m->core->alternate_sample_rate;
506     if (pa_modargs_get_alternate_sample_rate(ma, &alternate_sample_rate) < 0) {
507         pa_log_error("Failed to parse alternate sample rate");
508         goto fail;
509     }
510
511     m->userdata = u = pa_xnew0(struct userdata, 1);
512     u->core = m->core;
513     u->module = m;
514     u->first = true;
515     u->timestamp = 0ULL;
516     u->hal_interface = pa_hal_interface_get(u->core);
517     u->rtpoll = pa_rtpoll_new();
518     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
519
520     if (!(modarg_device = pa_modargs_get_value(ma, "device", NULL))) {
521         pa_log_error("device is invalid");
522         goto fail;
523     }
524
525     if (parse_to_get_card(modarg_device, card) || parse_to_get_device(modarg_device, device)) {
526         pa_log_error("failed to parse device module argument, %s", modarg_device);
527         goto fail;
528     }
529
530     u->card = pa_xstrdup(card);
531     u->device = pa_xstrdup(device);
532
533     u->frag_size = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGMENT_MSEC * PA_USEC_PER_MSEC, &ss);
534     u->nfrags = DEFAULT_FRAGMENTS;
535     if (pa_modargs_get_value_u32(ma, "fragment_size", &u->frag_size) < 0 ||
536         pa_modargs_get_value_u32(ma, "fragments", &u->nfrags) < 0) {
537         pa_log_error("fragment_size or fragments are invalid.");
538         goto fail;
539     }
540     pa_log_info("card(%s) device(%s) fragment_size(%u), fragments(%u)", u->card, u->device, u->frag_size, u->nfrags);
541
542     pa_sink_new_data_init(&data);
543     data.driver = __FILE__;
544     data.module = m;
545     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
546     pa_sink_new_data_set_sample_spec(&data, &ss);
547     pa_sink_new_data_set_channel_map(&data, &map);
548     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Tizen audio sink"));
549     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract");
550     pa_proplist_sets(data.proplist, "tizen.card", u->card);
551     pa_proplist_sets(data.proplist, "tizen.device", u->device);
552     pa_proplist_sets(data.proplist, "tizen.version", "2");
553     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "tizen");
554
555     frame_size = pa_frame_size(&ss);
556     buffer_size = u->frag_size * u->nfrags;
557     buffer_frames = buffer_size / frame_size;
558     period_frames = u->frag_size / frame_size;
559     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%zu", buffer_frames * frame_size);
560     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%zu", period_frames * frame_size);
561
562     if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
563         pa_log_error("Invalid properties.");
564         pa_sink_new_data_done(&data);
565         goto fail;
566     }
567
568     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
569     pa_sink_new_data_done(&data);
570
571     if (!u->sink) {
572         pa_log_error("Failed to create sink object.");
573         goto fail;
574     }
575
576     u->sink->parent.process_msg = sink_process_msg;
577     u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb;
578     u->sink->userdata = u;
579
580     if (pa_hal_interface_pcm_open(u->hal_interface,
581               u->card,
582               u->device,
583               DIRECTION_OUT,
584               &u->sink->sample_spec,
585               u->frag_size / pa_frame_size(&u->sink->sample_spec),
586               u->nfrags,
587               (void **)&u->pcm_handle)) {
588         pa_log_error("Error opening PCM device");
589         goto fail;
590     }
591
592     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
593     pa_sink_set_rtpoll(u->sink, u->rtpoll);
594
595     pa_sink_set_max_request(u->sink, buffer_size);
596     pa_sink_set_max_rewind(u->sink, buffer_size);
597
598     if (!(u->thread = pa_thread_new("tizenaudio-sink2", thread_func, u))) {
599         pa_log_error("Failed to create thread.");
600         goto fail;
601     }
602     pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(buffer_size, &ss));
603     pa_sink_put(u->sink);
604     pa_modargs_free(ma);
605
606     return 0;
607
608 fail:
609     if (ma)
610         pa_modargs_free(ma);
611
612     pa__done(m);
613     return -1;
614 }
615
616 int pa__get_n_used(pa_module *m) {
617     struct userdata *u;
618
619     pa_assert(m);
620     pa_assert_se((u = m->userdata));
621
622     return pa_sink_linked_by(u->sink);
623 }
624
625 void pa__done(pa_module*m) {
626     struct userdata *u;
627
628     pa_assert(m);
629
630     if (!(u = m->userdata))
631         return;
632
633     if (u->sink)
634         pa_sink_unlink(u->sink);
635
636     if (u->thread) {
637         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
638         pa_thread_free(u->thread);
639     }
640
641     pa_thread_mq_done(&u->thread_mq);
642
643     if (u->sink)
644         pa_sink_unref(u->sink);
645
646     pa_xfree(u->card);
647     pa_xfree(u->device);
648
649     if (u->rtpoll)
650         pa_rtpoll_free(u->rtpoll);
651
652     if (u->pcm_handle) {
653         pa_hal_interface_pcm_stop(u->hal_interface, u->pcm_handle);
654         pa_hal_interface_pcm_close(u->hal_interface, u->pcm_handle);
655     }
656
657     if (u->hal_interface)
658         pa_hal_interface_unref(u->hal_interface);
659
660     pa_xfree(u);
661 }