├── MODULE_LICENSE_BSD ├── METADATA ├── OWNERS ├── README ├── Android.bp ├── compress_ops.h ├── CleanSpec.mk ├── snd_utils.h ├── include └── tinycompress │ ├── version.h │ ├── compress_plugin.h │ ├── tinymp3.h │ └── tinycompress.h ├── utils.c ├── compress_hw.c ├── snd_utils.c ├── cplay.c ├── NOTICE ├── compress_plugin.c └── compress.c /MODULE_LICENSE_BSD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /METADATA: -------------------------------------------------------------------------------- 1 | third_party { 2 | license_type: NOTICE 3 | } 4 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | cferris@google.com 2 | dvdli@google.com 3 | elaurent@google.com 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README for tinycompress 2 | ======================= 3 | vinod.koul@linux.intel.com 4 | ========================== 5 | 6 | 1. WHAT 7 | tinycompress is a userspace library for anyone who wants to use the ALSA 8 | compressed APIs introduced in Linux 3.3 9 | This library provides the APIs to open a ALSA compressed device and read/write 10 | compressed data like MP3 etc to it. 11 | 12 | This also includes a utility command line player (cplay) which demonstrates 13 | the usage of this API. Currently this contains support for playing the mp3 format 14 | 15 | 2. WHERE 16 | The library can found in alsa-project.org 17 | Git: git clone git://git.alsa-project.org/tinycompress.git 18 | Http: http://git.alsa-project.org/?p=tinycompress.git 19 | 20 | 3. PATCHES 21 | Please send any enhancements/fixes to alsa developer mailing list at: 22 | alsa-devel@alsa-project.org. 23 | 24 | 4. LICENSE 25 | tinycompress is provided under LGPL and BSD dual license 26 | 27 | 5. CREDITS 28 | - Pierre-Louis Bossart for library design 29 | - Navjot Singh for writing the mp3 parser code 30 | 31 | -------------------------------------------------------------------------------- /Android.bp: -------------------------------------------------------------------------------- 1 | package { 2 | default_applicable_licenses: ["external_tinycompress_license"], 3 | } 4 | 5 | // Added automatically by a large-scale-change 6 | // 7 | // large-scale-change filtered out the below license kinds as false-positives: 8 | // SPDX-license-identifier-LGPL 9 | // SPDX-license-identifier-LGPL-2.1 10 | // See: http://go/android-license-faq 11 | license { 12 | name: "external_tinycompress_license", 13 | visibility: [":__subpackages__"], 14 | license_kinds: [ 15 | "SPDX-license-identifier-BSD", 16 | ], 17 | license_text: [ 18 | "NOTICE", 19 | ], 20 | } 21 | 22 | cc_library_shared { 23 | name: "libtinycompress", 24 | defaults: ["extended_compress_format_defaults"], 25 | vendor: true, 26 | 27 | cflags: [ 28 | "-Wall", 29 | "-Werror", 30 | "-Wno-macro-redefined", 31 | "-Wno-unused-function", 32 | ], 33 | export_include_dirs: ["include"], 34 | srcs: [ 35 | "compress.c", 36 | "utils.c", 37 | "compress_hw.c", 38 | "compress_plugin.c", 39 | "snd_utils.c", 40 | ], 41 | shared_libs: [ 42 | "libcutils", 43 | "libutils", 44 | ], 45 | header_libs: [ 46 | "generated_kernel_headers", 47 | ], 48 | } 49 | 50 | cc_binary { 51 | name: "cplay", 52 | vendor: true, 53 | 54 | cflags: [ 55 | "-Wall", 56 | "-Werror", 57 | "-Wno-macro-redefined" 58 | ], 59 | local_include_dirs: ["include"], 60 | srcs: ["cplay.c"], 61 | shared_libs: [ 62 | "libcutils", 63 | "libutils", 64 | "libtinycompress", 65 | ], 66 | } 67 | -------------------------------------------------------------------------------- /compress_ops.h: -------------------------------------------------------------------------------- 1 | /* compress.h 2 | ** 3 | ** Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #ifndef __COMPRESS_H__ 32 | #define __COMPRESS_H__ 33 | 34 | #include 35 | 36 | #include "sound/compress_params.h" 37 | #include "sound/compress_offload.h" 38 | 39 | struct compress_ops { 40 | int (*open) (unsigned int card, unsigned int device, 41 | unsigned int flags, void **data, void *node); 42 | void (*close) (void *data); 43 | int (*ioctl) (void *data, unsigned int cmd, ...); 44 | int (*read) (void *data, void *buf, size_t size); 45 | int (*write) (void *data, const void *buf, size_t size); 46 | int (*poll) (void *data, struct pollfd *fds, nfds_t nfds, 47 | int timeout); 48 | }; 49 | 50 | #endif /* end of __PCM_H__ */ 51 | -------------------------------------------------------------------------------- /CleanSpec.mk: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | 16 | # If you don't need to do a full clean build but would like to touch 17 | # a file or delete some intermediate files, add a clean step to the end 18 | # of the list. These steps will only be run once, if they haven't been 19 | # run before. 20 | # 21 | # E.g.: 22 | # $(call add-clean-step, touch -c external/sqlite/sqlite3.h) 23 | # $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) 24 | # 25 | # Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with 26 | # files that are missing or have been moved. 27 | # 28 | # Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. 29 | # Use $(OUT_DIR) to refer to the "out" directory. 30 | # 31 | # If you need to re-do something that's already mentioned, just copy 32 | # the command and add it to the bottom of the list. E.g., if a change 33 | # that you made last week required touching a file and a change you 34 | # made today requires touching the same file, just copy the old 35 | # touch step and add it to the end of the list. 36 | # 37 | # ************************************************ 38 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 39 | # ************************************************ 40 | 41 | # For example: 42 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) 43 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) 44 | #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) 45 | #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) 46 | 47 | $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/cplay) 48 | 49 | # ************************************************ 50 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST 51 | # ************************************************ 52 | -------------------------------------------------------------------------------- /snd_utils.h: -------------------------------------------------------------------------------- 1 | /* snd_utils.h 2 | ** 3 | ** Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #ifndef __SND_CARD_UTILS_H__ 32 | #define __SND_CARD_UTILS_H__ 33 | 34 | #include 35 | 36 | struct snd_node { 37 | void *card_node; 38 | void *dev_node; 39 | void *dl_hdl; 40 | 41 | void* (*get_card) (unsigned int card); 42 | void (*put_card) (void *card); 43 | void* (*get_node) (void *card, unsigned int id, 44 | int type); 45 | int (*get_int) (void *node, const char *prop, int *val); 46 | int (*get_str) (void *node, const char *prop, char **val); 47 | }; 48 | 49 | enum { 50 | NODE_PCM, 51 | NODE_MIXER, 52 | NODE_COMPRESS, 53 | }; 54 | 55 | enum snd_node_type { 56 | SND_NODE_TYPE_HW = 0, 57 | SND_NODE_TYPE_PLUGIN, 58 | SND_NODE_TYPE_INVALID, 59 | }; 60 | 61 | struct snd_node *snd_utils_get_dev_node(unsigned int card, 62 | unsigned int device, int dev_type); 63 | 64 | void snd_utils_put_dev_node(struct snd_node *node); 65 | 66 | enum snd_node_type snd_utils_get_node_type(struct snd_node *node); 67 | 68 | int snd_utils_get_int(struct snd_node *node, const char *prop, int *val); 69 | 70 | int snd_utils_get_str(struct snd_node *node, const char *prop, char **val); 71 | 72 | #endif /* end of __SND_CARD_UTILS_H__ */ 73 | -------------------------------------------------------------------------------- /include/tinycompress/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * Copyright (c) 2011-2012, Intel Corporation 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * Neither the name of Intel Corporation nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * LGPL LICENSE 32 | * 33 | * tinycompress library for compress audio offload in alsa 34 | * Copyright (c) 2011-2012, Intel Corporation. 35 | * 36 | * 37 | * This program is free software; you can redistribute it and/or modify it 38 | * under the terms and conditions of the GNU Lesser General Public License, 39 | * version 2.1, as published by the Free Software Foundation. 40 | * 41 | * This program is distributed in the hope it will be useful, but WITHOUT 42 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 43 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 44 | * License for more details. 45 | * 46 | * You should have received a copy of the GNU Lesser General Public License 47 | * along with this program; if not, write to 48 | * the Free Software Foundation, Inc., 49 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 50 | */ 51 | 52 | 53 | #ifndef __VERSION_H 54 | #define __VERSION_H 55 | 56 | 57 | #define TINYCOMPRESS_LIB_MAJOR 0 /* major number of library version */ 58 | #define TINYCOMPRESS_LIB_MINOR 2 /* minor number of library version */ 59 | #define TINYCOMPRESS_LIB_SUBMINOR 0 /* subminor number of library version */ 60 | 61 | /** library version */ 62 | #define TINYCOMPRESS_LIB_VERSION \ 63 | ((TINYCOMPRESS_LIB_MAJOR<<16)|\ 64 | (TINYCOMPRESS_LIB_MINOR<<8)|\ 65 | TINYCOMPRESS_LIB_SUBMINOR) 66 | 67 | /** library version (string) */ 68 | #define TINYCOMPRESS_LIB_VERSION_STR "0.2.0" 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * tinycompress utility functions 5 | * Copyright (c) 2011-2013, Intel Corporation 6 | * All rights reserved. 7 | * 8 | * Author: Vinod Koul 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * Neither the name of Intel Corporation nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 | * THE POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | * LGPL LICENSE 35 | * 36 | * tinycompress utility functions 37 | * Copyright (c) 2011-2013, Intel Corporation 38 | * 39 | * This program is free software; you can redistribute it and/or modify it 40 | * under the terms and conditions of the GNU Lesser General Public License, 41 | * version 2.1, as published by the Free Software Foundation. 42 | * 43 | * This program is distributed in the hope it will be useful, but WITHOUT 44 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 45 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 46 | * License for more details. 47 | * 48 | * You should have received a copy of the GNU Lesser General Public License 49 | * along with this program; if not, write to 50 | * the Free Software Foundation, Inc., 51 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 52 | */ 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #define __force 59 | #define __bitwise 60 | #define __user 61 | #include "tinycompress/tinycompress.h" 62 | 63 | 64 | unsigned int compress_get_alsa_rate(unsigned int rate) 65 | { 66 | switch (rate) { 67 | case 5512: 68 | return SNDRV_PCM_RATE_5512; 69 | case 8000: 70 | return SNDRV_PCM_RATE_8000; 71 | case 11025: 72 | return SNDRV_PCM_RATE_11025; 73 | case 16000: 74 | return SNDRV_PCM_RATE_16000; 75 | case 22050: 76 | return SNDRV_PCM_RATE_22050; 77 | case 32000: 78 | return SNDRV_PCM_RATE_32000; 79 | case 44100: 80 | return SNDRV_PCM_RATE_44100; 81 | case 48000: 82 | return SNDRV_PCM_RATE_48000; 83 | case 64000: 84 | return SNDRV_PCM_RATE_64000; 85 | case 88200: 86 | return SNDRV_PCM_RATE_88200; 87 | case 96000: 88 | return SNDRV_PCM_RATE_96000; 89 | case 176400: 90 | return SNDRV_PCM_RATE_176400; 91 | case 192000: 92 | return SNDRV_PCM_RATE_192000; 93 | default: 94 | return 0; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /include/tinycompress/compress_plugin.h: -------------------------------------------------------------------------------- 1 | /* compress_plugin.h 2 | ** 3 | ** Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #ifndef __COMPRESS_PLUGIN_H__ 32 | #define __COMPRESS_PLUGIN_H__ 33 | 34 | #include "sound/compress_params.h" 35 | #include "sound/compress_offload.h" 36 | 37 | #define COMPRESS_PLUGIN_OPEN_FN(name) \ 38 | int name##_open(struct compress_plugin **plugin, \ 39 | unsigned int card, \ 40 | unsigned int device, \ 41 | unsigned int flags) 42 | 43 | #define COMPRESS_PLUGIN_OPEN_FN_PTR() \ 44 | int (*plugin_open_fn) (struct compress_plugin **plugin, \ 45 | unsigned int card, \ 46 | unsigned int device, \ 47 | unsigned int flags); 48 | 49 | struct compress_plugin; 50 | 51 | struct compress_plugin_ops { 52 | void (*close) (struct compress_plugin *plugin); 53 | int (*get_caps) (struct compress_plugin *plugin, 54 | struct snd_compr_caps *caps); 55 | int (*set_params) (struct compress_plugin *plugin, 56 | struct snd_compr_params *params); 57 | int (*avail) (struct compress_plugin *plugin, 58 | struct snd_compr_avail *avail); 59 | int (*tstamp) (struct compress_plugin *plugin, 60 | struct snd_compr_tstamp *tstamp); 61 | int (*write) (struct compress_plugin *plugin, 62 | const void *buf, size_t size); 63 | int (*read) (struct compress_plugin *plugin, 64 | void *buf, size_t size); 65 | int (*start) (struct compress_plugin *plugin); 66 | int (*stop) (struct compress_plugin *plugin); 67 | int (*pause) (struct compress_plugin *plugin); 68 | int (*resume) (struct compress_plugin *plugin); 69 | int (*drain) (struct compress_plugin *plugin); 70 | int (*partial_drain) (struct compress_plugin *plugin); 71 | int (*next_track) (struct compress_plugin *plugin); 72 | int (*ioctl) (struct compress_plugin *plugin, int cmd, ...); 73 | int (*poll) (struct compress_plugin *plugin, 74 | struct pollfd *fds, nfds_t nfds, int timeout); 75 | }; 76 | 77 | struct compress_plugin { 78 | unsigned int card; 79 | 80 | struct compress_plugin_ops *ops; 81 | 82 | void *node; 83 | int mode; 84 | void *priv; 85 | 86 | unsigned int state; 87 | }; 88 | 89 | #endif /* end of __COMPRESS_PLUGIN_H__ */ 90 | -------------------------------------------------------------------------------- /compress_hw.c: -------------------------------------------------------------------------------- 1 | /* compress_hw.c 2 | ** 3 | ** Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | #include 44 | #include "tinycompress/tinycompress.h" 45 | #include "compress_ops.h" 46 | 47 | struct compress_hw_data { 48 | unsigned int card; 49 | unsigned int device; 50 | unsigned int fd; 51 | }; 52 | 53 | static int compress_hw_poll(void *data, struct pollfd *fds, 54 | nfds_t nfds, int timeout) 55 | { 56 | struct compress_hw_data *hw_data = data; 57 | 58 | fds->fd = hw_data->fd; 59 | return poll(fds, nfds, timeout); 60 | } 61 | 62 | static int compress_hw_write(void *data, const void *buf, size_t size) 63 | { 64 | struct compress_hw_data *hw_data = data; 65 | 66 | return write(hw_data->fd, buf, size); 67 | } 68 | 69 | static int compress_hw_read(void *data, void *buf, size_t size) 70 | { 71 | struct compress_hw_data *hw_data = data; 72 | 73 | return read(hw_data->fd, buf, size); 74 | } 75 | 76 | static int compress_hw_ioctl(void *data, unsigned int cmd, ...) 77 | { 78 | struct compress_hw_data *hw_data = data; 79 | va_list ap; 80 | void *arg; 81 | 82 | va_start(ap, cmd); 83 | arg = va_arg(ap, void *); 84 | va_end(ap); 85 | 86 | return ioctl(hw_data->fd, cmd, arg); 87 | } 88 | 89 | static void compress_hw_close(void *data) 90 | { 91 | struct compress_hw_data *hw_data = data; 92 | 93 | if (hw_data->fd > 0) 94 | close(hw_data->fd); 95 | 96 | free(hw_data); 97 | } 98 | 99 | static int compress_hw_open(unsigned int card, unsigned int device, 100 | unsigned int flags, void **data, __unused void *node) 101 | { 102 | struct compress_hw_data *hw_data; 103 | char fn[256]; 104 | int fd; 105 | 106 | hw_data = calloc(1, sizeof(*hw_data)); 107 | if (!hw_data) { 108 | return -ENOMEM; 109 | } 110 | 111 | snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card, device); 112 | 113 | if (flags & COMPRESS_OUT) 114 | fd = open(fn, O_RDONLY); 115 | else 116 | fd = open(fn, O_WRONLY); 117 | 118 | if (fd < 0) { 119 | return fd; 120 | } 121 | 122 | hw_data->card = card; 123 | hw_data->device = device; 124 | hw_data->fd = fd; 125 | 126 | *data = hw_data; 127 | 128 | return fd; 129 | } 130 | 131 | struct compress_ops compr_hw_ops = { 132 | .open = compress_hw_open, 133 | .close = compress_hw_close, 134 | .ioctl = compress_hw_ioctl, 135 | .read = compress_hw_read, 136 | .write = compress_hw_write, 137 | .poll = compress_hw_poll, 138 | }; 139 | -------------------------------------------------------------------------------- /include/tinycompress/tinymp3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * mp3 header and prasing 5 | * Copyright (c) 2011-2012, Intel Corporation 6 | * All rights reserved. 7 | * 8 | * Author: Vinod Koul 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * Neither the name of Intel Corporation nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 | * THE POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | * LGPL LICENSE 35 | * 36 | * mp3 header and parsing 37 | * Copyright (c) 2011-2012, Intel Corporation. 38 | * 39 | * 40 | * This program is free software; you can redistribute it and/or modify it 41 | * under the terms and conditions of the GNU Lesser General Public License, 42 | * version 2.1, as published by the Free Software Foundation. 43 | * 44 | * This program is distributed in the hope it will be useful, but WITHOUT 45 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 46 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 47 | * License for more details. 48 | * 49 | * You should have received a copy of the GNU Lesser General Public License 50 | * along with this program; if not, write to 51 | * the Free Software Foundation, Inc., 52 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 53 | */ 54 | 55 | 56 | #ifndef __TINYMP3_H 57 | #define __TINYMP3_H 58 | 59 | #if defined(__cplusplus) 60 | extern "C" { 61 | #endif 62 | 63 | 64 | #define MP3_SYNC 0xe0ff 65 | 66 | const int mp3_sample_rates[3][3] = { 67 | {44100, 48000, 32000}, /* MPEG-1 */ 68 | {22050, 24000, 16000}, /* MPEG-2 */ 69 | {11025, 12000, 8000}, /* MPEG-2.5 */ 70 | }; 71 | 72 | const int mp3_bit_rates[3][3][15] = { 73 | { 74 | /* MPEG-1 */ 75 | { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448}, /* Layer 1 */ 76 | { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384}, /* Layer 2 */ 77 | { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}, /* Layer 3 */ 78 | }, 79 | { 80 | /* MPEG-2 */ 81 | { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, /* Layer 1 */ 82 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, /* Layer 2 */ 83 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, /* Layer 3 */ 84 | }, 85 | { 86 | /* MPEG-2.5 */ 87 | { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, /* Layer 1 */ 88 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, /* Layer 2 */ 89 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, /* Layer 3 */ 90 | }, 91 | }; 92 | 93 | enum mpeg_version { 94 | MPEG1 = 0, 95 | MPEG2 = 1, 96 | MPEG25 = 2 97 | }; 98 | 99 | enum mp3_stereo_mode { 100 | STEREO = 0x00, 101 | JOINT = 0x01, 102 | DUAL = 0x02, 103 | MONO = 0x03 104 | }; 105 | 106 | #if defined(__cplusplus) 107 | } 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /snd_utils.c: -------------------------------------------------------------------------------- 1 | /* snd_utils.c 2 | ** 3 | ** Copyright (c) 2019, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include "snd_utils.h" 35 | 36 | #define SND_DLSYM(h, p, s, err) \ 37 | do { \ 38 | err = 0; \ 39 | p = dlsym(h, s); \ 40 | if (!p) \ 41 | err = -ENODEV; \ 42 | } while(0) 43 | 44 | int snd_utils_get_int(struct snd_node *node, const char *prop, int *val) 45 | { 46 | if (!node || !node->card_node || !node->dev_node) 47 | return SND_NODE_TYPE_HW; 48 | 49 | return node->get_int(node->dev_node, prop, val); 50 | } 51 | 52 | int snd_utils_get_str(struct snd_node *node, const char *prop, char **val) 53 | { 54 | if (!node || !node->card_node || !node->dev_node) 55 | return SND_NODE_TYPE_HW; 56 | 57 | return node->get_str(node->dev_node, prop, val); 58 | } 59 | 60 | void snd_utils_put_dev_node(struct snd_node *node) 61 | { 62 | if (!node) 63 | return; 64 | 65 | if (node->card_node) 66 | node->put_card(node->card_node); 67 | 68 | if (node->dl_hdl) 69 | dlclose(node->dl_hdl); 70 | 71 | free(node); 72 | } 73 | 74 | enum snd_node_type snd_utils_get_node_type(struct snd_node *node) 75 | { 76 | int val = SND_NODE_TYPE_HW; 77 | 78 | if (!node || !node->card_node || !node->dev_node) 79 | return SND_NODE_TYPE_HW; 80 | 81 | node->get_int(node->dev_node, "type", &val); 82 | 83 | return val; 84 | }; 85 | 86 | 87 | static int snd_utils_resolve_symbols(struct snd_node *node) 88 | { 89 | void *dl = node->dl_hdl; 90 | int err; 91 | 92 | SND_DLSYM(dl, node->get_card, "snd_card_def_get_card", err); 93 | if (err) 94 | goto done; 95 | SND_DLSYM(dl, node->put_card, "snd_card_def_put_card", err); 96 | if (err) 97 | goto done; 98 | SND_DLSYM(dl, node->get_node, "snd_card_def_get_node", err); 99 | if (err) 100 | goto done; 101 | SND_DLSYM(dl, node->get_int, "snd_card_def_get_int", err); 102 | if (err) 103 | goto done; 104 | SND_DLSYM(dl, node->get_str, "snd_card_def_get_str", err); 105 | 106 | done: 107 | return err; 108 | } 109 | 110 | struct snd_node *snd_utils_get_dev_node(unsigned int card, 111 | unsigned int device, int dev_type) 112 | { 113 | struct snd_node *node; 114 | int rc = 0; 115 | 116 | node = calloc(1, sizeof(*node)); 117 | if (!node) 118 | return NULL; 119 | 120 | node->dl_hdl = dlopen("libsndcardparser.so", RTLD_NOW); 121 | if (!node->dl_hdl) { 122 | goto err_dl_open; 123 | } 124 | 125 | rc = snd_utils_resolve_symbols(node); 126 | if (rc < 0) 127 | goto err_resolve_symbols; 128 | 129 | node->card_node = node->get_card(card); 130 | if (!node->card_node) 131 | goto err_resolve_symbols; 132 | 133 | node->dev_node = node->get_node(node->card_node, 134 | device, dev_type); 135 | if (!node->dev_node) 136 | goto err_get_node; 137 | 138 | return node; 139 | 140 | err_get_node: 141 | node->put_card(node->card_node); 142 | 143 | err_resolve_symbols: 144 | dlclose(node->dl_hdl); 145 | 146 | err_dl_open: 147 | free(node); 148 | return NULL; 149 | } 150 | -------------------------------------------------------------------------------- /cplay.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * tinyplay command line player for compress audio offload in alsa 5 | * Copyright (c) 2011-2012, Intel Corporation 6 | * All rights reserved. 7 | * 8 | * Author: Vinod Koul 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * Neither the name of Intel Corporation nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 | * THE POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | * LGPL LICENSE 35 | * 36 | * tinyplay command line player for compress audio offload in alsa 37 | * Copyright (c) 2011-2012, Intel Corporation. 38 | * 39 | * This program is free software; you can redistribute it and/or modify it 40 | * under the terms and conditions of the GNU Lesser General Public License, 41 | * version 2.1, as published by the Free Software Foundation. 42 | * 43 | * This program is distributed in the hope it will be useful, but WITHOUT 44 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 45 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 46 | * License for more details. 47 | * 48 | * You should have received a copy of the GNU Lesser General Public License 49 | * along with this program; if not, write to 50 | * the Free Software Foundation, Inc., 51 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 52 | */ 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #define __force 67 | #define __bitwise 68 | #define __user 69 | #include "sound/compress_params.h" 70 | #include "tinycompress/tinycompress.h" 71 | #include "tinycompress/tinymp3.h" 72 | 73 | static int verbose; 74 | 75 | static void usage(void) 76 | { 77 | fprintf(stderr, "usage: cplay [OPTIONS] filename\n" 78 | "-c\tcard number\n" 79 | "-d\tdevice node\n" 80 | "-b\tbuffer size\n" 81 | "-f\tfragments\n\n" 82 | "-v\tverbose mode\n" 83 | "-h\tPrints this help list\n\n" 84 | "Example:\n" 85 | "\tcplay -c 1 -d 2 test.mp3\n" 86 | "\tcplay -f 5 test.mp3\n"); 87 | 88 | exit(EXIT_FAILURE); 89 | } 90 | 91 | void play_samples(char *name, unsigned int card, unsigned int device, 92 | unsigned long buffer_size, unsigned int frag); 93 | 94 | struct mp3_header { 95 | uint16_t sync; 96 | uint8_t format1; 97 | uint8_t format2; 98 | }; 99 | 100 | int parse_mp3_header(struct mp3_header *header, unsigned int *num_channels, 101 | unsigned int *sample_rate, unsigned int *bit_rate) 102 | { 103 | int ver_idx, mp3_version, layer, bit_rate_idx, sample_rate_idx, channel_idx; 104 | 105 | /* check sync bits */ 106 | if ((header->sync & MP3_SYNC) != MP3_SYNC) { 107 | fprintf(stderr, "Error: Can't find sync word\n"); 108 | return -1; 109 | } 110 | ver_idx = (header->sync >> 11) & 0x03; 111 | mp3_version = ver_idx == 0 ? MPEG25 : ((ver_idx & 0x1) ? MPEG1 : MPEG2); 112 | layer = 4 - ((header->sync >> 9) & 0x03); 113 | bit_rate_idx = ((header->format1 >> 4) & 0x0f); 114 | sample_rate_idx = ((header->format1 >> 2) & 0x03); 115 | channel_idx = ((header->format2 >> 6) & 0x03); 116 | 117 | if (sample_rate_idx == 3 || layer == 4 || bit_rate_idx == 15) { 118 | fprintf(stderr, "Error: Can't find valid header\n"); 119 | return -1; 120 | } 121 | *num_channels = (channel_idx == MONO ? 1 : 2); 122 | *sample_rate = mp3_sample_rates[mp3_version][sample_rate_idx]; 123 | *bit_rate = (mp3_bit_rates[mp3_version][layer - 1][bit_rate_idx]) * 1000; 124 | if (verbose) 125 | printf("%s: exit\n", __func__); 126 | return 0; 127 | } 128 | 129 | int check_codec_format_supported(unsigned int card, unsigned int device, struct snd_codec *codec) 130 | { 131 | if (is_codec_supported(card, device, COMPRESS_IN, codec) == false) { 132 | fprintf(stderr, "Error: This codec or format is not supported by DSP\n"); 133 | return -1; 134 | } 135 | return 0; 136 | } 137 | 138 | static int print_time(struct compress *compress) 139 | { 140 | unsigned int avail; 141 | struct timespec tstamp; 142 | 143 | if (compress_get_hpointer(compress, &avail, &tstamp) != 0) { 144 | fprintf(stderr, "Error querying timestamp\n"); 145 | fprintf(stderr, "ERR: %s\n", compress_get_error(compress)); 146 | return -1; 147 | } else 148 | fprintf(stderr, "DSP played %jd.%jd\n", (intmax_t)tstamp.tv_sec, (intmax_t)tstamp.tv_nsec*1000); 149 | return 0; 150 | } 151 | 152 | int main(int argc, char **argv) 153 | { 154 | char *file; 155 | unsigned long buffer_size = 0; 156 | int c; 157 | unsigned int card = 0, device = 0, frag = 0; 158 | 159 | 160 | if (argc < 2) 161 | usage(); 162 | 163 | verbose = 0; 164 | while ((c = getopt(argc, argv, "hvb:f:c:d:")) != -1) { 165 | switch (c) { 166 | case 'h': 167 | usage(); 168 | break; 169 | case 'b': 170 | buffer_size = strtol(optarg, NULL, 0); 171 | break; 172 | case 'f': 173 | frag = strtol(optarg, NULL, 10); 174 | break; 175 | case 'c': 176 | card = strtol(optarg, NULL, 10); 177 | break; 178 | case 'd': 179 | device = strtol(optarg, NULL, 10); 180 | break; 181 | case 'v': 182 | verbose = 1; 183 | break; 184 | default: 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | if (optind >= argc) 189 | usage(); 190 | 191 | file = argv[optind]; 192 | 193 | play_samples(file, card, device, buffer_size, frag); 194 | 195 | fprintf(stderr, "Finish Playing.... Close Normally\n"); 196 | exit(EXIT_SUCCESS); 197 | } 198 | 199 | void play_samples(char *name, unsigned int card, unsigned int device, 200 | unsigned long buffer_size, unsigned int frag) 201 | { 202 | struct compr_config config; 203 | struct snd_codec codec; 204 | struct compress *compress; 205 | struct mp3_header header; 206 | FILE *file; 207 | char *buffer; 208 | int size, num_read, wrote; 209 | unsigned int channels, rate, bits; 210 | 211 | if (verbose) 212 | printf("%s: entry\n", __func__); 213 | file = fopen(name, "rb"); 214 | if (!file) { 215 | fprintf(stderr, "Unable to open file '%s'\n", name); 216 | exit(EXIT_FAILURE); 217 | } 218 | 219 | fread(&header, sizeof(header), 1, file); 220 | 221 | if (parse_mp3_header(&header, &channels, &rate, &bits) == -1) { 222 | fclose(file); 223 | exit(EXIT_FAILURE); 224 | } 225 | 226 | codec.id = SND_AUDIOCODEC_MP3; 227 | codec.ch_in = channels; 228 | codec.ch_out = channels; 229 | codec.sample_rate = rate; 230 | if (!codec.sample_rate) { 231 | fprintf(stderr, "invalid sample rate %d\n", rate); 232 | fclose(file); 233 | exit(EXIT_FAILURE); 234 | } 235 | codec.bit_rate = bits; 236 | codec.rate_control = 0; 237 | codec.profile = 0; 238 | codec.level = 0; 239 | codec.ch_mode = 0; 240 | codec.format = 0; 241 | if ((buffer_size != 0) && (frag != 0)) { 242 | config.fragment_size = buffer_size/frag; 243 | config.fragments = frag; 244 | } else { 245 | /* use driver defaults */ 246 | config.fragment_size = 0; 247 | config.fragments = 0; 248 | } 249 | config.codec = &codec; 250 | 251 | compress = compress_open(card, device, COMPRESS_IN, &config); 252 | if (!compress || !is_compress_ready(compress)) { 253 | fprintf(stderr, "Unable to open Compress device %d:%d\n", 254 | card, device); 255 | fprintf(stderr, "ERR: %s\n", compress_get_error(compress)); 256 | goto FILE_EXIT; 257 | }; 258 | if (verbose) 259 | printf("%s: Opened compress device\n", __func__); 260 | size = config.fragment_size; 261 | buffer = malloc(size * config.fragments); 262 | if (!buffer) { 263 | fprintf(stderr, "Unable to allocate %d bytes\n", size); 264 | goto COMP_EXIT; 265 | } 266 | 267 | /* we will write frag fragment_size and then start */ 268 | num_read = fread(buffer, 1, size * config.fragments, file); 269 | if (num_read > 0) { 270 | if (verbose) 271 | printf("%s: Doing first buffer write of %d\n", __func__, num_read); 272 | wrote = compress_write(compress, buffer, num_read); 273 | if (wrote < 0) { 274 | fprintf(stderr, "Error %d playing sample\n", wrote); 275 | fprintf(stderr, "ERR: %s\n", compress_get_error(compress)); 276 | goto BUF_EXIT; 277 | } 278 | if (wrote != num_read) { 279 | /* TODO: Buufer pointer needs to be set here */ 280 | fprintf(stderr, "We wrote %d, DSP accepted %d\n", num_read, wrote); 281 | } 282 | } 283 | printf("Playing file %s On Card %u device %u, with buffer of %lu bytes\n", 284 | name, card, device, buffer_size); 285 | printf("Format %u Channels %u, %u Hz, Bit Rate %d\n", 286 | SND_AUDIOCODEC_MP3, channels, rate, bits); 287 | 288 | compress_start(compress); 289 | if (verbose) 290 | printf("%s: You should hear audio NOW!!!\n", __func__); 291 | 292 | do { 293 | num_read = fread(buffer, 1, size, file); 294 | if (num_read > 0) { 295 | wrote = compress_write(compress, buffer, num_read); 296 | if (wrote < 0) { 297 | fprintf(stderr, "Error playing sample\n"); 298 | fprintf(stderr, "ERR: %s\n", compress_get_error(compress)); 299 | goto BUF_EXIT; 300 | } 301 | if (wrote != num_read) { 302 | /* TODO: Buffer pointer needs to be set here */ 303 | fprintf(stderr, "We wrote %d, DSP accepted %d\n", num_read, wrote); 304 | } 305 | if (verbose) { 306 | print_time(compress); 307 | printf("%s: wrote %d\n", __func__, wrote); 308 | } 309 | } 310 | } while (num_read > 0); 311 | 312 | if (verbose) 313 | printf("%s: exit success\n", __func__); 314 | /* issue drain if it supports */ 315 | compress_drain(compress); 316 | free(buffer); 317 | fclose(file); 318 | compress_close(compress); 319 | return; 320 | BUF_EXIT: 321 | free(buffer); 322 | COMP_EXIT: 323 | compress_close(compress); 324 | FILE_EXIT: 325 | fclose(file); 326 | if (verbose) 327 | printf("%s: exit failure\n", __func__); 328 | exit(EXIT_FAILURE); 329 | } 330 | 331 | -------------------------------------------------------------------------------- /include/tinycompress/tinycompress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * Copyright (c) 2011-2012, Intel Corporation 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | * this list of conditions and the following disclaimer in the documentation 14 | * and/or other materials provided with the distribution. 15 | * Neither the name of Intel Corporation nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * LGPL LICENSE 32 | * 33 | * tinycompress library for compress audio offload in alsa 34 | * Copyright (c) 2011-2012, Intel Corporation. 35 | * 36 | * 37 | * This program is free software; you can redistribute it and/or modify it 38 | * under the terms and conditions of the GNU Lesser General Public License, 39 | * version 2.1, as published by the Free Software Foundation. 40 | * 41 | * This program is distributed in the hope it will be useful, but WITHOUT 42 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 43 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 44 | * License for more details. 45 | * 46 | * You should have received a copy of the GNU Lesser General Public License 47 | * along with this program; if not, write to 48 | * the Free Software Foundation, Inc., 49 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 50 | */ 51 | 52 | 53 | #ifndef __TINYCOMPRESS_H 54 | #define __TINYCOMPRESS_H 55 | 56 | #if defined(__cplusplus) 57 | extern "C" { 58 | #endif 59 | /* 60 | * struct compr_config: config structure, needs to be filled by app 61 | * If fragment_size or fragments are zero, this means "don't care" 62 | * and tinycompress will choose values that the driver supports 63 | * 64 | * @fragment_size: size of fragment requested, in bytes 65 | * @fragments: number of fragments 66 | * @codec: codec type and parameters requested 67 | */ 68 | struct compr_config { 69 | __u32 fragment_size; 70 | __u32 fragments; 71 | struct snd_codec *codec; 72 | }; 73 | 74 | struct compr_gapless_mdata { 75 | __u32 encoder_delay; 76 | __u32 encoder_padding; 77 | }; 78 | 79 | #define COMPRESS_OUT 0x20000000 80 | #define COMPRESS_IN 0x10000000 81 | 82 | struct compress; 83 | struct snd_compr_tstamp; 84 | 85 | #ifdef ENABLE_EXTENDED_COMPRESS_FORMAT 86 | union snd_codec_options; 87 | struct snd_compr_metadata; 88 | #endif 89 | /* 90 | * compress_open: open a new compress stream 91 | * returns the valid struct compress on success, NULL on failure 92 | * If config does not specify a requested fragment size, on return 93 | * it will be updated with the size and number of fragments that 94 | * were configured 95 | * 96 | * @card: sound card number 97 | * @device: device number 98 | * @flags: device flags can be COMPRESS_OUT or COMPRESS_IN 99 | * @config: stream config requested. Returns actual fragment config 100 | */ 101 | struct compress *compress_open(unsigned int card, unsigned int device, 102 | unsigned int flags, struct compr_config *config); 103 | 104 | /* 105 | * compress_close: close the compress stream 106 | * 107 | * @compress: compress stream to be closed 108 | */ 109 | void compress_close(struct compress *compress); 110 | 111 | /* 112 | * compress_get_hpointer: get the hw timestamp 113 | * return 0 on success, negative on error 114 | * 115 | * @compress: compress stream on which query is made 116 | * @avail: buffer availble for write/read, in bytes 117 | * @tstamp: hw time 118 | */ 119 | int compress_get_hpointer(struct compress *compress, 120 | unsigned int *avail, struct timespec *tstamp); 121 | 122 | 123 | /* 124 | * compress_get_tstamp: get the raw hw timestamp 125 | * return 0 on success, negative on error 126 | * 127 | * @compress: compress stream on which query is made 128 | * @samples: number of decoded samples played 129 | * @sampling_rate: sampling rate of decoded samples 130 | */ 131 | int compress_get_tstamp(struct compress *compress, 132 | unsigned long *samples, unsigned int *sampling_rate); 133 | 134 | /* 135 | * compress_write: write data to the compress stream 136 | * return bytes written on success, negative on error 137 | * By default this is a blocking call and will not return 138 | * until all bytes have been written or there was a 139 | * write error. 140 | * If non-blocking mode has been enabled with compress_nonblock(), 141 | * this function will write all bytes that can be written without 142 | * blocking and will then return the number of bytes successfully 143 | * written. If the return value is not an error and is < size 144 | * the caller can use compress_wait() to block until the driver 145 | * is ready for more data. 146 | * 147 | * @compress: compress stream to be written to 148 | * @buf: pointer to data 149 | * @size: number of bytes to be written 150 | */ 151 | int compress_write(struct compress *compress, const void *buf, unsigned int size); 152 | 153 | /* 154 | * compress_read: read data from the compress stream 155 | * return bytes read on success, negative on error 156 | * By default this is a blocking call and will block until 157 | * size bytes have been written or there was a read error. 158 | * If non-blocking mode was enabled using compress_nonblock() 159 | * the behaviour will change to read only as many bytes as 160 | * are currently available (if no bytes are available it 161 | * will return immediately). The caller can then use 162 | * compress_wait() to block until more bytes are available. 163 | * 164 | * @compress: compress stream from where data is to be read 165 | * @buf: pointer to data buffer 166 | * @size: size of given buffer 167 | */ 168 | int compress_read(struct compress *compress, void *buf, unsigned int size); 169 | 170 | /* 171 | * compress_start: start the compress stream 172 | * return 0 on success, negative on error 173 | * 174 | * @compress: compress stream to be started 175 | */ 176 | int compress_start(struct compress *compress); 177 | 178 | /* 179 | * compress_stop: stop the compress stream 180 | * return 0 on success, negative on error 181 | * 182 | * @compress: compress stream to be stopped 183 | */ 184 | int compress_stop(struct compress *compress); 185 | 186 | /* 187 | * compress_pause: pause the compress stream 188 | * return 0 on success, negative on error 189 | * 190 | * @compress: compress stream to be paused 191 | */ 192 | int compress_pause(struct compress *compress); 193 | 194 | /* 195 | * compress_resume: resume the compress stream 196 | * return 0 on success, negative on error 197 | * 198 | * @compress: compress stream to be resumed 199 | */ 200 | int compress_resume(struct compress *compress); 201 | 202 | /* 203 | * compress_drain: drain the compress stream 204 | * return 0 on success, negative on error 205 | * 206 | * @compress: compress stream to be drain 207 | */ 208 | int compress_drain(struct compress *compress); 209 | 210 | /* 211 | * compress_next_track: set the next track for stream 212 | * 213 | * return 0 on success, negative on error 214 | * 215 | * @compress: compress stream to be transistioned to next track 216 | */ 217 | int compress_next_track(struct compress *compress); 218 | 219 | /* 220 | * compress_partial_drain: drain will return after the last frame is decoded 221 | * by DSP and will play the , All the data written into compressed 222 | * ring buffer is decoded 223 | * 224 | * return 0 on success, negative on error 225 | * 226 | * @compress: compress stream to be drain 227 | */ 228 | int compress_partial_drain(struct compress *compress); 229 | 230 | /* 231 | * compress_set_gapless_metadata: set gapless metadata of a compress strem 232 | * 233 | * return 0 on success, negative on error 234 | * 235 | * @compress: compress stream for which metadata has to set 236 | * @mdata: metadata encoder delay and padding 237 | */ 238 | 239 | int compress_set_gapless_metadata(struct compress *compress, 240 | struct compr_gapless_mdata *mdata); 241 | 242 | #ifdef ENABLE_EXTENDED_COMPRESS_FORMAT 243 | /* 244 | * compress_set_next_track_param: set params of next compress stream in gapless 245 | * 246 | * return 0 on success, negative on error 247 | * 248 | * @compress: compress stream for which codec options has to be set 249 | * @codec_options: codec options of compress stream based on codec type 250 | */ 251 | 252 | int compress_set_next_track_param(struct compress *compress, 253 | union snd_codec_options *codec_options); 254 | #endif 255 | 256 | /* 257 | * is_codec_supported:check if the given codec is supported 258 | * returns true when supported, false if not 259 | * 260 | * @card: sound card number 261 | * @device: device number 262 | * @flags: stream flags 263 | * @codec: codec type and parameters to be checked 264 | */ 265 | bool is_codec_supported(unsigned int card, unsigned int device, 266 | unsigned int flags, struct snd_codec *codec); 267 | 268 | /* 269 | * compress_set_max_poll_wait: set the maximum time tinycompress 270 | * will wait for driver to signal a poll(). Interval is in 271 | * milliseconds. 272 | * Pass interval of -1 to disable timeout and make poll() wait 273 | * until driver signals. 274 | * If this function is not used the timeout defaults to 20 seconds. 275 | */ 276 | void compress_set_max_poll_wait(struct compress *compress, int milliseconds); 277 | 278 | /* Enable or disable non-blocking mode for write and read */ 279 | void compress_nonblock(struct compress *compress, int nonblock); 280 | 281 | /* Wait for ring buffer to ready for next read or write */ 282 | int compress_wait(struct compress *compress, int timeout_ms); 283 | 284 | int is_compress_running(struct compress *compress); 285 | 286 | int is_compress_ready(struct compress *compress); 287 | 288 | /* Returns a human readable reason for the last error */ 289 | const char *compress_get_error(struct compress *compress); 290 | /* 291 | * since the SNDRV_PCM_RATE_* is not availble anywhere in userspace 292 | * and we have used these to define the sampling rate, we need to define 293 | * then here 294 | */ 295 | #define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ 296 | #define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ 297 | #define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ 298 | #define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ 299 | #define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ 300 | #define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ 301 | #define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ 302 | #define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ 303 | #define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ 304 | #define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ 305 | #define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ 306 | #define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ 307 | #define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ 308 | 309 | /* utility functions */ 310 | unsigned int compress_get_alsa_rate(unsigned int rate); 311 | 312 | #ifdef ENABLE_EXTENDED_COMPRESS_FORMAT 313 | /* set metadata */ 314 | int compress_set_metadata(struct compress *compress, 315 | struct snd_compr_metadata *mdata); 316 | 317 | /* get metadata */ 318 | int compress_get_metadata(struct compress *compress, 319 | struct snd_compr_metadata *mdata); 320 | #endif 321 | 322 | #if defined(__cplusplus) 323 | } 324 | #endif 325 | 326 | #endif 327 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | BSD LICENSE 2 | 3 | tinycompress library for compress audio offload in alsa 4 | Copyright (c) 2011-2012, Intel Corporation 5 | All rights reserved. 6 | 7 | Author: Vinod Koul 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | Neither the name of Intel Corporation nor the names of its contributors 18 | may be used to endorse or promote products derived from this software 19 | without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | LGPL LICENSE 34 | 35 | tinycompress library for compress audio offload in alsa 36 | Copyright (c) 2011-2012, Intel Corporation. 37 | 38 | 39 | This program is free software; you can redistribute it and/or modify it 40 | under the terms and conditions of the GNU Lesser General Public License, 41 | version 2.1, as published by the Free Software Foundation. 42 | 43 | This program is distributed in the hope it will be useful, but WITHOUT 44 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 45 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 46 | License for more details. 47 | 48 | You should have received a copy of the GNU Lesser General Public License 49 | along with this program; if not, write to 50 | the Free Software Foundation, Inc., 51 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 52 | 53 | =============================================================================== 54 | 55 | BSD LICENSE 56 | 57 | tinyplay command line player for compress audio offload in alsa 58 | Copyright (c) 2011-2012, Intel Corporation 59 | All rights reserved. 60 | 61 | Author: Vinod Koul 62 | 63 | Redistribution and use in source and binary forms, with or without 64 | modification, are permitted provided that the following conditions are met: 65 | 66 | Redistributions of source code must retain the above copyright notice, 67 | this list of conditions and the following disclaimer. 68 | Redistributions in binary form must reproduce the above copyright notice, 69 | this list of conditions and the following disclaimer in the documentation 70 | and/or other materials provided with the distribution. 71 | Neither the name of Intel Corporation nor the names of its contributors 72 | may be used to endorse or promote products derived from this software 73 | without specific prior written permission. 74 | 75 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 76 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 77 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 78 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 79 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 80 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 81 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 82 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 83 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 84 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 85 | THE POSSIBILITY OF SUCH DAMAGE. 86 | 87 | LGPL LICENSE 88 | 89 | tinyplay command line player for compress audio offload in alsa 90 | Copyright (c) 2011-2012, Intel Corporation. 91 | 92 | This program is free software; you can redistribute it and/or modify it 93 | under the terms and conditions of the GNU Lesser General Public License, 94 | version 2.1, as published by the Free Software Foundation. 95 | 96 | This program is distributed in the hope it will be useful, but WITHOUT 97 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 98 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 99 | License for more details. 100 | 101 | You should have received a copy of the GNU Lesser General Public License 102 | along with this program; if not, write to 103 | the Free Software Foundation, Inc., 104 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 105 | 106 | =============================================================================== 107 | 108 | BSD LICENSE 109 | 110 | mp3 header and prasing 111 | Copyright (c) 2011-2012, Intel Corporation 112 | All rights reserved. 113 | 114 | Author: Vinod Koul 115 | 116 | Redistribution and use in source and binary forms, with or without 117 | modification, are permitted provided that the following conditions are met: 118 | 119 | Redistributions of source code must retain the above copyright notice, 120 | this list of conditions and the following disclaimer. 121 | Redistributions in binary form must reproduce the above copyright notice, 122 | this list of conditions and the following disclaimer in the documentation 123 | and/or other materials provided with the distribution. 124 | Neither the name of Intel Corporation nor the names of its contributors 125 | may be used to endorse or promote products derived from this software 126 | without specific prior written permission. 127 | 128 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 129 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 130 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 131 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 132 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 133 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 134 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 135 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 136 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 137 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 138 | THE POSSIBILITY OF SUCH DAMAGE. 139 | 140 | LGPL LICENSE 141 | 142 | mp3 header and parsing 143 | Copyright (c) 2011-2012, Intel Corporation. 144 | 145 | 146 | This program is free software; you can redistribute it and/or modify it 147 | under the terms and conditions of the GNU Lesser General Public License, 148 | version 2.1, as published by the Free Software Foundation. 149 | 150 | This program is distributed in the hope it will be useful, but WITHOUT 151 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 152 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 153 | License for more details. 154 | 155 | You should have received a copy of the GNU Lesser General Public License 156 | along with this program; if not, write to 157 | the Free Software Foundation, Inc., 158 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 159 | 160 | =============================================================================== 161 | 162 | BSD LICENSE 163 | 164 | Copyright (c) 2011-2012, Intel Corporation 165 | All rights reserved. 166 | 167 | Redistribution and use in source and binary forms, with or without 168 | modification, are permitted provided that the following conditions are met: 169 | 170 | Redistributions of source code must retain the above copyright notice, 171 | this list of conditions and the following disclaimer. 172 | Redistributions in binary form must reproduce the above copyright notice, 173 | this list of conditions and the following disclaimer in the documentation 174 | and/or other materials provided with the distribution. 175 | Neither the name of Intel Corporation nor the names of its contributors 176 | may be used to endorse or promote products derived from this software 177 | without specific prior written permission. 178 | 179 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 180 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 182 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 183 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 184 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 185 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 186 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 187 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 188 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 189 | THE POSSIBILITY OF SUCH DAMAGE. 190 | 191 | LGPL LICENSE 192 | 193 | tinycompress library for compress audio offload in alsa 194 | Copyright (c) 2011-2012, Intel Corporation. 195 | 196 | 197 | This program is free software; you can redistribute it and/or modify it 198 | under the terms and conditions of the GNU Lesser General Public License, 199 | version 2.1, as published by the Free Software Foundation. 200 | 201 | This program is distributed in the hope it will be useful, but WITHOUT 202 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 203 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 204 | License for more details. 205 | 206 | You should have received a copy of the GNU Lesser General Public License 207 | along with this program; if not, write to 208 | the Free Software Foundation, Inc., 209 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 210 | 211 | =============================================================================== 212 | 213 | BSD LICENSE 214 | 215 | tinycompress utility functions 216 | Copyright (c) 2011-2013, Intel Corporation 217 | All rights reserved. 218 | 219 | Author: Vinod Koul 220 | 221 | Redistribution and use in source and binary forms, with or without 222 | modification, are permitted provided that the following conditions are met: 223 | 224 | Redistributions of source code must retain the above copyright notice, 225 | this list of conditions and the following disclaimer. 226 | Redistributions in binary form must reproduce the above copyright notice, 227 | this list of conditions and the following disclaimer in the documentation 228 | and/or other materials provided with the distribution. 229 | Neither the name of Intel Corporation nor the names of its contributors 230 | may be used to endorse or promote products derived from this software 231 | without specific prior written permission. 232 | 233 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 234 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 235 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 236 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 237 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 238 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 239 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 240 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 242 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 243 | THE POSSIBILITY OF SUCH DAMAGE. 244 | 245 | LGPL LICENSE 246 | 247 | tinycompress utility functions 248 | Copyright (c) 2011-2013, Intel Corporation 249 | 250 | This program is free software; you can redistribute it and/or modify it 251 | under the terms and conditions of the GNU Lesser General Public License, 252 | version 2.1, as published by the Free Software Foundation. 253 | 254 | This program is distributed in the hope it will be useful, but WITHOUT 255 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 256 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 257 | License for more details. 258 | 259 | You should have received a copy of the GNU Lesser General Public License 260 | along with this program; if not, write to 261 | the Free Software Foundation, Inc., 262 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 263 | -------------------------------------------------------------------------------- /compress_plugin.c: -------------------------------------------------------------------------------- 1 | /* compress_plugin.c 2 | ** 3 | ** Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are 7 | ** met: 8 | ** * Redistributions of source code must retain the above copyright 9 | ** notice, this list of conditions and the following disclaimer. 10 | ** * Redistributions in binary form must reproduce the above 11 | ** copyright notice, this list of conditions and the following 12 | ** disclaimer in the documentation and/or other materials provided 13 | ** with the distribution. 14 | ** * Neither the name of The Linux Foundation nor the names of its 15 | ** contributors may be used to endorse or promote products derived 16 | ** from this software without specific prior written permission. 17 | ** 18 | ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 19 | ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 21 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 22 | ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 | ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 | ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | **/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include "tinycompress/compress_plugin.h" 46 | #include "sound/compress_offload.h" 47 | #include "compress_ops.h" 48 | #include "snd_utils.h" 49 | 50 | #define U32_MAX ((uint32_t)~0U) 51 | 52 | enum { 53 | COMPRESS_PLUG_STATE_OPEN, 54 | COMPRESS_PLUG_STATE_SETUP, 55 | COMPRESS_PLUG_STATE_PREPARED, 56 | COMPRESS_PLUG_STATE_PAUSE, 57 | COMPRESS_PLUG_STATE_RUNNING, 58 | }; 59 | 60 | struct compress_plug_data { 61 | unsigned int card; 62 | unsigned int device; 63 | unsigned int fd; 64 | unsigned int flags; 65 | 66 | void *dl_hdl; 67 | COMPRESS_PLUGIN_OPEN_FN_PTR(); 68 | 69 | struct compress_plugin *plugin; 70 | void *dev_node; 71 | }; 72 | 73 | static int compress_plug_get_caps(struct compress_plug_data *plug_data, 74 | struct snd_compr_caps *caps) 75 | { 76 | struct compress_plugin *plugin = plug_data->plugin; 77 | 78 | return plugin->ops->get_caps(plugin, caps); 79 | } 80 | 81 | static int compress_plug_set_params(struct compress_plug_data *plug_data, 82 | struct snd_compr_params *params) 83 | { 84 | struct compress_plugin *plugin = plug_data->plugin; 85 | int rc; 86 | 87 | if (plugin->state != COMPRESS_PLUG_STATE_OPEN) 88 | return -EBADFD; 89 | 90 | if (params->buffer.fragment_size == 0 || 91 | params->buffer.fragments > U32_MAX / params->buffer.fragment_size || 92 | params->buffer.fragments == 0) 93 | return -EINVAL; 94 | 95 | rc = plugin->ops->set_params(plugin, params); 96 | if (!rc) 97 | plugin->state = COMPRESS_PLUG_STATE_SETUP; 98 | 99 | return rc; 100 | } 101 | 102 | static int compress_plug_avail(struct compress_plug_data *plug_data, 103 | struct snd_compr_avail *avail) 104 | { 105 | struct compress_plugin *plugin = plug_data->plugin; 106 | 107 | return plugin->ops->avail(plugin, avail); 108 | } 109 | 110 | static int compress_plug_tstamp(struct compress_plug_data *plug_data, 111 | struct snd_compr_tstamp *tstamp) 112 | { 113 | struct compress_plugin *plugin = plug_data->plugin; 114 | 115 | if (plugin->state != COMPRESS_PLUG_STATE_SETUP) 116 | return -EBADFD; 117 | 118 | return plugin->ops->tstamp(plugin, tstamp); 119 | } 120 | 121 | static int compress_plug_start(struct compress_plug_data *plug_data) 122 | { 123 | struct compress_plugin *plugin = plug_data->plugin; 124 | int rc; 125 | 126 | /* for playback moved to prepare in first write */ 127 | /* for capture: move to prepare state set params */ 128 | /* TODO: add direction in set params */ 129 | if (plugin->state != COMPRESS_PLUG_STATE_PREPARED) 130 | return -EBADFD; 131 | 132 | rc = plugin->ops->start(plugin); 133 | if (!rc) 134 | plugin->state = COMPRESS_PLUG_STATE_RUNNING; 135 | 136 | return rc; 137 | } 138 | 139 | static int compress_plug_stop(struct compress_plug_data *plug_data) 140 | { 141 | struct compress_plugin *plugin = plug_data->plugin; 142 | int rc; 143 | 144 | if (plugin->state == COMPRESS_PLUG_STATE_PREPARED || 145 | plugin->state == COMPRESS_PLUG_STATE_SETUP) 146 | return -EBADFD; 147 | 148 | rc = plugin->ops->stop(plugin); 149 | if (!rc) 150 | plugin->state = COMPRESS_PLUG_STATE_SETUP; 151 | 152 | return rc; 153 | } 154 | 155 | static int compress_plug_pause(struct compress_plug_data *plug_data) 156 | { 157 | struct compress_plugin *plugin = plug_data->plugin; 158 | int rc; 159 | 160 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING) 161 | return -EBADFD; 162 | 163 | rc = plugin->ops->pause(plugin); 164 | if (!rc) 165 | plugin->state = COMPRESS_PLUG_STATE_PAUSE; 166 | 167 | return rc; 168 | } 169 | 170 | static int compress_plug_resume(struct compress_plug_data *plug_data) 171 | { 172 | struct compress_plugin *plugin = plug_data->plugin; 173 | int rc; 174 | 175 | if (plugin->state != COMPRESS_PLUG_STATE_PAUSE) 176 | return -EBADFD; 177 | 178 | rc = plugin->ops->resume(plugin); 179 | if (!rc) 180 | plugin->state = COMPRESS_PLUG_STATE_RUNNING; 181 | 182 | return rc; 183 | } 184 | 185 | static int compress_plug_drain(struct compress_plug_data *plug_data) 186 | { 187 | struct compress_plugin *plugin = plug_data->plugin; 188 | 189 | /* check if we will allow in pause */ 190 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING) 191 | return -EBADFD; 192 | 193 | return plugin->ops->drain(plugin); 194 | } 195 | 196 | static int compress_plug_partial_drain(struct compress_plug_data *plug_data) 197 | { 198 | struct compress_plugin *plugin = plug_data->plugin; 199 | 200 | /* check if we will allow in pause */ 201 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING) 202 | return -EBADFD; 203 | 204 | return plugin->ops->partial_drain(plugin); 205 | } 206 | 207 | static int compress_plug_next_track(struct compress_plug_data *plug_data) 208 | { 209 | struct compress_plugin *plugin = plug_data->plugin; 210 | 211 | /* transion to next track applied to running stream only */ 212 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING) 213 | return -EBADFD; 214 | 215 | return plugin->ops->next_track(plugin); 216 | } 217 | 218 | static int compress_plug_ioctl(void *data, unsigned int cmd, ...) 219 | { 220 | struct compress_plug_data *plug_data = data; 221 | struct compress_plugin *plugin = plug_data->plugin; 222 | int ret = 0; 223 | va_list ap; 224 | void *arg; 225 | 226 | va_start(ap, cmd); 227 | arg = va_arg(ap, void *); 228 | va_end(ap); 229 | 230 | switch (cmd) { 231 | case SNDRV_COMPRESS_IOCTL_VERSION: 232 | *((int*)arg) = SNDRV_COMPRESS_VERSION; 233 | break; 234 | case SNDRV_COMPRESS_GET_CAPS: 235 | ret = compress_plug_get_caps(plug_data, arg); 236 | break; 237 | case SNDRV_COMPRESS_SET_PARAMS: 238 | ret = compress_plug_set_params(plug_data, arg); 239 | break; 240 | case SNDRV_COMPRESS_AVAIL: 241 | ret = compress_plug_avail(plug_data, arg); 242 | break; 243 | case SNDRV_COMPRESS_TSTAMP: 244 | ret = compress_plug_tstamp(plug_data, arg); 245 | break; 246 | case SNDRV_COMPRESS_START: 247 | ret = compress_plug_start(plug_data); 248 | break; 249 | case SNDRV_COMPRESS_STOP: 250 | ret = compress_plug_stop(plug_data); 251 | break; 252 | case SNDRV_COMPRESS_PAUSE: 253 | ret = compress_plug_pause(plug_data); 254 | break; 255 | case SNDRV_COMPRESS_RESUME: 256 | ret = compress_plug_resume(plug_data); 257 | break; 258 | case SNDRV_COMPRESS_DRAIN: 259 | ret = compress_plug_drain(plug_data); 260 | break; 261 | case SNDRV_COMPRESS_PARTIAL_DRAIN: 262 | ret = compress_plug_partial_drain(plug_data); 263 | break; 264 | case SNDRV_COMPRESS_NEXT_TRACK: 265 | ret = compress_plug_next_track(plug_data); 266 | break; 267 | default: 268 | if (plugin->ops->ioctl) 269 | ret = plugin->ops->ioctl(plugin, cmd, arg); 270 | else 271 | ret = -EINVAL; 272 | break; 273 | } 274 | 275 | return ret; 276 | } 277 | 278 | static int compress_plug_poll(void *data, struct pollfd *fds, 279 | nfds_t nfds, int timeout) 280 | { 281 | struct compress_plug_data *plug_data = data; 282 | struct compress_plugin *plugin = plug_data->plugin; 283 | 284 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING) 285 | return -EBADFD; 286 | 287 | return plugin->ops->poll(plugin, fds, nfds, timeout); 288 | } 289 | 290 | 291 | static int compress_plug_read(void *data, void *buf, size_t size) 292 | { 293 | struct compress_plug_data *plug_data = data; 294 | struct compress_plugin *plugin = plug_data->plugin; 295 | 296 | if (plugin->state != COMPRESS_PLUG_STATE_RUNNING && 297 | plugin->state != COMPRESS_PLUG_STATE_SETUP) 298 | return -EBADFD; 299 | 300 | return plugin->ops->read(plugin, buf, size); 301 | } 302 | 303 | static int compress_plug_write(void *data, const void *buf, size_t size) 304 | { 305 | struct compress_plug_data *plug_data = data; 306 | struct compress_plugin *plugin = plug_data->plugin; 307 | int rc; 308 | 309 | if (plugin->state != COMPRESS_PLUG_STATE_SETUP && 310 | plugin->state != COMPRESS_PLUG_STATE_PREPARED && 311 | plugin->state != COMPRESS_PLUG_STATE_RUNNING) 312 | return -EBADFD; 313 | 314 | rc = plugin->ops->write(plugin, buf, size); 315 | if ((rc > 0) && (plugin->state == COMPRESS_PLUG_STATE_SETUP)) 316 | plugin->state = COMPRESS_PLUG_STATE_PREPARED; 317 | 318 | return rc; 319 | } 320 | 321 | static void compress_plug_close(void *data) 322 | { 323 | struct compress_plug_data *plug_data = data; 324 | struct compress_plugin *plugin = plug_data->plugin; 325 | 326 | plugin->ops->close(plugin); 327 | dlclose(plug_data->dl_hdl); 328 | 329 | free(plug_data); 330 | } 331 | 332 | static int compress_plug_open(unsigned int card, unsigned int device, 333 | unsigned int flags, void **data, void *node) 334 | { 335 | struct compress_plug_data *plug_data; 336 | void *dl_hdl; 337 | int rc = 0; 338 | char *so_name, *open_fn, token[80], *name, *token_saveptr; 339 | 340 | plug_data = calloc(1, sizeof(*plug_data)); 341 | if (!plug_data) { 342 | return -ENOMEM; 343 | } 344 | 345 | rc = snd_utils_get_str(node, "so-name", &so_name); 346 | if (rc) { 347 | fprintf(stderr, "%s: failed to get plugin lib name\n", 348 | __func__); 349 | goto err_get_lib; 350 | } 351 | 352 | dl_hdl = dlopen(so_name, RTLD_NOW); 353 | if (!dl_hdl) { 354 | fprintf(stderr, "%s: unable to open %s, error: %s\n", 355 | __func__, so_name, dlerror()); 356 | goto err_dl_open; 357 | } else { 358 | fprintf(stderr, "%s: dlopen successful for %s\n", 359 | __func__, so_name); 360 | } 361 | 362 | sscanf(so_name, "lib%s", token); 363 | token_saveptr = token; 364 | name = strtok_r(token, ".", &token_saveptr); 365 | if (!name) { 366 | fprintf(stderr, "%s: invalid library name\n", __func__); 367 | goto err_open_fn; 368 | } 369 | const size_t open_fn_size = strlen(name) + strlen("_open") + 1; 370 | open_fn = calloc(1, open_fn_size); 371 | if (!open_fn) { 372 | rc = -ENOMEM; 373 | goto err_open_fn; 374 | } 375 | 376 | strlcpy(open_fn, name, open_fn_size); 377 | strlcat(open_fn, "_open", open_fn_size); 378 | 379 | plug_data->plugin_open_fn = dlsym(dl_hdl, open_fn); 380 | if (!plug_data->plugin_open_fn) { 381 | fprintf(stderr, "%s: dlsym to open fn failed, err = '%s'\n", 382 | __func__, dlerror()); 383 | goto err_dlsym; 384 | } 385 | 386 | rc = plug_data->plugin_open_fn(&plug_data->plugin, 387 | card, device, flags); 388 | if (rc) { 389 | fprintf(stderr, "%s: failed to open plugin\n", __func__); 390 | goto err_dlsym; 391 | } 392 | 393 | /* Call snd-card-def to get card and compress nodes */ 394 | /* Check how to manage fd for plugin */ 395 | 396 | plug_data->dl_hdl = dl_hdl; 397 | plug_data->card = card; 398 | plug_data->device = device; 399 | plug_data->dev_node = node; 400 | plug_data->flags = flags; 401 | 402 | *data = plug_data; 403 | 404 | plug_data->plugin->state = COMPRESS_PLUG_STATE_OPEN; 405 | 406 | return 0; 407 | 408 | err_dlsym: 409 | free(open_fn); 410 | err_open_fn: 411 | dlclose(dl_hdl); 412 | err_get_lib: 413 | err_dl_open: 414 | free(plug_data); 415 | 416 | return rc; 417 | } 418 | 419 | struct compress_ops compr_plug_ops = { 420 | .open = compress_plug_open, 421 | .close = compress_plug_close, 422 | .ioctl = compress_plug_ioctl, 423 | .read = compress_plug_read, 424 | .write = compress_plug_write, 425 | .poll = compress_plug_poll, 426 | }; 427 | -------------------------------------------------------------------------------- /compress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD LICENSE 3 | * 4 | * tinycompress library for compress audio offload in alsa 5 | * Copyright (c) 2011-2012, Intel Corporation 6 | * All rights reserved. 7 | * 8 | * Author: Vinod Koul 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * 13 | * Redistributions of source code must retain the above copyright notice, 14 | * this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright notice, 16 | * this list of conditions and the following disclaimer in the documentation 17 | * and/or other materials provided with the distribution. 18 | * Neither the name of Intel Corporation nor the names of its contributors 19 | * may be used to endorse or promote products derived from this software 20 | * without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 | * THE POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | * LGPL LICENSE 35 | * 36 | * tinycompress library for compress audio offload in alsa 37 | * Copyright (c) 2011-2012, Intel Corporation. 38 | * 39 | * 40 | * This program is free software; you can redistribute it and/or modify it 41 | * under the terms and conditions of the GNU Lesser General Public License, 42 | * version 2.1, as published by the Free Software Foundation. 43 | * 44 | * This program is distributed in the hope it will be useful, but WITHOUT 45 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 46 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 47 | * License for more details. 48 | * 49 | * You should have received a copy of the GNU Lesser General Public License 50 | * along with this program; if not, write to 51 | * the Free Software Foundation, Inc., 52 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 53 | */ 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | 69 | #include 70 | #include 71 | #define __force 72 | #define __bitwise 73 | #define __user 74 | #include 75 | #include "sound/compress_params.h" 76 | #include "sound/compress_offload.h" 77 | #include "tinycompress/tinycompress.h" 78 | #include "compress_ops.h" 79 | #include "snd_utils.h" 80 | 81 | #define COMPR_ERR_MAX 128 82 | 83 | /* Default maximum time we will wait in a poll() - 20 seconds */ 84 | #define DEFAULT_MAX_POLL_WAIT_MS 20000 85 | 86 | struct compress { 87 | int fd; 88 | unsigned int flags; 89 | char error[COMPR_ERR_MAX]; 90 | struct compr_config *config; 91 | int running; 92 | int max_poll_wait_ms; 93 | int nonblocking; 94 | unsigned int gapless_metadata; 95 | unsigned int next_track; 96 | 97 | struct compress_ops *ops; 98 | void *data; 99 | void *snd_node; 100 | }; 101 | 102 | extern struct compress_ops compr_hw_ops; 103 | extern struct compress_ops compr_plug_ops; 104 | 105 | static int oops(struct compress *compress, int e, const char *fmt, ...) 106 | { 107 | va_list ap; 108 | int sz; 109 | 110 | va_start(ap, fmt); 111 | vsnprintf(compress->error, COMPR_ERR_MAX, fmt, ap); 112 | va_end(ap); 113 | sz = strlen(compress->error); 114 | 115 | snprintf(compress->error + sz, COMPR_ERR_MAX - sz, 116 | ": %s", strerror(e)); 117 | errno = e; 118 | 119 | return -1; 120 | } 121 | 122 | const char *compress_get_error(struct compress *compress) 123 | { 124 | return compress->error; 125 | } 126 | static struct compress bad_compress = { 127 | .fd = -1, 128 | }; 129 | 130 | int is_compress_running(struct compress *compress) 131 | { 132 | return ((compress->fd >= 0) && compress->running) ? 1 : 0; 133 | } 134 | 135 | int is_compress_ready(struct compress *compress) 136 | { 137 | return (compress->fd >= 0) ? 1 : 0; 138 | } 139 | 140 | static int get_compress_version(struct compress *compress) 141 | { 142 | int version = 0; 143 | 144 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_IOCTL_VERSION, &version)) { 145 | oops(compress, errno, "cant read version"); 146 | return -1; 147 | } 148 | return version; 149 | } 150 | 151 | static bool _is_codec_type_supported(struct compress_ops *ops, void *data, 152 | struct snd_codec *codec) 153 | { 154 | struct snd_compr_caps caps; 155 | bool found = false; 156 | unsigned int i; 157 | 158 | if (ops->ioctl(data, SNDRV_COMPRESS_GET_CAPS, &caps)) { 159 | oops(&bad_compress, errno, "cannot get device caps"); 160 | return false; 161 | } 162 | 163 | for (i = 0; i < caps.num_codecs; i++) { 164 | if (caps.codecs[i] == codec->id) { 165 | /* found the codec */ 166 | found = true; 167 | break; 168 | } 169 | } 170 | /* TODO: match the codec properties */ 171 | return found; 172 | } 173 | 174 | static inline void 175 | fill_compress_params(struct compr_config *config, struct snd_compr_params *params) 176 | { 177 | params->buffer.fragment_size = config->fragment_size; 178 | params->buffer.fragments = config->fragments; 179 | memcpy(¶ms->codec, config->codec, sizeof(params->codec)); 180 | } 181 | 182 | struct compress *compress_open(unsigned int card, unsigned int device, 183 | unsigned int flags, struct compr_config *config) 184 | { 185 | struct compress *compress; 186 | struct snd_compr_params params; 187 | struct snd_compr_caps caps; 188 | int compress_type; 189 | 190 | if (!config) { 191 | oops(&bad_compress, EINVAL, "passed bad config"); 192 | return &bad_compress; 193 | } 194 | 195 | compress = calloc(1, sizeof(struct compress)); 196 | if (!compress) { 197 | oops(&bad_compress, errno, "cannot allocate compress object"); 198 | return &bad_compress; 199 | } 200 | 201 | compress->next_track = 0; 202 | compress->gapless_metadata = 0; 203 | compress->config = calloc(1, sizeof(*config)); 204 | if (!compress->config) 205 | goto input_fail; 206 | 207 | compress->max_poll_wait_ms = DEFAULT_MAX_POLL_WAIT_MS; 208 | 209 | compress->flags = flags; 210 | if (!((flags & COMPRESS_OUT) || (flags & COMPRESS_IN))) { 211 | oops(&bad_compress, EINVAL, "can't deduce device direction from given flags"); 212 | goto config_fail; 213 | } 214 | 215 | compress->snd_node = snd_utils_get_dev_node(card, device, NODE_COMPRESS); 216 | compress_type = snd_utils_get_node_type(compress->snd_node); 217 | if (compress_type == SND_NODE_TYPE_PLUGIN) 218 | compress->ops = &compr_plug_ops; 219 | else 220 | compress->ops = &compr_hw_ops; 221 | 222 | compress->fd = compress->ops->open(card, device, flags, 223 | &compress->data, compress->snd_node); 224 | if (compress->fd < 0) { 225 | oops(&bad_compress, errno, "cannot open card(%u) device(%u)", 226 | card, device); 227 | goto config_fail; 228 | } 229 | 230 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_GET_CAPS, &caps)) { 231 | oops(compress, errno, "cannot get device caps"); 232 | goto codec_fail; 233 | } 234 | 235 | /* If caller passed "don't care" fill in default values */ 236 | if ((config->fragment_size == 0) || (config->fragments == 0)) { 237 | config->fragment_size = caps.min_fragment_size; 238 | config->fragments = caps.max_fragments; 239 | } 240 | 241 | #if 0 242 | /* FIXME need to turn this On when DSP supports 243 | * and treat in no support case 244 | */ 245 | if (_is_codec_supported(compress, config, &caps) == false) { 246 | oops(compress, errno, "codec not supported\n"); 247 | goto codec_fail; 248 | } 249 | #endif 250 | 251 | memcpy(compress->config, config, sizeof(*compress->config)); 252 | fill_compress_params(config, ¶ms); 253 | 254 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_SET_PARAMS, ¶ms)) { 255 | oops(&bad_compress, errno, "cannot set device"); 256 | goto codec_fail; 257 | } 258 | 259 | return compress; 260 | 261 | codec_fail: 262 | snd_utils_put_dev_node(compress->snd_node); 263 | compress->ops->close(compress->data); 264 | compress->fd = -1; 265 | config_fail: 266 | free(compress->config); 267 | input_fail: 268 | free(compress); 269 | return &bad_compress; 270 | } 271 | 272 | void compress_close(struct compress *compress) 273 | { 274 | if (compress == &bad_compress) 275 | return; 276 | 277 | snd_utils_put_dev_node(compress->snd_node); 278 | compress->ops->close(compress->data); 279 | compress->running = 0; 280 | compress->fd = -1; 281 | free(compress->config); 282 | free(compress); 283 | } 284 | 285 | int compress_get_hpointer(struct compress *compress, 286 | unsigned int *avail, struct timespec *tstamp) 287 | { 288 | struct snd_compr_avail kavail; 289 | __u64 time; 290 | 291 | if (!is_compress_ready(compress)) 292 | return oops(compress, ENODEV, "device not ready"); 293 | 294 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_AVAIL, &kavail)) 295 | return oops(compress, errno, "cannot get avail"); 296 | if (0 == kavail.tstamp.sampling_rate) 297 | return oops(compress, ENODATA, "sample rate unknown"); 298 | *avail = (unsigned int)kavail.avail; 299 | time = kavail.tstamp.pcm_io_frames / kavail.tstamp.sampling_rate; 300 | tstamp->tv_sec = time; 301 | time = kavail.tstamp.pcm_io_frames % kavail.tstamp.sampling_rate; 302 | tstamp->tv_nsec = time * 1000000000 / kavail.tstamp.sampling_rate; 303 | return 0; 304 | } 305 | 306 | int compress_get_tstamp(struct compress *compress, 307 | unsigned long *samples, unsigned int *sampling_rate) 308 | { 309 | struct snd_compr_tstamp ktstamp; 310 | 311 | if (!is_compress_ready(compress)) 312 | return oops(compress, ENODEV, "device not ready"); 313 | 314 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_TSTAMP, &ktstamp)) 315 | return oops(compress, errno, "cannot get tstamp"); 316 | 317 | *samples = ktstamp.pcm_io_frames; 318 | *sampling_rate = ktstamp.sampling_rate; 319 | return 0; 320 | } 321 | 322 | int compress_write(struct compress *compress, const void *buf, unsigned int size) 323 | { 324 | struct snd_compr_avail avail; 325 | struct pollfd fds; 326 | int to_write = 0; /* zero indicates we haven't written yet */ 327 | int written, total = 0, ret; 328 | const char* cbuf = buf; 329 | const unsigned int frag_size = compress->config->fragment_size; 330 | 331 | if (!(compress->flags & COMPRESS_IN)) 332 | return oops(compress, EINVAL, "Invalid flag set"); 333 | if (!is_compress_ready(compress)) 334 | return oops(compress, ENODEV, "device not ready"); 335 | fds.events = POLLOUT; 336 | 337 | /*TODO: treat auto start here first */ 338 | while (size) { 339 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_AVAIL, &avail)) 340 | return oops(compress, errno, "cannot get avail"); 341 | 342 | /* We can write if we have at least one fragment available 343 | * or there is enough space for all remaining data 344 | */ 345 | if ((avail.avail < frag_size) && (avail.avail < size)) { 346 | 347 | if (compress->nonblocking) 348 | return total; 349 | 350 | ret = compress->ops->poll(compress->data, &fds, 1, 351 | compress->max_poll_wait_ms); 352 | if (fds.revents & POLLERR) { 353 | return oops(compress, EIO, "poll returned error!"); 354 | } 355 | /* A pause will cause -EBADFD or zero. 356 | * This is not an error, just stop writing */ 357 | if ((ret == 0) || (ret < 0 && errno == EBADFD)) 358 | break; 359 | if (ret < 0) 360 | return oops(compress, errno, "poll error"); 361 | if (fds.revents & POLLOUT) { 362 | continue; 363 | } 364 | } 365 | /* write avail bytes */ 366 | if (size > avail.avail) 367 | to_write = avail.avail; 368 | else 369 | to_write = size; 370 | written = compress->ops->write(compress->data, cbuf, to_write); 371 | if (written < 0) { 372 | /* If play was paused the write returns -EBADFD */ 373 | if (errno == EBADFD) 374 | break; 375 | return oops(compress, errno, "write failed!"); 376 | } 377 | 378 | size -= written; 379 | cbuf += written; 380 | total += written; 381 | } 382 | return total; 383 | } 384 | 385 | int compress_read(struct compress *compress, void *buf, unsigned int size) 386 | { 387 | struct snd_compr_avail avail; 388 | struct pollfd fds; 389 | int to_read = 0; 390 | int num_read, total = 0, ret; 391 | char* cbuf = buf; 392 | const unsigned int frag_size = compress->config->fragment_size; 393 | 394 | if (!(compress->flags & COMPRESS_OUT)) 395 | return oops(compress, EINVAL, "Invalid flag set"); 396 | if (!is_compress_ready(compress)) 397 | return oops(compress, ENODEV, "device not ready"); 398 | fds.events = POLLIN; 399 | 400 | while (size) { 401 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_AVAIL, &avail)) 402 | return oops(compress, errno, "cannot get avail"); 403 | 404 | if ( (avail.avail < frag_size) && (avail.avail < size) ) { 405 | /* Less than one fragment available and not at the 406 | * end of the read, so poll 407 | */ 408 | if (compress->nonblocking) 409 | return total; 410 | 411 | ret = compress->ops->poll(compress->data, &fds, 1, 412 | compress->max_poll_wait_ms); 413 | if (fds.revents & POLLERR) { 414 | return oops(compress, EIO, "poll returned error!"); 415 | } 416 | /* A pause will cause -EBADFD or zero. 417 | * This is not an error, just stop reading */ 418 | if ((ret == 0) || (ret < 0 && errno == EBADFD)) 419 | break; 420 | if (ret < 0) 421 | return oops(compress, errno, "poll error"); 422 | if (fds.revents & POLLIN) { 423 | continue; 424 | } 425 | } 426 | /* read avail bytes */ 427 | if (size > avail.avail) 428 | to_read = avail.avail; 429 | else 430 | to_read = size; 431 | num_read = compress->ops->read(compress->data, cbuf, to_read); 432 | if (num_read < 0) { 433 | /* If play was paused the read returns -EBADFD */ 434 | if (errno == EBADFD) 435 | break; 436 | return oops(compress, errno, "read failed!"); 437 | } 438 | 439 | size -= num_read; 440 | cbuf += num_read; 441 | total += num_read; 442 | } 443 | 444 | return total; 445 | } 446 | 447 | int compress_start(struct compress *compress) 448 | { 449 | if (!is_compress_ready(compress)) 450 | return oops(compress, ENODEV, "device not ready"); 451 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_START)) 452 | return oops(compress, errno, "cannot start the stream"); 453 | compress->running = 1; 454 | return 0; 455 | 456 | } 457 | 458 | int compress_stop(struct compress *compress) 459 | { 460 | if (!is_compress_running(compress)) 461 | return oops(compress, ENODEV, "device not ready"); 462 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_STOP)) 463 | return oops(compress, errno, "cannot stop the stream"); 464 | return 0; 465 | } 466 | 467 | int compress_pause(struct compress *compress) 468 | { 469 | if (!is_compress_running(compress)) 470 | return oops(compress, ENODEV, "device not ready"); 471 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_PAUSE)) 472 | return oops(compress, errno, "cannot pause the stream"); 473 | return 0; 474 | } 475 | 476 | int compress_resume(struct compress *compress) 477 | { 478 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_RESUME)) 479 | return oops(compress, errno, "cannot resume the stream"); 480 | return 0; 481 | } 482 | 483 | int compress_drain(struct compress *compress) 484 | { 485 | if (!is_compress_running(compress)) 486 | return oops(compress, ENODEV, "device not ready"); 487 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_DRAIN)) 488 | return oops(compress, errno, "cannot drain the stream"); 489 | return 0; 490 | } 491 | 492 | int compress_partial_drain(struct compress *compress) 493 | { 494 | if (!is_compress_running(compress)) 495 | return oops(compress, ENODEV, "device not ready"); 496 | 497 | if (!compress->next_track) 498 | return oops(compress, EPERM, "next track not signalled"); 499 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_PARTIAL_DRAIN)) 500 | return oops(compress, errno, "cannot drain the stream\n"); 501 | compress->next_track = 0; 502 | return 0; 503 | } 504 | 505 | int compress_next_track(struct compress *compress) 506 | { 507 | if (!is_compress_running(compress)) 508 | return oops(compress, ENODEV, "device not ready"); 509 | 510 | if (!compress->gapless_metadata) 511 | return oops(compress, EPERM, "metadata not set"); 512 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_NEXT_TRACK)) 513 | return oops(compress, errno, "cannot set next track\n"); 514 | compress->next_track = 1; 515 | compress->gapless_metadata = 0; 516 | return 0; 517 | } 518 | 519 | int compress_set_gapless_metadata(struct compress *compress, 520 | struct compr_gapless_mdata *mdata) 521 | { 522 | struct snd_compr_metadata metadata; 523 | int version; 524 | 525 | if (!is_compress_ready(compress)) 526 | return oops(compress, ENODEV, "device not ready"); 527 | 528 | version = get_compress_version(compress); 529 | if (version <= 0) 530 | return -1; 531 | 532 | if (version < SNDRV_PROTOCOL_VERSION(0, 1, 1)) 533 | return oops(compress, ENXIO, "gapless apis not supported in kernel"); 534 | 535 | metadata.key = SNDRV_COMPRESS_ENCODER_PADDING; 536 | metadata.value[0] = mdata->encoder_padding; 537 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_SET_METADATA, &metadata)) 538 | return oops(compress, errno, "can't set metadata for stream\n"); 539 | 540 | metadata.key = SNDRV_COMPRESS_ENCODER_DELAY; 541 | metadata.value[0] = mdata->encoder_delay; 542 | if (compress->ops->ioctl(compress->data, SNDRV_COMPRESS_SET_METADATA, &metadata)) 543 | return oops(compress, errno, "can't set metadata for stream\n"); 544 | compress->gapless_metadata = 1; 545 | return 0; 546 | } 547 | 548 | #ifdef ENABLE_EXTENDED_COMPRESS_FORMAT 549 | int compress_set_next_track_param(struct compress *compress, 550 | union snd_codec_options *codec_options) 551 | { 552 | if (!is_compress_running(compress)) 553 | return oops(compress, ENODEV, "device not ready"); 554 | 555 | if (ioctl(compress->fd, SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM, codec_options)) 556 | return oops(compress, errno, "cannot set next track params\n"); 557 | return 0; 558 | } 559 | #endif 560 | 561 | bool is_codec_supported(unsigned int card, unsigned int device, 562 | unsigned int flags, struct snd_codec *codec) 563 | { 564 | struct compress_ops *ops; 565 | void *snd_node, *data; 566 | bool ret; 567 | int compress_type, fd; 568 | 569 | snd_node = snd_utils_get_dev_node(card, device, NODE_COMPRESS); 570 | compress_type = snd_utils_get_node_type(snd_node); 571 | if (compress_type == SND_NODE_TYPE_PLUGIN) 572 | ops = &compr_plug_ops; 573 | else 574 | ops = &compr_hw_ops; 575 | 576 | fd = ops->open(card, device, flags, &data, NULL); 577 | if (fd < 0) 578 | return oops(&bad_compress, errno, "cannot open card %u, device %u", 579 | card, device); 580 | 581 | ret = _is_codec_type_supported(ops, data, codec); 582 | 583 | snd_utils_put_dev_node(snd_node); 584 | ops->close(data); 585 | return ret; 586 | } 587 | 588 | void compress_set_max_poll_wait(struct compress *compress, int milliseconds) 589 | { 590 | compress->max_poll_wait_ms = milliseconds; 591 | } 592 | 593 | void compress_nonblock(struct compress *compress, int nonblock) 594 | { 595 | compress->nonblocking = !!nonblock; 596 | } 597 | 598 | int compress_wait(struct compress *compress, int timeout_ms) 599 | { 600 | struct pollfd fds; 601 | int ret; 602 | 603 | fds.events = POLLOUT | POLLIN; 604 | 605 | ret = compress->ops->poll(compress->data, &fds, 1, timeout_ms); 606 | if (ret > 0) { 607 | if (fds.revents & POLLERR) 608 | return oops(compress, EIO, "poll returned error!"); 609 | if (fds.revents & (POLLOUT | POLLIN)) 610 | return 0; 611 | } 612 | if (ret == 0) 613 | return oops(compress, ETIME, "poll timed out"); 614 | if (ret < 0) 615 | return oops(compress, errno, "poll error"); 616 | 617 | return oops(compress, EIO, "poll signalled unhandled event"); 618 | } 619 | 620 | #ifdef ENABLE_EXTENDED_COMPRESS_FORMAT 621 | int compress_get_metadata(struct compress *compress, 622 | struct snd_compr_metadata *mdata) { 623 | int version; 624 | if (!is_compress_ready(compress)) 625 | return oops(compress, ENODEV, "device not ready"); 626 | 627 | version = get_compress_version(compress); 628 | if (version <= 0) 629 | return -1; 630 | 631 | if (ioctl(compress->fd, SNDRV_COMPRESS_GET_METADATA, mdata)) { 632 | return oops(compress, errno, "can't get metadata for stream\n"); 633 | } 634 | return 0; 635 | } 636 | 637 | int compress_set_metadata(struct compress *compress, 638 | struct snd_compr_metadata *mdata) { 639 | 640 | int version; 641 | if (!is_compress_ready(compress)) 642 | return oops(compress, ENODEV, "device not ready"); 643 | 644 | version = get_compress_version(compress); 645 | if (version <= 0) 646 | return -1; 647 | 648 | if (ioctl(compress->fd, SNDRV_COMPRESS_SET_METADATA, mdata)) { 649 | return oops(compress, errno, "can't set metadata for stream\n"); 650 | } 651 | return 0; 652 | } 653 | #endif 654 | --------------------------------------------------------------------------------