├── AUTHORS ├── COPYING ├── ChangeLog ├── Doxyfile ├── INSTALL ├── Makefile.am ├── NEWS ├── README ├── README.md ├── README_equalizer ├── THANKS ├── TODO ├── alsa.c ├── alsa.h ├── audio.c ├── audio.h ├── audio_conversion.c ├── audio_conversion.h ├── common.c ├── common.h ├── compat.c ├── compat.h ├── compiler.h ├── config.example.in ├── config.rpath ├── configure.in ├── decoder.c ├── decoder.h ├── decoder_plugins ├── Makefile.am ├── aac │ ├── Makefile.am │ ├── aac.c │ └── aac.m4 ├── decoders.m4 ├── ffmpeg │ ├── Makefile.am │ ├── ffmpeg.c │ └── ffmpeg.m4 ├── flac │ ├── Makefile.am │ ├── flac.c │ └── flac.m4 ├── modplug │ ├── Makefile.am │ ├── modplug.c │ └── modplug.m4 ├── mp3 │ ├── Makefile.am │ ├── mp3.c │ ├── mp3.m4 │ ├── xing.c │ └── xing.h ├── musepack │ ├── Makefile.am │ ├── musepack.c │ └── musepack.m4 ├── sidplay2 │ ├── Makefile.am │ ├── sidplay2.cc │ ├── sidplay2.h │ └── sidplay2.m4 ├── sndfile │ ├── Makefile.am │ ├── sndfile.c │ └── sndfile.m4 ├── speex │ ├── Makefile.am │ ├── speex.c │ └── speex.m4 ├── timidity │ ├── Makefile.am │ ├── timidity.c │ └── timidity.m4 ├── vorbis │ ├── Makefile.am │ ├── vorbis.c │ └── vorbis.m4 └── wavpack │ ├── Makefile.am │ ├── wavpack.c │ └── wavpack.m4 ├── doxy_pages ├── decoder_api.doxy ├── main_page.doxy └── sound_output_driver_api.doxy ├── equalizer.c ├── equalizer.h ├── fifo_buf.c ├── fifo_buf.h ├── files.c ├── files.h ├── interface.c ├── interface.h ├── interface_elements.c ├── interface_elements.h ├── io.c ├── io.h ├── io_curl.c ├── io_curl.h ├── jack.c ├── jack.h ├── keymap.example ├── keys.c ├── keys.h ├── lists.c ├── lists.h ├── log.c ├── log.h ├── lyrics.c ├── lyrics.h ├── m4 ├── ax_c___attribute__.m4 ├── ax_cflags_gcc_option.m4 ├── ax_compare_version.m4 ├── ax_gcc_func_attribute.m4 ├── ax_gcc_var_attribute.m4 ├── ax_path_bdb.m4 ├── ax_pthread.m4 ├── ax_require_defined.m4 └── ax_with_curses.m4 ├── main.c ├── md5.c ├── md5.h ├── menu.c ├── menu.h ├── mocp.1 ├── null_out.c ├── null_out.h ├── options.c ├── options.h ├── oss.c ├── oss.h ├── out_buf.c ├── out_buf.h ├── player.c ├── player.h ├── playlist.c ├── playlist.h ├── playlist_file.c ├── playlist_file.h ├── protocol.c ├── protocol.h ├── rbtree.c ├── rbtree.h ├── rcc.c ├── rcc.h ├── server.c ├── server.h ├── sndio_out.c ├── sndio_out.h ├── softmixer.c ├── softmixer.h ├── tags_cache.c ├── tags_cache.h ├── themes.c ├── themes.h ├── themes ├── Makefile.am ├── black_theme ├── darkdot_theme ├── example_theme ├── green_theme ├── moca_theme ├── nightly_theme ├── red_theme ├── transparent-background ├── transparent-background_screenshot_thumb.png ├── variant_red_theme └── yellow_red_theme ├── tools ├── README ├── maketests.sh └── md5check.sh ├── utf8.c └── utf8.h /AUTHORS: -------------------------------------------------------------------------------- 1 | Damian Pietras 2 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | See the NEWS file. 2 | -------------------------------------------------------------------------------- /Doxyfile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = MOC 2 | PROJECT_NUMBER = 2.6-alpha3 3 | OUTPUT_DIRECTORY = technical_docs 4 | CREATE_SUBDIRS = NO 5 | OUTPUT_LANGUAGE = English 6 | USE_WINDOWS_ENCODING = NO 7 | BRIEF_MEMBER_DESC = YES 8 | REPEAT_BRIEF = YES 9 | ABBREVIATE_BRIEF = 10 | ALWAYS_DETAILED_SEC = NO 11 | INLINE_INHERITED_MEMB = NO 12 | FULL_PATH_NAMES = YES 13 | STRIP_FROM_PATH = 14 | STRIP_FROM_INC_PATH = 15 | SHORT_NAMES = NO 16 | JAVADOC_AUTOBRIEF = YES 17 | MULTILINE_CPP_IS_BRIEF = NO 18 | DETAILS_AT_TOP = NO 19 | INHERIT_DOCS = YES 20 | DISTRIBUTE_GROUP_DOC = YES 21 | TAB_SIZE = 8 22 | ALIASES = 23 | OPTIMIZE_OUTPUT_FOR_C = YES 24 | OPTIMIZE_OUTPUT_JAVA = NO 25 | SUBGROUPING = YES 26 | EXTRACT_ALL = YES 27 | EXTRACT_PRIVATE = YES 28 | EXTRACT_STATIC = NO 29 | EXTRACT_LOCAL_CLASSES = YES 30 | EXTRACT_LOCAL_METHODS = NO 31 | HIDE_UNDOC_MEMBERS = YES 32 | HIDE_UNDOC_CLASSES = YES 33 | HIDE_FRIEND_COMPOUNDS = NO 34 | HIDE_IN_BODY_DOCS = NO 35 | INTERNAL_DOCS = NO 36 | CASE_SENSE_NAMES = YES 37 | HIDE_SCOPE_NAMES = NO 38 | SHOW_INCLUDE_FILES = NO 39 | INLINE_INFO = YES 40 | SORT_MEMBER_DOCS = YES 41 | SORT_BRIEF_DOCS = NO 42 | SORT_BY_SCOPE_NAME = NO 43 | GENERATE_TODOLIST = YES 44 | GENERATE_TESTLIST = YES 45 | GENERATE_BUGLIST = YES 46 | GENERATE_DEPRECATEDLIST= YES 47 | ENABLED_SECTIONS = 48 | MAX_INITIALIZER_LINES = 30 49 | SHOW_USED_FILES = YES 50 | SHOW_DIRECTORIES = NO 51 | FILE_VERSION_FILTER = 52 | QUIET = NO 53 | WARNINGS = YES 54 | WARN_IF_UNDOCUMENTED = YES 55 | WARN_IF_DOC_ERROR = YES 56 | WARN_NO_PARAMDOC = NO 57 | WARN_FORMAT = "$file:$line: $text" 58 | WARN_LOGFILE = 59 | INPUT = 60 | FILE_PATTERNS = *.c *.h *.doxy 61 | RECURSIVE = YES 62 | EXCLUDE = 63 | EXCLUDE_SYMLINKS = NO 64 | EXCLUDE_PATTERNS = 65 | EXAMPLE_PATH = 66 | EXAMPLE_PATTERNS = 67 | EXAMPLE_RECURSIVE = NO 68 | IMAGE_PATH = 69 | INPUT_FILTER = 70 | FILTER_PATTERNS = 71 | FILTER_SOURCE_FILES = NO 72 | SOURCE_BROWSER = NO 73 | INLINE_SOURCES = NO 74 | STRIP_CODE_COMMENTS = YES 75 | REFERENCED_BY_RELATION = YES 76 | REFERENCES_RELATION = YES 77 | VERBATIM_HEADERS = YES 78 | ALPHABETICAL_INDEX = NO 79 | COLS_IN_ALPHA_INDEX = 5 80 | IGNORE_PREFIX = 81 | GENERATE_HTML = YES 82 | HTML_OUTPUT = html 83 | HTML_FILE_EXTENSION = .html 84 | HTML_HEADER = 85 | HTML_FOOTER = 86 | HTML_STYLESHEET = 87 | HTML_ALIGN_MEMBERS = YES 88 | GENERATE_HTMLHELP = NO 89 | CHM_FILE = 90 | HHC_LOCATION = 91 | GENERATE_CHI = NO 92 | BINARY_TOC = NO 93 | TOC_EXPAND = NO 94 | DISABLE_INDEX = NO 95 | ENUM_VALUES_PER_LINE = 4 96 | GENERATE_TREEVIEW = NO 97 | TREEVIEW_WIDTH = 250 98 | GENERATE_LATEX = YES 99 | LATEX_OUTPUT = latex 100 | LATEX_CMD_NAME = latex 101 | MAKEINDEX_CMD_NAME = makeindex 102 | COMPACT_LATEX = NO 103 | PAPER_TYPE = a4wide 104 | EXTRA_PACKAGES = 105 | LATEX_HEADER = 106 | PDF_HYPERLINKS = NO 107 | USE_PDFLATEX = NO 108 | LATEX_BATCHMODE = NO 109 | LATEX_HIDE_INDICES = NO 110 | GENERATE_RTF = NO 111 | RTF_OUTPUT = rtf 112 | COMPACT_RTF = NO 113 | RTF_HYPERLINKS = NO 114 | RTF_STYLESHEET_FILE = 115 | RTF_EXTENSIONS_FILE = 116 | GENERATE_MAN = NO 117 | MAN_OUTPUT = man 118 | MAN_EXTENSION = .3 119 | MAN_LINKS = NO 120 | GENERATE_XML = NO 121 | XML_OUTPUT = xml 122 | XML_SCHEMA = 123 | XML_DTD = 124 | XML_PROGRAMLISTING = YES 125 | GENERATE_AUTOGEN_DEF = NO 126 | GENERATE_PERLMOD = NO 127 | PERLMOD_LATEX = NO 128 | PERLMOD_PRETTY = YES 129 | PERLMOD_MAKEVAR_PREFIX = 130 | ENABLE_PREPROCESSING = YES 131 | MACRO_EXPANSION = NO 132 | EXPAND_ONLY_PREDEF = NO 133 | SEARCH_INCLUDES = YES 134 | INCLUDE_PATH = 135 | INCLUDE_FILE_PATTERNS = 136 | PREDEFINED = 137 | EXPAND_AS_DEFINED = 138 | SKIP_FUNCTION_MACROS = YES 139 | TAGFILES = 140 | GENERATE_TAGFILE = 141 | ALLEXTERNALS = NO 142 | EXTERNAL_GROUPS = YES 143 | PERL_PATH = /usr/bin/perl 144 | CLASS_DIAGRAMS = YES 145 | HIDE_UNDOC_RELATIONS = YES 146 | HAVE_DOT = NO 147 | CLASS_GRAPH = YES 148 | COLLABORATION_GRAPH = YES 149 | GROUP_GRAPHS = YES 150 | UML_LOOK = NO 151 | TEMPLATE_RELATIONS = NO 152 | INCLUDE_GRAPH = YES 153 | INCLUDED_BY_GRAPH = YES 154 | CALL_GRAPH = NO 155 | GRAPHICAL_HIERARCHY = YES 156 | DIRECTORY_GRAPH = YES 157 | DOT_IMAGE_FORMAT = png 158 | DOT_PATH = 159 | DOTFILE_DIRS = 160 | MAX_DOT_GRAPH_WIDTH = 1024 161 | MAX_DOT_GRAPH_HEIGHT = 1024 162 | MAX_DOT_GRAPH_DEPTH = 0 163 | DOT_TRANSPARENT = NO 164 | DOT_MULTI_TARGETS = NO 165 | GENERATE_LEGEND = YES 166 | DOT_CLEANUP = YES 167 | SEARCHENGINE = NO 168 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | SUBDIRS = themes decoder_plugins 3 | AM_CPPFLAGS = -DSYSTEM_THEMES_DIR=\"$(pkgdatadir)/themes\" \ 4 | -DPLUGIN_DIR=\"$(plugindir)/$(DECODER_PLUGIN_DIR)\" 5 | 6 | bin_PROGRAMS = mocp 7 | mocp_SOURCES = log.c \ 8 | log.h \ 9 | protocol.h \ 10 | protocol.c \ 11 | server.c \ 12 | server.h \ 13 | main.c \ 14 | common.c \ 15 | common.h \ 16 | compiler.h \ 17 | playlist.c \ 18 | playlist.h \ 19 | fifo_buf.c \ 20 | fifo_buf.h \ 21 | out_buf.c \ 22 | out_buf.h \ 23 | audio.c \ 24 | audio.h \ 25 | decoder.c \ 26 | decoder.h \ 27 | interface.c \ 28 | interface.h \ 29 | interface_elements.c \ 30 | interface_elements.h \ 31 | menu.c \ 32 | menu.h \ 33 | files.c \ 34 | files.h \ 35 | options.c \ 36 | options.h \ 37 | player.c \ 38 | player.h \ 39 | playlist_file.c \ 40 | playlist_file.h \ 41 | themes.c \ 42 | themes.h \ 43 | keys.c \ 44 | keys.h \ 45 | io.c \ 46 | io.h \ 47 | compat.c \ 48 | compat.h \ 49 | audio_conversion.c \ 50 | audio_conversion.h \ 51 | rbtree.c \ 52 | rbtree.h \ 53 | tags_cache.c \ 54 | tags_cache.h \ 55 | utf8.c \ 56 | utf8.h \ 57 | rcc.c \ 58 | rcc.h \ 59 | softmixer.c \ 60 | softmixer.h \ 61 | lyrics.h \ 62 | lyrics.c \ 63 | lists.h \ 64 | lists.c \ 65 | equalizer.h \ 66 | equalizer.c 67 | EXTRA_mocp_SOURCES = \ 68 | md5.c \ 69 | md5.h \ 70 | null_out.c \ 71 | null_out.h \ 72 | sndio_out.c \ 73 | sndio_out.h \ 74 | oss.c \ 75 | oss.h \ 76 | alsa.c \ 77 | alsa.h \ 78 | io_curl.c \ 79 | io_curl.h \ 80 | jack.c \ 81 | jack.h 82 | man_MANS = mocp.1 83 | mocp_LDADD = @EXTRA_OBJS@ -lltdl -lm 84 | mocp_DEPENDENCIES = @EXTRA_OBJS@ 85 | mocp_LDFLAGS = @EXTRA_LIBS@ $(RCC_LIBS) -export-dynamic 86 | EXTRA_DIST = README_equalizer mocp.1 THANKS keymap.example Doxyfile \ 87 | doxy_pages/decoder_api.doxy doxy_pages/main_page.doxy \ 88 | doxy_pages/sound_output_driver_api.doxy 89 | EXTRA_DIST += @EXTRA_DISTS@ 90 | EXTRA_DIST += tools/README tools/md5check.sh tools/maketests.sh 91 | noinst_DATA = tools/README 92 | noinst_SCRIPTS = tools/md5check.sh tools/maketests.sh 93 | 94 | doc_DATA = config.example THANKS README README_equalizer keymap.example 95 | -------------------------------------------------------------------------------- /README_equalizer: -------------------------------------------------------------------------------- 1 | Preamble 2 | --- 3 | This document is meant to give you an overview on the idea of having a 4 | parametric equalizer for sound enhancement and how you can create your 5 | own presets. Also the interaction with the equalizer in MOC is described. 6 | 7 | I would like to improve this document to make it more usable; so if you 8 | have any comments and/or ideas feel free to contact me. 9 | 10 | - Hendrik Iben (hibentzi(dot)de) 11 | 12 | 13 | Content 14 | --- 15 | 0. Document History 16 | 1. Motivation 17 | 2. Usage 18 | 3. Preset Format 19 | 4. Creating Presets 20 | 5. TODO 21 | 6. References 22 | 23 | 24 | 0. Document History 25 | --- 26 | 07.09.2008 - Initial version 27 | 15.03.2011 - Reformatted 28 | 29 | 30 | 1. Nuts and Bolts / Motivation for Implementing the Equalizer 31 | --- 32 | The equalizer is an implementation of a biquadratic peaking equalizer 33 | filter looked up from the Audio EQ Cookbook[1]. 34 | 35 | It happens to be a parametric equalizer and this means that, different 36 | from other equalizer implementations, the number of bands* is not fixed. 37 | When I started the idea of implementing the equalizer I looked around 38 | in the source of other audio playback software and found that a lot of 39 | them are recycling the code used by the famous XMMS[2] audio player. 40 | I also would have liked to recycle the code but I decided against it 41 | for two reasons: 42 | 43 | The first reason is that there is almost no documentation on the algorithm 44 | used. Maybe the signal processing folks have fun finding out what makes 45 | this thing work but I was totally lost. So I decided that I wanted to 46 | *know* what I am doing if I do it. 47 | 48 | As for the second reason, the code used by XMMS is totally optimized for 49 | integer arithmetic. There is no problem with this in general but I had 50 | the goal of implementing something that was as accurate as I could and 51 | I wanted to use floating point arithmetic. 52 | 53 | So I am no signals processing guy, but I have -- I think -- a solid 54 | understanding of the matter. I sat down and started to read about 55 | equalizing, audio processing and signal theory in general. After some 56 | time I found a mathematical description and a C implementation of 57 | biquadratic filters in the Audio Cookbook. I made an implementation of 58 | the XMMS equalizer and the biquadratic filter using Octave[3] to compare 59 | the outcome of both filters. I was a bit surprised how different filters 60 | can be but in the end succeeded (?) in finding a quite good biquadratic 61 | filter set that would produce results not unlike the XMMS equalizer. 62 | 63 | Although I did not use the XMMS-code I think that people will be more 64 | happy to accept this equalizer if they can use their presets with it. 65 | There is some conversion needed, but it's a straightforward process. 66 | I converted all presets provided by XMMS into presets for this mixer. 67 | They should be available at [4]. 68 | 69 | * A band is a chosen center frequency where a filter has most impact. 70 | If you look at WinAmp / XMMS / Beep Media Player you will find that 71 | they settled on a common set of 10 bands. 72 | 73 | 74 | 2. Using the Equalizer 75 | --- 76 | The default keys for the equalizer are: 77 | 78 | 'e' - Refresh equalizer 79 | 'E' - Toggle equalizer (on/off) 80 | 'k' - Select next preset 81 | 'K' - Select previous preset 82 | 83 | Each of these actions results in a message displayed in the message area. 84 | This message will be overridden by the next action. 85 | 86 | 87 | 3. Preset Format 88 | --- 89 | Presets for the equalizer are to be placed in a directory called 'eqsets' 90 | in MOC's home directory (e.g., $HOME/.moc/eqsets). There is no convention 91 | for the filename, but it will serve as the name in the selection process. 92 | 93 | File format in pseudo EBNF: 94 | 95 | EQSET 96 | (( )|(0 ))* 97 | 98 | CF: Center frequency (sane values are from ~20 to ~20000). 99 | BW: Bandwith in Octaves. This defines how fast the bands 100 | influence vanishes over the frequencies. 101 | AMP: Amplification factor (in dB) to apply to the band. 102 | PREAMP: Specifies an amplification factor applied before equalizing. 103 | 104 | So a valid equalizer set would be: 105 | 106 | # this is a comment 107 | EQSET 108 | # amplify audio by 1.4dB 109 | 0 1.4 110 | # damp frequencies at 100Hz by -4dB, filter bandwidth 1.5 octaves 111 | 100 1.5 -4 112 | # amplify frequencies at 4000Hz by 2dB, filter bandwidth 1.5 octaves 113 | 4000 1.5 2 114 | 115 | There is no order to stick to when specifying frequencies. 116 | 117 | 118 | 4. Creating Your Own Presets 119 | --- 120 | For a start you should have a look at the converted presets[4]. The 121 | bandwidths used in the conversion have been extracted by taking a look 122 | at the filters signal response (implementation and analysis in Octave). 123 | I tried to do this as accurately as possible but I don't know if I made 124 | a mistake. They sound correct though... :-) 125 | 126 | You might note that there is never a positive amplification factor in 127 | the presets although there are in the original preset. The reason for 128 | this is that I used the maximum amplification in the preset as zero 129 | amplification and adjusted the other values accordingly. 130 | 131 | In general, when creating a preset get used to the following idea: Do not 132 | amplify the frequencies you want but damp those that are of no interest. 133 | This has the same effect but avoids clipping and this equalizer type seems 134 | to be very prone to clipping. Also be very careful with pre-amplifying 135 | the audio for the same reason. 136 | 137 | With that said, the next confusing thing is the bandwidth definition. 138 | Every band needs a defined bandwidth in octaves where the bandwidth 139 | defines where the filter's effect has been reduced by 3dB*. This means 140 | that if you define a band at 1000Hz with a bandwidth of 1.5 octaves and 141 | an amplification of -10dB, at 353.6Hz** and at 2828.4Hz the amplification 142 | will be reduced to -7dB. 143 | 144 | If unsure, stay in between 1.0 and 2.0. Just keep in mind that if two 145 | bands overlap you might get an undesired amplification. 146 | 147 | When designing presets, just save the preset and select it in MOC. After 148 | each change press the refresh key (default 'e'). This will re-create the 149 | equalizer reflecting your changes. 150 | 151 | If your preset is not found, have a look at the output of MOC's server 152 | thread. Parsing errors are emitted there. 153 | 154 | * 3dB is commonly used for bandwidth. -3dB equals about 70.7% of 155 | original amplification. 156 | ** 353.6 =~ 1000*(2^-1.5), 2828.4 =~ 1000*(2^1.5) 157 | 158 | 159 | 5. TODO 160 | --- 161 | - The equalizer is currently not optimized in any way. 162 | 163 | - It converts all sound data into floating point values to perform the 164 | equalization and converts them back afterwards. A better approach 165 | would be either to provide integer algorithms for equalization or to 166 | leave the audio data in floating point format. 167 | 168 | - There is no sorting for the presets; their order is defined by reading 169 | the directory content. 170 | 171 | - Maybe it would be nice to add a name to the preset different from the 172 | filename. 173 | 174 | 175 | 6. References 176 | --- 177 | [1] Cookbook formulae for audio EQ biquad filter coefficients 178 | http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt 179 | [2] X Multimedia System 180 | http://www.xmms.org/ 181 | [3] GNU Octave 182 | http://www.gnu.org/software/octave/ 183 | [4] Converted WinAmp / XMMS Equalizer sets 184 | http://www.informatik.uni-bremen.de/~hiben/moc/eqsets.tar.gz 185 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | This file does not list all bugs which: 2 | 3 | - are known but rarely encountered, 4 | - are not visible to the user, 5 | - are programming errors detectable only with the aid of testing tools, 6 | - are benign, or 7 | - have been reported but not yet confirmed to be attributable to MOC. 8 | 9 | It also does not contain many "To Do" items as these are often quite fluid 10 | and can evolve rapidly over time. 11 | 12 | The MOC Maintainer does hold a master list containing bugs, feature requests, 13 | program change requests and future requirements, and once it is possible to 14 | generate this file from that list automatically it may be updated more 15 | frequently so it is current and comprehensive. 16 | 17 | 18 | Known Bugs: 19 | 20 | * Character set problems: 21 | - Do we assume filesystem in UTF-8? It's incorrect. 22 | - id3tags v2.3 with UTF-16 are not properly handled by libid3tag, taglib 23 | has no problems. Need to use libtag here? 24 | - Recognition of ID3 tags v1 is broken (example: small.mp3). [node/234] 25 | - Perhaps MOC can add support for the frame field_type to differentiate 26 | between ID3_FIELD_TYPE_LATIN1 and ID3_FIELD_TYPE_STRING. [node/234] 27 | - Some national characters in file and directory names don't get displayed 28 | correctly. 29 | * Program crashes: 30 | - I have a problem with MOC 2.4.0 on FreeBSD 6.1-PRERELEASE. When I build 31 | MOC with musepack (libmpcdec) support MOC always core dumps on exit. 32 | (This may have been fixed by other storage-related patches and will be 33 | removed in MOC 2.7 if no one has confirmed it still exists.) 34 | - Using DB_THREAD in combination with DB_CREATE and DB_PRIVATE seems to 35 | cause a segfault on OpenWRT. The circumvention is to configure MOC on 36 | OpenWRT with '--disable-cache' or set the MOC configuration option 37 | 'TagsCacheSize' to zero. 38 | * Valgrind-detected memory problems: 39 | - libasound: memory leaks 40 | - libdb: uninitialised parameter storage 41 | - libffmpeg: uninitialised storage in conditions and reads 42 | - libgme: uninitialised storage in conditions and reads 43 | - libmagic: uninitialised storage in reads 44 | - librcc: uninitialised storage in conditions 45 | - libspeex: uninitialised storage in conditions and reads 46 | - The problems above occur in libraries but it needs to be determined 47 | whether they somehow arise from MOC's misuse of them. 48 | - There are many data race and mutex handling problems (particularly 49 | around the time of file-to-file transitions), but these are not visible 50 | to the users and difficult to solve without compromising gapless playback. 51 | * Directory and playlists: 52 | - When sorting by file name (directories), put files beginning with a 53 | non-alphanumeric character at the top. 54 | - mocp -a playlist.pls should not sort added files. [node/240] 55 | - Client does not show changes when a file's tags are updated by another 56 | program. 57 | - Client continues to show file names after ReadTags is toggled when 58 | MOC is started with 'ShowTime=yes' and 'ReadTags=no'. 59 | * Decoder problems: 60 | - Seeking in some formats does not work in the FFmpeg decoder because of 61 | the limitations of the FFmpeg libraries (and seeking is disabled for 62 | them). FLV also has seeking issues and is disabled but will be enabled 63 | if SEEK_IN_DECODER is set in the FFmpeg decoder plug-in. (This may be 64 | parameterised in due course.) 65 | - Some decoders do not currently pass the MD5 sum or sample count checks. 66 | - The duration of some AAC audios is incorrectly reported. This problem 67 | arises from the limitations of the format, but MOC now makes much more 68 | accurate guesses. 69 | 70 | 71 | Transitional Code Removal: 72 | 73 | * Remove TagLib version 1.5 requirement warning. 74 | * Remove Musepack libmpc (instead of libmpcdec) requirement warning. 75 | * Remove librcc raised requirement warning. 76 | 77 | 78 | Pending 2.6 Changes: 79 | 80 | * Require at least TagLib version 1.5. 81 | * Require Musepack libmpc (instead of libmpcdec). 82 | * Require at least librcc version 0.2.10. 83 | 84 | 85 | Pending 2.7 Changes: 86 | 87 | * Remove FreeBSD program crash bug if no one has confirmed it still exists. 88 | * Remove 'ALSAStutterDefeat' start-up warning. 89 | 90 | 91 | Future Wishlist (items marked with $ are bigger changes requiring more time): 92 | 93 | * Move TODO to moc.daper.net/roadmap . 94 | * A string-valued variable "TitleFormatString", similar to "FormatString". 95 | I'd suggest all the same %-escapes, plus: 96 | %F -- expands to (the expansion of) the current FormatString 97 | if there is a song playing or paused, and empty string if stopped. 98 | %S -- expands to play/stop/pause. 99 | * Command line option to play from a specified file/first from the last 100 | added files. [node/286] 101 | * Multiple file selection to move many files at once up and down. [node/288] 102 | * Review strcat()/strcpy()/sprintf() usage, change to 103 | strncat()/strncpy()/snprintf() where possible. 104 | * More side menus: many directory/playlist views. 105 | * LADSPA/LV2 106 | * Editing the title of an item on the playlist (for Internet streams). 107 | *$ Media library: tree-like menu for artists and albums. 108 | * Seek by a % value (also using keys for 10%, 20%, etc). 109 | * Ability to play from a playlist made of items found after searching. 110 | * JACK: intelligent behaviour when we get disconnected from the server 111 | - detect it, try connect and exit if it fails. 112 | * FastGo instead of FastDir: go to a directory, URL or a playlist. 113 | * Read tags for sndfile formats. 114 | *$ http://www.peercast.org/ 115 | * Crossfade. 116 | * Command to see all information about a file with all tags, also all 117 | information about an internet stream (from IceCast headers like icy-url, 118 | icy-pub). 119 | *$ Lyrics downloaded from the Internet. 120 | * lirc. 121 | * Don't use PATH_MAX. 122 | * Seek forward using the content of the output buffer. 123 | *$ Locales. 124 | *$ Song ratings or something like Q in XMMS. 125 | * Configurable sorting. 126 | * Add a key for switching sort modes. 127 | *$ Equalizer like in Beep Media Player 128 | *$ Make equal volume level for every song like in http://volnorm.sourceforge.net 129 | *$ Replaygain. 130 | * Seek to arbitrary position (by typing a number). 131 | *$ ESD. 132 | *$ CUE-sheet. 133 | * Command line option to delete the currently played item from the playlist. 134 | * Scripting. 135 | * Some options can be changed at run-time using a menu. 136 | * posix_fadvise() with POSIX_FADV_WILLNEED instead of the input buffer thread 137 | for files. 138 | * Recording played sound to a file. 139 | * Upgrade TiMidity decoder plug-in to TiMidity++. This would add support 140 | for soundfonts (.sf2) which are now more common. 141 | 142 | 143 | Maybe Never: 144 | 145 | * Report ignored server-specific options when the server is not being run. 146 | * Funny ASCII equalizer. 147 | * Mouse support. [node/743] 148 | -------------------------------------------------------------------------------- /alsa.h: -------------------------------------------------------------------------------- 1 | #ifndef ALSA_H 2 | #define ALSA_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void alsa_funcs (struct hw_funcs *funcs); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /audio_conversion.h: -------------------------------------------------------------------------------- 1 | #ifndef AUDIO_CONVERSION_H 2 | #define AUDIO_CONVERSION_H 3 | 4 | #ifdef HAVE_STDINT_H 5 | # include 6 | #endif 7 | 8 | #include 9 | 10 | #ifdef HAVE_SAMPLERATE 11 | # include 12 | #endif 13 | 14 | #include "audio.h" 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | struct audio_conversion 21 | { 22 | struct sound_params from; 23 | struct sound_params to; 24 | 25 | #ifdef HAVE_SAMPLERATE 26 | SRC_STATE *src_state; 27 | float *resample_buf; 28 | size_t resample_buf_nsamples; /* in samples ( sizeof(float) ) */ 29 | #endif 30 | 31 | }; 32 | 33 | int audio_conv_new (struct audio_conversion *conv, 34 | const struct sound_params *from, 35 | const struct sound_params *to); 36 | char *audio_conv (struct audio_conversion *conv, 37 | const char *buf, const size_t size, size_t *conv_len); 38 | void audio_conv_destroy (struct audio_conversion *conv); 39 | 40 | void audio_conv_bswap_16 (int16_t *buf, const size_t num); 41 | void audio_conv_bswap_32 (int32_t *buf, const size_t num); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The purpose of this header is to provide common functions and macros 3 | * used throughout MOC code. It also provides (x-prefixed) functions 4 | * which augment or adapt their respective system functions with error 5 | * checking and the like. 6 | */ 7 | 8 | #ifndef COMMON_H 9 | #define COMMON_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "compat.h" 17 | 18 | /* Suppress overly-enthusiastic GNU variadic macro extensions warning. */ 19 | #if defined(__clang__) && HAVE_VARIADIC_MACRO_WARNING 20 | # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 21 | #endif 22 | 23 | struct timespec; 24 | 25 | #ifdef HAVE_FUNC_ATTRIBUTE_FORMAT 26 | # define ATTR_PRINTF(x,y) __attribute__ ((format (printf, x, y))) 27 | #else 28 | # define ATTR_PRINTF(...) 29 | #endif 30 | 31 | #ifdef HAVE_FUNC_ATTRIBUTE_NORETURN 32 | # define ATTR_NORETURN __attribute__((noreturn)) 33 | #else 34 | # define ATTR_NORETURN 35 | #endif 36 | 37 | #ifdef HAVE_VAR_ATTRIBUTE_UNUSED 38 | # define ATTR_UNUSED __attribute__((unused)) 39 | #else 40 | # define ATTR_UNUSED 41 | #endif 42 | 43 | #ifndef GCC_VERSION 44 | #define GCC_VERSION (__GNUC__ * 10000 + \ 45 | __GNUC_MINOR__ * 100 + \ 46 | __GNUC_PATCHLEVEL__) 47 | #endif 48 | 49 | /* These macros allow us to use the appropriate method for manipulating 50 | * GCC's diagnostic pragmas depending on the compiler's version. */ 51 | #if GCC_VERSION >= 40200 52 | # define GCC_DIAG_STR(s) #s 53 | # define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y) 54 | # define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) 55 | # define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) 56 | # if GCC_VERSION >= 40600 57 | # define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \ 58 | GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) 59 | # define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop) 60 | # else 61 | # define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) 62 | # define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x)) 63 | # endif 64 | #else 65 | # define GCC_DIAG_OFF(x) 66 | # define GCC_DIAG_ON(x) 67 | #endif 68 | 69 | #ifdef HAVE_FORMAT_TRUNCATION_WARNING 70 | # define SUPPRESS_FORMAT_TRUNCATION_WARNING GCC_DIAG_OFF(format-truncation) 71 | # define UNSUPPRESS_FORMAT_TRUNCATION_WARNING GCC_DIAG_ON(format-truncation) 72 | #else 73 | # define SUPPRESS_FORMAT_TRUNCATION_WARNING 74 | # define UNSUPPRESS_FORMAT_TRUNCATION_WARNING 75 | #endif 76 | 77 | #define CONFIG_DIR ".moc" 78 | #define LOCK(mutex) pthread_mutex_lock (&mutex) 79 | #define UNLOCK(mutex) pthread_mutex_unlock (&mutex) 80 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 81 | #define ssizeof(x) ((ssize_t) sizeof(x)) 82 | 83 | /* Maximal string length sent/received. */ 84 | #define MAX_SEND_STRING 4096 85 | 86 | /* Exit status on fatal error. */ 87 | #define EXIT_FATAL 2 88 | 89 | #ifndef MIN 90 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 91 | #endif 92 | 93 | #ifndef MAX 94 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 95 | #endif 96 | 97 | #ifndef LIMIT 98 | #define LIMIT(val, lim) ((val) >= 0 && (val) < (lim)) 99 | #endif 100 | 101 | #ifndef RANGE 102 | #define RANGE(min, val, max) ((val) >= (min) && (val) <= (max)) 103 | #endif 104 | 105 | #ifndef CLAMP 106 | #define CLAMP(min, val, max) ((val) < (min) ? (min) : \ 107 | (val) > (max) ? (max) : (val)) 108 | #endif 109 | 110 | #ifdef NDEBUG 111 | #define error(...) \ 112 | internal_error (NULL, 0, NULL, ## __VA_ARGS__) 113 | #define fatal(...) \ 114 | internal_fatal (NULL, 0, NULL, ## __VA_ARGS__) 115 | #define ASSERT_ONLY ATTR_UNUSED 116 | #else 117 | #define error(...) \ 118 | internal_error (__FILE__, __LINE__, __func__, ## __VA_ARGS__) 119 | #define fatal(...) \ 120 | internal_fatal (__FILE__, __LINE__, __func__, ## __VA_ARGS__) 121 | #define ASSERT_ONLY 122 | #endif 123 | 124 | #ifndef STRERROR_FN 125 | # define STRERROR_FN xstrerror 126 | #endif 127 | 128 | #define error_errno(format, errnum) \ 129 | do { \ 130 | char *err##__LINE__ = STRERROR_FN (errnum); \ 131 | error (format ": %s", err##__LINE__); \ 132 | free (err##__LINE__); \ 133 | } while (0) 134 | 135 | #ifdef __cplusplus 136 | extern "C" { 137 | #endif 138 | 139 | void *xmalloc (size_t size); 140 | void *xcalloc (size_t nmemb, size_t size); 141 | void *xrealloc (void *ptr, const size_t size); 142 | char *xstrdup (const char *s); 143 | void xsleep (size_t ticks, size_t ticks_per_sec); 144 | char *xstrerror (int errnum); 145 | void xsignal (int signum, void (*func)(int)); 146 | 147 | void internal_error (const char *file, int line, const char *function, 148 | const char *format, ...) ATTR_PRINTF(4, 5); 149 | void internal_fatal (const char *file, int line, const char *function, 150 | const char *format, ...) ATTR_NORETURN ATTR_PRINTF(4, 5); 151 | void set_me_server (); 152 | char *str_repl (char *target, const char *oldstr, const char *newstr); 153 | char *trim (const char *src, size_t len); 154 | char *format_msg (const char *format, ...); 155 | char *format_msg_va (const char *format, va_list va); 156 | bool is_valid_symbol (const char *candidate); 157 | char *create_file_name (const char *file); 158 | int get_realtime (struct timespec *ts); 159 | void sec_to_min (char *buff, const int seconds); 160 | const char *get_home (); 161 | void common_cleanup (); 162 | 163 | #ifdef __cplusplus 164 | } 165 | #endif 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /compat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2005 Damian Pietras 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | */ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include "config.h" 14 | #endif 15 | 16 | /* Various functions which some systems lack. */ 17 | 18 | #ifndef HAVE_STRCASESTR 19 | #include 20 | #include 21 | 22 | /* Case insensitive version of strstr(). */ 23 | char *strcasestr (const char *haystack, const char *needle) 24 | { 25 | char *haystack_i, *needle_i; 26 | char *c; 27 | char *res; 28 | 29 | haystack_i = xstrdup (haystack); 30 | needle_i = xstrdup (needle); 31 | 32 | c = haystack_i; 33 | while (*c) { 34 | *c = tolower (*c); 35 | c++; 36 | } 37 | 38 | c = needle_i; 39 | while (*c) { 40 | *c = tolower (*c); 41 | c++; 42 | } 43 | 44 | res = strstr (haystack_i, needle_i); 45 | free (haystack_i); 46 | free (needle_i); 47 | return res ? res - haystack_i + (char *)haystack : NULL; 48 | } 49 | #endif 50 | 51 | /* This is required to prevent an "empty translation unit" warning 52 | if neither strcasestr() nor clock_gettime() get defined. */ 53 | #if defined(HAVE_STRCASESTR) && defined(HAVE_CLOCK_GETTIME) 54 | int compat_is_empty; 55 | #endif 56 | -------------------------------------------------------------------------------- /compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The purpose of this header is to provide functions and macros which 3 | * MOC code expects but which are missing or broken on the host system. 4 | * 5 | * This header should be included by all code before any other MOC 6 | * headers (except 'compiler.h'). Therefore, it is included once by 7 | * 'common.h' which is itself included by all code. 8 | */ 9 | 10 | #ifndef COMPAT_H 11 | #define COMPAT_H 12 | 13 | #ifdef HAVE_BYTESWAP_H 14 | # include 15 | #else 16 | /* Given an unsigned 16-bit argument X, return the value corresponding to 17 | X with reversed byte order. */ 18 | # define bswap_16(x) ((((x) & 0x00FF) << 8) | \ 19 | (((x) & 0xFF00) >> 8)) 20 | 21 | /* Given an unsigned 32-bit argument X, return the value corresponding to 22 | X with reversed byte order. */ 23 | # define bswap_32(x) ((((x) & 0x000000FF) << 24) | \ 24 | (((x) & 0x0000FF00) << 8) | \ 25 | (((x) & 0x00FF0000) >> 8) | \ 26 | (((x) & 0xFF000000) >> 24)) 27 | #endif 28 | 29 | #ifndef SUN_LEN 30 | #define SUN_LEN(p) \ 31 | ((sizeof *(p)) - sizeof((p)->sun_path) + strlen ((p)->sun_path)) 32 | #endif 33 | 34 | /* Maximum path length, we don't consider exceptions like mounted NFS */ 35 | #ifndef PATH_MAX 36 | # if defined(_POSIX_PATH_MAX) 37 | # define PATH_MAX _POSIX_PATH_MAX /* Posix */ 38 | # elif defined(MAXPATHLEN) 39 | # define PATH_MAX MAXPATHLEN /* Solaris? Also linux...*/ 40 | # else 41 | # define PATH_MAX 4096 /* Suppose, we have 4096 */ 42 | # endif 43 | #endif 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | #if !HAVE_DECL_STRCASESTR && !defined(__cplusplus) 50 | char *strcasestr (const char *haystack, const char *needle); 51 | #endif 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /compiler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The purpose of this header is to configure the compiler and system 3 | * headers the way we want them to be. It should be included in every 4 | * source code file *before* any system headers are included, and thus 5 | * an include for it is automatically appended to the 'config.h' header 6 | * by 'configure'. 7 | * 8 | * It is also included by 'configure' tests to ensure that any system 9 | * headers *they* include will be configured consistantly and symbols 10 | * they declare will not be exposed differently in the tests and the 11 | * code thus causing the configuration macros defined in 'config.h' 12 | * to be mismatched with the included system headers. 13 | * 14 | * Because it is used in both places, it should not include any code 15 | * which is relevant only to MOC code. 16 | */ 17 | 18 | #ifndef COMPILER_H 19 | #define COMPILER_H 20 | 21 | /* _XOPEN_SOURCE is known to break compilation on OpenBSD. */ 22 | #ifndef OPENBSD 23 | # if defined(_XOPEN_SOURCE) && _XOPEN_SOURCE < 600 24 | # undef _XOPEN_SOURCE 25 | # endif 26 | # ifndef _XOPEN_SOURCE 27 | # define _XOPEN_SOURCE 600 28 | # endif 29 | #endif 30 | 31 | /* _XOPEN_SOURCE_EXTENDED is known to break compilation on FreeBSD. */ 32 | #ifndef FREEBSD 33 | # define _XOPEN_SOURCE_EXTENDED 1 34 | #endif 35 | 36 | /* Require POSIX.1-2001 or better. */ 37 | #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L 38 | # undef _POSIX_C_SOURCE 39 | #endif 40 | #ifndef _POSIX_C_SOURCE 41 | # define _POSIX_C_SOURCE 200112L 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /decoder_plugins/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = 2 | 3 | if BUILD_mp3 4 | SUBDIRS += mp3 5 | endif 6 | 7 | if BUILD_aac 8 | SUBDIRS += aac 9 | endif 10 | 11 | if BUILD_musepack 12 | SUBDIRS += musepack 13 | endif 14 | 15 | if BUILD_vorbis 16 | SUBDIRS += vorbis 17 | endif 18 | 19 | if BUILD_flac 20 | SUBDIRS += flac 21 | endif 22 | 23 | if BUILD_wavpack 24 | SUBDIRS += wavpack 25 | endif 26 | 27 | if BUILD_sndfile 28 | SUBDIRS += sndfile 29 | endif 30 | 31 | if BUILD_modplug 32 | SUBDIRS += modplug 33 | endif 34 | 35 | if BUILD_timidity 36 | SUBDIRS += timidity 37 | endif 38 | 39 | if BUILD_sidplay2 40 | SUBDIRS += sidplay2 41 | endif 42 | 43 | if BUILD_ffmpeg 44 | SUBDIRS += ffmpeg 45 | endif 46 | 47 | if BUILD_speex 48 | SUBDIRS += speex 49 | endif 50 | -------------------------------------------------------------------------------- /decoder_plugins/aac/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libaac_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libaac_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libaac_decoder_la_LIBADD = -lid3tag -lz $(FAAD2_LIBS) 5 | libaac_decoder_la_CFLAGS = $(FAAD2_CFLAGS) -I$(top_srcdir) 6 | libaac_decoder_la_SOURCES = aac.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/aac/aac.m4: -------------------------------------------------------------------------------- 1 | dnl libfaad2 (aac) 2 | 3 | AC_ARG_WITH(aac, AS_HELP_STRING([--without-aac], 4 | [Compile without AAC support (libfaad2)])) 5 | 6 | if test "x$with_aac" != "xno" 7 | then 8 | faad2_OK="no" 9 | AC_CHECK_LIB(faad, NeAACDecInit, [faad2_OK="yes"]) 10 | 11 | if test "x$faad2_OK" = "xyes"; then 12 | AC_CHECK_HEADER([neaacdec.h], , 13 | AC_MSG_ERROR([You need a more recent libfaad2 (libfaad2 devel package).])) 14 | fi 15 | 16 | if test "x$faad2_OK" = "xyes" -a "$HAVE_ID3TAG" = "yes" 17 | then 18 | FAAD2_LIBS="-lfaad" 19 | AC_SUBST([FAAD2_CFLAGS]) 20 | AC_SUBST([FAAD2_LIBS]) 21 | want_aac="yes" 22 | DECODER_PLUGINS="$DECODER_PLUGINS aac" 23 | fi 24 | fi 25 | 26 | AM_CONDITIONAL([BUILD_aac], [test "$want_aac"]) 27 | AC_CONFIG_FILES([decoder_plugins/aac/Makefile]) 28 | -------------------------------------------------------------------------------- /decoder_plugins/decoders.m4: -------------------------------------------------------------------------------- 1 | DECODER_PLUGIN_DIR=decoder_plugins 2 | AC_SUBST([DECODER_PLUGIN_DIR]) 3 | 4 | dnl libid3tag (with zlib) 5 | AC_CHECK_LIB(z, gzopen, [HAVE_ZLIB=yes],) 6 | AC_CHECK_LIB(id3tag, id3_file_open, [HAVE_LIBID3TAG=yes],) 7 | AC_CHECK_HEADER([id3tag.h],[HAVE_LIBID3TAG_H=yes],) 8 | 9 | if test "x$HAVE_ZLIB" = "xyes" -a "x$HAVE_LIBID3TAG" = "xyes" \ 10 | -a "x$HAVE_LIBID3TAG_H" = "xyes" 11 | then 12 | HAVE_ID3TAG=yes 13 | else 14 | HAVE_ID3TAG=no 15 | fi 16 | 17 | m4_include(decoder_plugins/aac/aac.m4) 18 | m4_include(decoder_plugins/ffmpeg/ffmpeg.m4) 19 | m4_include(decoder_plugins/flac/flac.m4) 20 | m4_include(decoder_plugins/modplug/modplug.m4) 21 | m4_include(decoder_plugins/mp3/mp3.m4) 22 | m4_include(decoder_plugins/musepack/musepack.m4) 23 | m4_include(decoder_plugins/sidplay2/sidplay2.m4) 24 | m4_include(decoder_plugins/sndfile/sndfile.m4) 25 | m4_include(decoder_plugins/speex/speex.m4) 26 | m4_include(decoder_plugins/timidity/timidity.m4) 27 | m4_include(decoder_plugins/vorbis/vorbis.m4) 28 | m4_include(decoder_plugins/wavpack/wavpack.m4) 29 | 30 | AC_CONFIG_FILES([decoder_plugins/Makefile]) 31 | -------------------------------------------------------------------------------- /decoder_plugins/ffmpeg/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libffmpeg_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libffmpeg_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libffmpeg_decoder_la_LIBADD = $(ffmpeg_LIBS) 5 | libffmpeg_decoder_la_CPPFLAGS = $(ffmpeg_CPPFLAGS) -I$(top_srcdir) 6 | libffmpeg_decoder_la_CFLAGS = $(ffmpeg_CFLAGS) -I$(top_srcdir) 7 | libffmpeg_decoder_la_SOURCES = ffmpeg.c 8 | -------------------------------------------------------------------------------- /decoder_plugins/ffmpeg/ffmpeg.m4: -------------------------------------------------------------------------------- 1 | dnl ffmpeg/libav 2 | 3 | AC_ARG_WITH(ffmpeg, AS_HELP_STRING([--without-ffmpeg], 4 | [Compile without ffmpeg/libav])) 5 | 6 | if test "x$with_ffmpeg" != "xno" 7 | then 8 | PKG_CHECK_MODULES(ffmpeg, libavutil libavcodec libavformat, 9 | [ffmpeg_CPPFLAGS=`$PKG_CONFIG --cflags-only-I libavutil libavcodec libavformat` 10 | AC_SUBST(ffmpeg_CPPFLAGS) 11 | AC_SUBST(ffmpeg_CFLAGS) 12 | AC_SUBST(ffmpeg_LIBS) 13 | want_ffmpeg="yes"], 14 | [true]) 15 | if test "x$want_ffmpeg" = "xyes" 16 | then 17 | if $PKG_CONFIG --max-version 53.47.99 libavcodec 18 | then 19 | AC_MSG_ERROR([You need FFmpeg/LibAV of at least release 1.0/10.0.]) 20 | fi 21 | if test "`$PKG_CONFIG --modversion libavcodec | awk -F. '{ print $3; }'`" -gt 99 22 | then 23 | if ! $PKG_CONFIG --atleast-version 54.59.100 libavcodec 24 | then 25 | AC_MSG_ERROR([You need FFmpeg of at least release 1.0.]) 26 | fi 27 | DECODER_PLUGINS="$DECODER_PLUGINS ffmpeg" 28 | AC_DEFINE([HAVE_FFMPEG], 1, 29 | [Define to 1 if you know you have FFmpeg.]) 30 | else 31 | if ! $PKG_CONFIG --atleast-version 55.34.1 libavcodec 32 | then 33 | AC_MSG_ERROR([You need LibAV of at least release 10.0.]) 34 | fi 35 | DECODER_PLUGINS="$DECODER_PLUGINS ffmpeg(libav)" 36 | AC_DEFINE([HAVE_LIBAV], 1, 37 | [Define to 1 if you know you have LibAV.]) 38 | fi 39 | save_CPPFLAGS="$CPPFLAGS" 40 | CPPFLAGS="$CPPFLAGS $ffmpeg_CPPFLAGS" 41 | save_CFLAGS="$CFLAGS" 42 | CFLAGS="$CFLAGS $ffmpeg_CFLAGS" 43 | save_LIBS="$LIBS" 44 | LIBS="$LIBS $ffmpeg_LIBS" 45 | AC_CHECK_MEMBERS([struct AVProbeData.mime_type], [], [], 46 | [#include ]) 47 | AC_CHECK_HEADERS([libavutil/channel_layout.h]) 48 | AC_SEARCH_LIBS(av_packet_alloc, avcodec, 49 | [AC_DEFINE([HAVE_AV_PACKET_FNS], 1, 50 | [Define to 1 if you have the `av_packet_*' functions.])]) 51 | AC_SEARCH_LIBS(av_frame_alloc, avutil, 52 | [AC_DEFINE([HAVE_AV_FRAME_FNS], 1, 53 | [Define to 1 if you have the `av_frame_*' functions.])]) 54 | AC_SEARCH_LIBS(avcodec_free_context, avcodec, 55 | [AC_DEFINE([HAVE_AVCODEC_FREE_CONTEXT], 1, 56 | [Define to 1 if you have the `avcodec_free_context' function.])]) 57 | AC_SEARCH_LIBS(avcodec_receive_frame, avcodec, 58 | [AC_DEFINE([HAVE_AVCODEC_RECEIVE_FRAME], 1, 59 | [Define to 1 if you have the `avcodec_receive_frame' function.])]) 60 | AC_CHECK_MEMBERS([struct AVStream.codecpar], [], [], 61 | [#include ]) 62 | CPPFLAGS="$save_CPPFLAGS" 63 | CFLAGS="$save_CFLAGS" 64 | LIBS="$save_LIBS" 65 | fi 66 | fi 67 | 68 | AM_CONDITIONAL([BUILD_ffmpeg], [test "$want_ffmpeg"]) 69 | AC_CONFIG_FILES([decoder_plugins/ffmpeg/Makefile]) 70 | -------------------------------------------------------------------------------- /decoder_plugins/flac/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libflac_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libflac_decoder_la_CFLAGS = $(LIBFLAC_CFLAGS) -I$(top_srcdir) 4 | libflac_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 5 | libflac_decoder_la_LIBADD = $(LIBFLAC_LIBS) 6 | libflac_decoder_la_SOURCES = flac.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/flac/flac.m4: -------------------------------------------------------------------------------- 1 | dnl FLAC 2 | 3 | AC_ARG_WITH(flac, AS_HELP_STRING([--without-flac], 4 | [Compile without FLAC support])) 5 | 6 | if test "x$with_flac" != "xno" 7 | then 8 | PKG_CHECK_MODULES(LIBFLAC, [flac >= 1.1.3], 9 | [AC_SUBST(LIBFLAC_LIBS) 10 | AC_SUBST(LIBFLAC_CFLAGS) 11 | want_flac="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS flac"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_flac], [test "$want_flac"]) 17 | AC_CONFIG_FILES([decoder_plugins/flac/Makefile]) 18 | -------------------------------------------------------------------------------- /decoder_plugins/modplug/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libmodplug_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libmodplug_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libmodplug_decoder_la_LIBADD = $(modplug_LIBS) 5 | libmodplug_decoder_la_CFLAGS = $(modplug_CFLAGS) -I$(top_srcdir) 6 | libmodplug_decoder_la_SOURCES = modplug.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/modplug/modplug.m4: -------------------------------------------------------------------------------- 1 | dnl libmodplug 2 | 3 | AC_ARG_WITH(modplug, AS_HELP_STRING([--without-modplug], 4 | [Compile without libmodplug])) 5 | 6 | if test "x$with_modplug" != "xno" 7 | then 8 | PKG_CHECK_MODULES(modplug, libmodplug >= 0.7, 9 | [AC_SUBST(modplug_LIBS) 10 | AC_SUBST(modplug_CFLAGS) 11 | want_modplug="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS modplug"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_modplug], [test "$want_modplug"]) 17 | AC_CONFIG_FILES([decoder_plugins/modplug/Makefile]) 18 | -------------------------------------------------------------------------------- /decoder_plugins/mp3/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libmp3_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libmp3_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libmp3_decoder_la_CFLAGS = -I$(top_srcdir) 5 | libmp3_decoder_la_LIBADD = -lmad -lid3tag -lz $(RCC_LIBS) 6 | libmp3_decoder_la_SOURCES = mp3.c xing.c xing.h 7 | -------------------------------------------------------------------------------- /decoder_plugins/mp3/mp3.m4: -------------------------------------------------------------------------------- 1 | dnl libmad (mp3) 2 | 3 | AC_ARG_WITH(mp3, AS_HELP_STRING([--without-mp3], 4 | [Compile without mp3 support (libmad)])) 5 | 6 | if test "x$with_mp3" != "xno" 7 | then 8 | AC_CHECK_LIB(mad, mad_stream_init, [ 9 | AC_CHECK_HEADER([mad.h], ,)]) 10 | 11 | if test "$ac_cv_lib_mad_mad_stream_init" = "yes" -a "$HAVE_ID3TAG" = "yes" 12 | then 13 | want_mp3="yes" 14 | DECODER_PLUGINS="$DECODER_PLUGINS mp3" 15 | fi 16 | fi 17 | 18 | AM_CONDITIONAL([BUILD_mp3], [test "$want_mp3"]) 19 | AC_CONFIG_FILES([decoder_plugins/mp3/Makefile]) 20 | -------------------------------------------------------------------------------- /decoder_plugins/mp3/xing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mad - MPEG audio decoder 3 | * Copyright (C) 2000-2001 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software Foundation, 17 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | * 19 | * $Id: xing.c,v 1.5 2002/11/18 16:32:21 daper Exp $ 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | 26 | #include 27 | 28 | #include "xing.h" 29 | 30 | #define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g') 31 | 32 | /* 33 | * NAME: xing->init() 34 | * DESCRIPTION: initialize Xing structure 35 | */ 36 | void xing_init(struct xing *xing) 37 | { 38 | xing->flags = 0; 39 | } 40 | 41 | /* 42 | * NAME: xing->parse() 43 | * DESCRIPTION: parse a Xing VBR header 44 | */ 45 | int xing_parse(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen) 46 | { 47 | if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC) 48 | goto fail; 49 | 50 | xing->flags = mad_bit_read(&ptr, 32); 51 | bitlen -= 64; 52 | 53 | if (xing->flags & XING_FRAMES) { 54 | if (bitlen < 32) 55 | goto fail; 56 | 57 | xing->frames = mad_bit_read(&ptr, 32); 58 | bitlen -= 32; 59 | } 60 | 61 | if (xing->flags & XING_BYTES) { 62 | if (bitlen < 32) 63 | goto fail; 64 | 65 | xing->bytes = mad_bit_read(&ptr, 32); 66 | bitlen -= 32; 67 | } 68 | 69 | if (xing->flags & XING_TOC) { 70 | int i; 71 | 72 | if (bitlen < 800) 73 | goto fail; 74 | 75 | for (i = 0; i < 100; ++i) 76 | xing->toc[i] = mad_bit_read(&ptr, 8); 77 | 78 | bitlen -= 800; 79 | } 80 | 81 | if (xing->flags & XING_SCALE) { 82 | if (bitlen < 32) 83 | goto fail; 84 | 85 | xing->scale = mad_bit_read(&ptr, 32); 86 | bitlen -= 32; 87 | } 88 | 89 | return 0; 90 | 91 | fail: 92 | xing->flags = 0; 93 | return -1; 94 | } 95 | -------------------------------------------------------------------------------- /decoder_plugins/mp3/xing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * mad - MPEG audio decoder 3 | * Copyright (C) 2000-2001 Robert Leslie 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * $Id: xing.h,v 1.3 2002/10/04 13:38:09 daper Exp $ 20 | */ 21 | #ifndef XING_H 22 | #define XING_H 23 | 24 | #include "mad.h" 25 | 26 | struct xing 27 | { 28 | long flags; /* valid fields (see below) */ 29 | unsigned long frames; /* total number of frames */ 30 | unsigned long bytes; /* total number of bytes */ 31 | unsigned char toc[100]; /* 100-point seek table */ 32 | long scale; /* ?? */ 33 | }; 34 | 35 | enum 36 | { 37 | XING_FRAMES = 0x00000001L, 38 | XING_BYTES = 0x00000002L, 39 | XING_TOC = 0x00000004L, 40 | XING_SCALE = 0x00000008L 41 | }; 42 | 43 | void xing_init (struct xing *); 44 | 45 | #define xing_finish(xing) /* nothing */ 46 | 47 | int xing_parse (struct xing *, struct mad_bitptr, unsigned int); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /decoder_plugins/musepack/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libmusepack_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libmusepack_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libmusepack_decoder_la_LIBADD = $(MUSEPACK_LIBS) $(TAGLIB_LIBS) 5 | libmusepack_decoder_la_CFLAGS = $(MUSEPACK_CFLAGS) $(TAGLIB_CFLAGS) \ 6 | -I$(top_srcdir) 7 | libmusepack_decoder_la_SOURCES = musepack.c 8 | -------------------------------------------------------------------------------- /decoder_plugins/musepack/musepack.m4: -------------------------------------------------------------------------------- 1 | dnl libmpcdec 2 | 3 | AC_ARG_WITH(musepack, AS_HELP_STRING([--without-musepack], 4 | [Compile without musepack (mpc) support])) 5 | 6 | if test "x$with_musepack" != "xno" 7 | then 8 | dnl taken from gstreamer 9 | AC_CHECK_HEADER([mpc/mpcdec.h], 10 | [have_musepack="yes"], 11 | [AC_CHECK_HEADER([mpcdec/mpcdec.h], 12 | [have_musepack="yes" 13 | UPGRADE_MUSEPACK="yes" 14 | AC_DEFINE(MPC_IS_OLD_API, 1, [Define if the old MusePack API is used])], 15 | [have_musepack="no"])]) 16 | 17 | if test "x$have_musepack" = "xyes" 18 | then 19 | 20 | MUSEPACK_LIBS="-lmpcdec" 21 | AC_SUBST([MUSEPACK_LIBS]) 22 | 23 | dnl taglib 24 | AC_CHECK_PROG([TAGLIB_CONFIG], [taglib-config], [yes]) 25 | if test "x$TAGLIB_CONFIG" = "xyes" 26 | then 27 | AC_MSG_CHECKING([taglib version]) 28 | taglib_ver=`taglib-config --version` 29 | AX_COMPARE_VERSION($taglib_ver, [ge], [1.3.1]) 30 | if test "x$ax_compare_version" = "xtrue" 31 | then 32 | AC_MSG_RESULT([$taglib_ver, OK]) 33 | 34 | TAGLIB_CFLAGS="`taglib-config --cflags`" 35 | dnl TAGLIB_LIBS="`taglib-config --libs`" 36 | TAGLIB_LIBS="-ltag_c" 37 | AC_SUBST([TAGLIB_CFLAGS]) 38 | AC_SUBST([TAGLIB_LIBS]) 39 | 40 | dnl check for tag_c.h 41 | old_cflags="$CFLAGS" 42 | old_cppflags="$CPPFLAGS" 43 | CFLAGS="$CFLAGS $TAGLIB_CFLAGS" 44 | CPPFLAGS="$CPPFLAGS $TAGLIB_CFLAGS" 45 | AC_CHECK_HEADER([tag_c.h], [ 46 | want_musepack="yes" 47 | DECODER_PLUGINS="$DECODER_PLUGINS musepack" 48 | ]) 49 | CFLAGS="$old_cflags" 50 | CPPFLAGS="$old_cppflags" 51 | 52 | AX_COMPARE_VERSION($taglib_ver, [lt], [1.5]) 53 | if test "x$ax_compare_version" = "xtrue" 54 | then 55 | UPGRADE_TAGLIB="yes" 56 | fi 57 | else 58 | AC_MSG_RESULT([$taglib_ver, but minimum is 1.3.1 - required for musepack]) 59 | fi 60 | fi 61 | fi 62 | fi 63 | 64 | AM_CONDITIONAL([BUILD_musepack], [test "$want_musepack"]) 65 | AC_CONFIG_FILES([decoder_plugins/musepack/Makefile]) 66 | -------------------------------------------------------------------------------- /decoder_plugins/sidplay2/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libsidplay2_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libsidplay2_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ $(sidplay2_LDFLAGS) 4 | libsidplay2_decoder_la_LIBADD = $(sidplay2_LIBS) $(sidutils_LIBS) 5 | libsidplay2_decoder_la_CFLAGS = $(sidplay2_CFLAGS) $(sidutils_CFLAGS) -I$(top_srcdir) 6 | libsidplay2_decoder_la_CXXFLAGS = $(sidplay2_CFLAGS) $(sidutils_CFLAGS) -I$(top_srcdir) 7 | libsidplay2_decoder_la_SOURCES = sidplay2.cc sidplay2.h 8 | -------------------------------------------------------------------------------- /decoder_plugins/sidplay2/sidplay2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2004 Damian Pietras 4 | * 5 | * libsidplay2-plugin Copyright (C) 2007 Hendrik Iben 6 | * Enables MOC to play sids via libsidplay2/libsidutils. 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | */ 14 | 15 | #ifdef HAVE_CONFIG_H 16 | #include "config.h" 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #include "decoder.h" 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #ifdef __cplusplus 30 | 31 | // debug and error are used by this library too... 32 | #undef debug 33 | #undef error 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define RESID_ID "ReSID" 41 | #define OPT_DEFLEN "SidPlay2_DefaultSongLength" 42 | #define OPT_MINLEN "SidPlay2_MinimumSongLength" 43 | #define OPT_DATABASE "SidPlay2_Database" 44 | #define OPT_FREQ "SidPlay2_Frequency" 45 | #define OPT_PREC "SidPlay2_Bits" 46 | #define OPT_PMODE "SidPlay2_PlayMode" 47 | #define OPT_OPTI "SidPlay2_Optimisation" 48 | #define OPT_START "SidPlay2_StartAtStart" 49 | #define OPT_SUBTUNES "SidPlay2_PlaySubTunes" 50 | 51 | #define STITLE 0 52 | #define SAUTHOR 1 53 | #define SCOPY 2 54 | 55 | #define POOL_SIZE 2 56 | 57 | struct sidplay2_data 58 | { 59 | SidTuneMod * tune; 60 | SID_EXTERN::sidplay2 *player; 61 | sid2_config_t cfg; 62 | ReSIDBuilder *builder; 63 | int length; 64 | int *sublengths; 65 | int songs; 66 | int startSong; 67 | int currentSong; 68 | int timeStart; 69 | int timeEnd; 70 | struct decoder_error error; 71 | int sample_format, frequency, channels; 72 | }; 73 | 74 | #endif 75 | 76 | #ifdef __cplusplus 77 | extern "C" { 78 | #endif 79 | 80 | void *sidplay2_open (const char *file); 81 | void sidplay2_close (void *void_data); 82 | void sidplay2_get_error (void *prv_data, struct decoder_error *error); 83 | void sidplay2_info (const char *file_name, struct file_tags *info, 84 | const int tags_sel); 85 | int sidplay2_seek (void *void_data, int sec); 86 | int sidplay2_decode (void *void_data, char *buf, int buf_len, 87 | struct sound_params *sound_params); 88 | int sidplay2_get_bitrate (void *void_data); 89 | int sidplay2_get_duration (void *void_data); 90 | void sidplay2_get_name (const char *file, char buf[4]); 91 | int sidplay2_our_format_ext (const char *ext); 92 | void destroy (); 93 | void init (); 94 | decoder *plugin_init (); 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | -------------------------------------------------------------------------------- /decoder_plugins/sidplay2/sidplay2.m4: -------------------------------------------------------------------------------- 1 | dnl libsidplay2 2 | 3 | AC_ARG_WITH(sidplay2, AS_HELP_STRING([--without-sidplay2], 4 | [Compile without libsidplay2])) 5 | 6 | if test "x$with_sidplay2" != "xno" 7 | then 8 | PKG_CHECK_MODULES(sidplay2, libsidplay2 >= 2.1.1, 9 | [sidplay2_OK="yes"], 10 | [true]) 11 | 12 | PKG_CHECK_MODULES(sidutils, libsidutils >= 1.0.4, 13 | [sidutils_OK="yes"], 14 | [true]) 15 | dnl This is a rather ugly hack to find the builder 16 | dnl as libsidplay2 works fine without it but the 17 | dnl decoder uses it... 18 | if test "x$sidplay2_OK" = "xyes"; then 19 | if test "x$sidutils_OK" = "xyes"; then 20 | s2lib=`$PKG_CONFIG --variable=builders libsidplay2 2>/dev/null` 21 | if test "x$s2lib" != "x"; then 22 | AC_LANG_PUSH([C++]) 23 | save_CXXFLAGS="$CXXFLAGS" 24 | CXXFLAGS="$CXXFLAGS $sidplay2_CFLAGS" 25 | AC_CHECK_HEADER([sidplay/builders/resid.h], [resid_OK="yes"]) 26 | CXXFLAGS="$save_CXXFLAGS" 27 | AC_LANG_POP([C++]) 28 | if test "x$resid_OK" = "xyes"; then 29 | sidplay2_LDFLAGS="-L$s2lib -lresid-builder" 30 | AC_SUBST(sidplay2_LDFLAGS) 31 | AC_SUBST(sidplay2_LIBS) 32 | AC_SUBST(sidplay2_CFLAGS) 33 | AC_SUBST(sidutils_LIBS) 34 | AC_SUBST(sidutils_CFLAGS) 35 | want_sidplay2="yes" 36 | DECODER_PLUGINS="$DECODER_PLUGINS sidplay2" 37 | fi 38 | fi 39 | fi 40 | fi 41 | fi 42 | 43 | AM_CONDITIONAL([BUILD_sidplay2], [test "$want_sidplay2"]) 44 | AC_CONFIG_FILES([decoder_plugins/sidplay2/Makefile]) 45 | -------------------------------------------------------------------------------- /decoder_plugins/sndfile/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libsndfile_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libsndfile_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libsndfile_decoder_la_LIBADD = $(sndfile_LIBS) 5 | libsndfile_decoder_la_CFLAGS = $(sndfile_CFLAGS) -I$(top_srcdir) 6 | libsndfile_decoder_la_SOURCES = sndfile.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/sndfile/sndfile.m4: -------------------------------------------------------------------------------- 1 | dnl libsndfile 2 | 3 | AC_ARG_WITH(sndfile, AS_HELP_STRING([--without-sndfile], 4 | [Compile without libsndfile])) 5 | 6 | if test "x$with_sndfile" != "xno" 7 | then 8 | PKG_CHECK_MODULES(sndfile, sndfile >= 1.0.0, 9 | [AC_SUBST(sndfile_LIBS) 10 | AC_SUBST(sndfile_CFLAGS) 11 | want_sndfile="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS sndfile"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_sndfile], [test "$want_sndfile"]) 17 | AC_CONFIG_FILES([decoder_plugins/sndfile/Makefile]) 18 | -------------------------------------------------------------------------------- /decoder_plugins/speex/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libspeex_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libspeex_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libspeex_decoder_la_LIBADD = $(speex_LIBS) 5 | libspeex_decoder_la_CFLAGS = $(speex_CFLAGS) -I$(top_srcdir) 6 | libspeex_decoder_la_SOURCES = speex.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/speex/speex.m4: -------------------------------------------------------------------------------- 1 | dnl speex 2 | 3 | AC_ARG_WITH(speex, AS_HELP_STRING([--without-speex], 4 | [Compile without speex support])) 5 | 6 | if test "x$with_speex" != "xno" 7 | then 8 | PKG_CHECK_MODULES(speex, [ogg >= 1.0 speex >= 1.0.0], 9 | [AC_SUBST(speex_LIBS) 10 | AC_SUBST(speex_CFLAGS) 11 | want_speex="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS speex"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_speex], [test "$want_speex"]) 17 | AC_CONFIG_FILES([decoder_plugins/speex/Makefile]) 18 | -------------------------------------------------------------------------------- /decoder_plugins/timidity/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libtimidity_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libtimidity_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libtimidity_decoder_la_LIBADD = $(timidity_LIBS) 5 | libtimidity_decoder_la_CFLAGS = $(timidity_CFLAGS) -I$(top_srcdir) 6 | libtimidity_decoder_la_SOURCES = timidity.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/timidity/timidity.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2004 Damian Pietras 4 | * 5 | * libTiMidity-plugin Copyright (C) 2007 Hendrik Iben 6 | * The hard work is done by the libTiMidity-Library written by 7 | * Konstantin Korikov (http://libtimidity.sourceforge.net). 8 | * I have merely hacked together a wrapper... 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; either version 2 of the License, or 13 | * (at your option) any later version. 14 | * 15 | */ 16 | 17 | #ifdef HAVE_CONFIG_H 18 | #include "config.h" 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define DEBUG 27 | 28 | #include "common.h" 29 | #include "io.h" 30 | #include "decoder.h" 31 | #include "log.h" 32 | #include "files.h" 33 | #include "options.h" 34 | 35 | MidSongOptions midioptions; 36 | 37 | struct timidity_data 38 | { 39 | MidSong *midisong; 40 | int length; 41 | struct decoder_error error; 42 | }; 43 | 44 | static struct timidity_data *make_timidity_data(const char *file) { 45 | struct timidity_data *data; 46 | 47 | data = (struct timidity_data *)xmalloc (sizeof(struct timidity_data)); 48 | 49 | data->midisong = NULL; 50 | decoder_error_init (&data->error); 51 | 52 | MidIStream *midistream = mid_istream_open_file(file); 53 | 54 | if(midistream==NULL) { 55 | decoder_error(&data->error, ERROR_FATAL, 0, 56 | "Can't open midifile: %s", file); 57 | return data; 58 | } 59 | 60 | data->midisong = mid_song_load(midistream, &midioptions); 61 | mid_istream_close(midistream); 62 | 63 | if(data->midisong==NULL) { 64 | decoder_error(&data->error, ERROR_FATAL, 0, 65 | "Can't load midifile: %s", file); 66 | return data; 67 | } 68 | 69 | return data; 70 | } 71 | 72 | static void *timidity_open (const char *file) 73 | { 74 | struct timidity_data *data = make_timidity_data(file); 75 | 76 | if(data->midisong) { 77 | data->length = mid_song_get_total_time(data->midisong); 78 | } 79 | 80 | 81 | if(data->midisong) { 82 | debug ("Opened file %s", file); 83 | 84 | mid_song_set_volume(data->midisong, options_get_int("TiMidity_Volume")); 85 | mid_song_start(data->midisong); 86 | } 87 | 88 | return data; 89 | } 90 | 91 | static void timidity_close (void *void_data) 92 | { 93 | struct timidity_data *data = (struct timidity_data *)void_data; 94 | 95 | if (data->midisong) { 96 | mid_song_free(data->midisong); 97 | } 98 | 99 | decoder_error_clear (&data->error); 100 | free (data); 101 | } 102 | 103 | static void timidity_info (const char *file_name, struct file_tags *info, 104 | const int tags_sel) 105 | { 106 | struct timidity_data *data = make_timidity_data(file_name); 107 | 108 | if(data->midisong==NULL) { 109 | free (data); 110 | return; 111 | } 112 | 113 | if(tags_sel & TAGS_TIME) { 114 | info->time = mid_song_get_total_time(data->midisong) / 1000; 115 | info->filled |= TAGS_TIME; 116 | } 117 | 118 | timidity_close(data); 119 | } 120 | 121 | static int timidity_seek (void *void_data, int sec) 122 | { 123 | struct timidity_data *data = (struct timidity_data *)void_data; 124 | 125 | assert (sec >= 0); 126 | 127 | int ms = sec*1000; 128 | 129 | ms = MIN(ms,data->length); 130 | 131 | mid_song_seek(data->midisong, ms); 132 | 133 | return ms/1000; 134 | } 135 | 136 | static int timidity_decode (void *void_data, char *buf, int buf_len, 137 | struct sound_params *sound_params) 138 | { 139 | struct timidity_data *data = (struct timidity_data *)void_data; 140 | 141 | sound_params->channels = midioptions.channels; 142 | sound_params->rate = midioptions.rate; 143 | sound_params->fmt = (midioptions.format==MID_AUDIO_S16LSB)?(SFMT_S16 | SFMT_LE):SFMT_S8; 144 | 145 | return mid_song_read_wave(data->midisong, (void *)buf, buf_len); 146 | } 147 | 148 | static int timidity_get_bitrate (void *unused ATTR_UNUSED) 149 | { 150 | return -1; 151 | } 152 | 153 | static int timidity_get_duration (void *void_data) 154 | { 155 | struct timidity_data *data = (struct timidity_data *)void_data; 156 | return data->length/1000; 157 | } 158 | 159 | static void timidity_get_name (const char *unused ATTR_UNUSED, char buf[4]) 160 | { 161 | strcpy (buf, "MID"); 162 | } 163 | 164 | static int timidity_our_format_ext(const char *ext) 165 | { 166 | return !strcasecmp (ext, "MID"); 167 | } 168 | 169 | static int timidity_our_format_mime (const char *mime) 170 | { 171 | return !strcasecmp(mime, "audio/midi") 172 | || !strncasecmp(mime, "audio/midi;", 10); 173 | } 174 | 175 | static void timidity_get_error (void *prv_data, struct decoder_error *error) 176 | { 177 | struct timidity_data *data = (struct timidity_data *)prv_data; 178 | 179 | decoder_error_copy (error, &data->error); 180 | } 181 | 182 | static void timidity_destroy() 183 | { 184 | mid_exit(); 185 | } 186 | 187 | static struct decoder timidity_decoder = 188 | { 189 | DECODER_API_VERSION, 190 | NULL, 191 | timidity_destroy, 192 | timidity_open, 193 | NULL, 194 | NULL, 195 | timidity_close, 196 | timidity_decode, 197 | timidity_seek, 198 | timidity_info, 199 | timidity_get_bitrate, 200 | timidity_get_duration, 201 | timidity_get_error, 202 | timidity_our_format_ext, 203 | timidity_our_format_mime, 204 | timidity_get_name, 205 | NULL, 206 | NULL, 207 | NULL 208 | }; 209 | 210 | struct decoder *plugin_init () 211 | { 212 | char *config; 213 | int initresult; 214 | 215 | config = options_get_str("TiMidity_Config"); 216 | if (config == NULL || strcasecmp(config, "yes") == 0) 217 | initresult = mid_init(NULL); 218 | else if (strcasecmp(config, "no") == 0) 219 | initresult = mid_init_no_config(); 220 | else 221 | initresult = mid_init(config); 222 | 223 | // Is there a better way to signal failed init? 224 | // The decoder-init-function may not return errors AFAIK... 225 | if(initresult < 0) 226 | { 227 | if (config == NULL || strcasecmp(config, "yes") == 0) 228 | config = ""; 229 | fatal("TiMidity-Plugin: Error processing TiMidity-Configuration!\n" 230 | " Configuration file is: %s", config); 231 | } 232 | 233 | midioptions.rate = options_get_int("TiMidity_Rate"); 234 | midioptions.format = (options_get_int("TiMidity_Bits")==16)?MID_AUDIO_S16LSB:MID_AUDIO_S8; 235 | midioptions.channels = options_get_int("TiMidity_Channels"); 236 | midioptions.buffer_size = midioptions.rate; 237 | 238 | return &timidity_decoder; 239 | } 240 | -------------------------------------------------------------------------------- /decoder_plugins/timidity/timidity.m4: -------------------------------------------------------------------------------- 1 | dnl libtimidity 2 | 3 | AC_ARG_WITH(timidity, AS_HELP_STRING([--without-timidity], 4 | [Compile without libtimidity])) 5 | 6 | if test "x$with_timidity" != "xno" 7 | then 8 | PKG_CHECK_MODULES(timidity, libtimidity >= 0.1.0, 9 | [AC_SUBST(timidity_LIBS) 10 | AC_SUBST(timidity_CFLAGS) 11 | want_timidity="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS timidity"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_timidity], [test "$want_timidity"]) 17 | AC_CONFIG_FILES([decoder_plugins/timidity/Makefile]) 18 | -------------------------------------------------------------------------------- /decoder_plugins/vorbis/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libvorbis_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libvorbis_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libvorbis_decoder_la_LIBADD = $(OGG_VORBIS_LIBS) 5 | libvorbis_decoder_la_CFLAGS = $(OGG_VORBIS_CFLAGS) -I$(top_srcdir) 6 | libvorbis_decoder_la_SOURCES = vorbis.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/vorbis/vorbis.m4: -------------------------------------------------------------------------------- 1 | dnl vorbis 2 | 3 | AC_ARG_WITH(vorbis, AS_HELP_STRING([--without-vorbis], 4 | [Compile without Ogg Vorbis support])) 5 | 6 | if test "x$with_vorbis" == "xtremor" 7 | then 8 | PKG_CHECK_MODULES(OGG_VORBIS, 9 | [vorbisidec >= 1.0], 10 | [AC_SUBST(OGG_VORBIS_LIBS) 11 | AC_SUBST(OGG_VORBIS_CFLAGS) 12 | AC_DEFINE([HAVE_TREMOR], 1, [Define if you integer Vorbis.]) 13 | want_vorbis="yes" 14 | DECODER_PLUGINS="$DECODER_PLUGINS vorbis(tremor)"], 15 | [true]) 16 | else 17 | if test "x$with_vorbis" != "xno" 18 | then 19 | PKG_CHECK_MODULES(OGG_VORBIS, 20 | [ogg >= 1.0 vorbis >= 1.0 vorbisfile >= 1.0], 21 | [AC_SUBST(OGG_VORBIS_LIBS) 22 | AC_SUBST(OGG_VORBIS_CFLAGS) 23 | want_vorbis="yes" 24 | DECODER_PLUGINS="$DECODER_PLUGINS vorbis"], 25 | [true]) 26 | fi 27 | fi 28 | 29 | AM_CONDITIONAL([BUILD_vorbis], [test "$want_vorbis"]) 30 | AC_CONFIG_FILES([decoder_plugins/vorbis/Makefile]) 31 | -------------------------------------------------------------------------------- /decoder_plugins/wavpack/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libwavpack_decoder.la 2 | libdir = $(plugindir)/$(DECODER_PLUGIN_DIR) 3 | libwavpack_decoder_la_LDFLAGS = @PLUGIN_LDFLAGS@ 4 | libwavpack_decoder_la_LIBADD = $(WAVPACK_LIBS) 5 | libwavpack_decoder_la_CFLAGS = $(WAVPACK_CFLAGS) -I$(top_srcdir) 6 | libwavpack_decoder_la_SOURCES = wavpack.c 7 | -------------------------------------------------------------------------------- /decoder_plugins/wavpack/wavpack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2004 Damian Pietras 4 | * 5 | * libwavpack-plugin Copyright (C) 2006 Alexandrov Sergey 6 | * Enables MOC to play wavpack files (actually just a wrapper around 7 | * wavpack library). 8 | * 9 | * Structure of this plugin is an adaption of the libvorbis-plugin from 10 | * moc. 11 | * 12 | * This program is free software; you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation; either version 2 of the License, or 15 | * (at your option) any later version. 16 | * 17 | */ 18 | 19 | 20 | #ifdef HAVE_CONFIG_H 21 | #include "config.h" 22 | #endif 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define DEBUG 31 | 32 | #include "common.h" /* for xmalloc(), xstrdup() etc. */ 33 | #include "log.h" /* for logit() and debug() */ 34 | #include "decoder.h" /* required: provides decoder structure definition */ 35 | #include "io.h" /* if you use io_*() functions to access files. */ 36 | #include "audio.h" /* for sound_params structure */ 37 | 38 | struct wavpack_data 39 | { 40 | WavpackContext *wpc; 41 | int sample_num; 42 | int sample_rate; 43 | int avg_bitrate; 44 | int channels; 45 | int duration; 46 | int mode; 47 | struct decoder_error error; 48 | int ok; /* was this stream successfully opened? */ 49 | }; 50 | 51 | 52 | static void wav_data_init (struct wavpack_data *data) 53 | { 54 | data->sample_num = WavpackGetNumSamples (data->wpc); 55 | data->sample_rate = WavpackGetSampleRate (data->wpc); 56 | data->channels = WavpackGetReducedChannels (data->wpc); 57 | data->duration = data->sample_num / data->sample_rate; 58 | data->mode = WavpackGetMode (data->wpc); 59 | data->avg_bitrate = WavpackGetAverageBitrate (data->wpc, 1) / 1000; 60 | 61 | data->ok = 1; 62 | debug ("File opened. S_n %d. S_r %d. Time %d. Avg_Bitrate %d.", 63 | data->sample_num, data->sample_rate, 64 | data->duration, data->avg_bitrate 65 | ); 66 | } 67 | 68 | 69 | static void *wav_open (const char *file) 70 | { 71 | struct wavpack_data *data; 72 | data = (struct wavpack_data *)xmalloc (sizeof(struct wavpack_data)); 73 | data->ok = 0; 74 | decoder_error_init (&data->error); 75 | 76 | int o_flags = OPEN_2CH_MAX | OPEN_WVC; 77 | 78 | char wv_error[100]; 79 | 80 | if ((data->wpc = WavpackOpenFileInput(file, 81 | wv_error, o_flags, 0)) == NULL) { 82 | decoder_error (&data->error, ERROR_FATAL, 0, "%s", wv_error); 83 | logit ("wv_open error: %s", wv_error); 84 | } 85 | else 86 | wav_data_init (data); 87 | 88 | return data; 89 | } 90 | 91 | static void wav_close (void *prv_data) 92 | { 93 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 94 | 95 | if (data->ok) { 96 | WavpackCloseFile (data->wpc); 97 | } 98 | 99 | decoder_error_clear (&data->error); 100 | free (data); 101 | logit ("File closed"); 102 | } 103 | 104 | static int wav_seek (void *prv_data, int sec) 105 | { 106 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 107 | 108 | assert (sec >= 0); 109 | 110 | if (WavpackSeekSample (data->wpc, sec * data->sample_rate)) 111 | return sec; 112 | 113 | decoder_error (&data->error, ERROR_FATAL, 0, "Fatal seeking error!"); 114 | return -1; 115 | } 116 | 117 | 118 | static int wav_get_bitrate (void *prv_data) 119 | { 120 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 121 | 122 | int bitrate; 123 | bitrate = WavpackGetInstantBitrate (data->wpc) / 1000; 124 | 125 | return (bitrate == 0)? data->avg_bitrate : bitrate; 126 | } 127 | 128 | static int wav_get_avg_bitrate (void *prv_data) 129 | { 130 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 131 | 132 | return data->avg_bitrate; 133 | } 134 | 135 | static int wav_get_duration (void *prv_data) 136 | { 137 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 138 | return data->duration; 139 | } 140 | 141 | static void wav_get_error (void *prv_data, struct decoder_error *error) 142 | { 143 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 144 | decoder_error_copy (error, &data->error); 145 | } 146 | 147 | static void wav_info (const char *file_name, struct file_tags *info, 148 | const int tags_sel) 149 | { 150 | char wv_error[100]; 151 | char *tag; 152 | int tag_len; 153 | 154 | WavpackContext *wpc; 155 | 156 | wpc = WavpackOpenFileInput (file_name, wv_error, OPEN_TAGS, 0); 157 | 158 | if (wpc == NULL) { 159 | logit ("wv_open error: %s", wv_error); 160 | return; 161 | } 162 | 163 | int duration = WavpackGetNumSamples (wpc) / WavpackGetSampleRate (wpc); 164 | 165 | if(tags_sel & TAGS_TIME) { 166 | info->time = duration; 167 | info->filled |= TAGS_TIME; 168 | } 169 | 170 | if(tags_sel & TAGS_COMMENTS) { 171 | if ((tag_len = WavpackGetTagItem (wpc, "title", NULL, 0)) > 0) { 172 | info->title = (char *)xmalloc (++tag_len); 173 | WavpackGetTagItem (wpc, "title", info->title, tag_len); 174 | } 175 | 176 | if ((tag_len = WavpackGetTagItem (wpc, "artist", NULL, 0)) > 0) { 177 | info->artist = (char *)xmalloc (++tag_len); 178 | WavpackGetTagItem (wpc, "artist", info->artist, tag_len); 179 | } 180 | 181 | if ((tag_len = WavpackGetTagItem (wpc, "album", NULL, 0)) > 0) { 182 | info->album = (char *)xmalloc (++tag_len); 183 | WavpackGetTagItem (wpc, "album", info->album, tag_len); 184 | } 185 | 186 | if ((tag_len = WavpackGetTagItem (wpc, "track", NULL, 0)) > 0) { 187 | tag = (char *)xmalloc (++tag_len); 188 | WavpackGetTagItem (wpc, "track", tag, tag_len); 189 | info->track = atoi (tag); 190 | free (tag); 191 | } 192 | 193 | info->filled |= TAGS_COMMENTS; 194 | } 195 | 196 | WavpackCloseFile (wpc); 197 | } 198 | 199 | 200 | static int wav_decode (void *prv_data, char *buf, int buf_len, 201 | struct sound_params *sound_params) 202 | { 203 | struct wavpack_data *data = (struct wavpack_data *)prv_data; 204 | int ret, i, s_num, iBps, oBps; 205 | 206 | int8_t *buf8 = (int8_t *)buf; 207 | int16_t *buf16 = (int16_t *)buf; 208 | int32_t *buf32 = (int32_t *)buf; 209 | 210 | iBps = data->channels * WavpackGetBytesPerSample (data->wpc); 211 | oBps = (iBps == 6) ? 8 : iBps; 212 | s_num = buf_len / oBps; 213 | 214 | decoder_error_clear (&data->error); 215 | 216 | int32_t *dbuf = (int32_t *)xcalloc (s_num, data->channels * 4); 217 | 218 | ret = WavpackUnpackSamples (data->wpc, dbuf, s_num); 219 | 220 | if (ret == 0) { 221 | free (dbuf); 222 | return 0; 223 | } 224 | 225 | if (data->mode & MODE_FLOAT) { 226 | sound_params->fmt = SFMT_FLOAT; 227 | memcpy (buf, dbuf, ret * oBps); 228 | } else { 229 | debug ("iBps %d", iBps); 230 | switch (iBps / data->channels){ 231 | case 4: for (i = 0; i < ret * data->channels; i++) 232 | buf32[i] = dbuf[i]; 233 | sound_params->fmt = SFMT_S32 | SFMT_NE; 234 | break; 235 | case 3: for (i = 0; i < ret * data->channels; i++) 236 | buf32[i] = dbuf[i] * 256; 237 | sound_params->fmt = SFMT_S32 | SFMT_NE; 238 | break; 239 | case 2: for (i = 0; i < ret * data->channels; i++) 240 | buf16[i] = dbuf[i]; 241 | sound_params->fmt = SFMT_S16 | SFMT_NE; 242 | break; 243 | case 1: for (i = 0; i < ret * data->channels; i++) 244 | buf8[i] = dbuf[i]; 245 | sound_params->fmt = SFMT_S8 | SFMT_NE; 246 | } 247 | } 248 | 249 | sound_params->channels = data->channels; 250 | sound_params->rate = data->sample_rate; 251 | 252 | free (dbuf); 253 | return ret * oBps ; 254 | } 255 | 256 | static int wav_our_mime (const char *mime ATTR_UNUSED) 257 | { 258 | /* We don't support internet streams for now. */ 259 | #if 0 260 | return !strcasecmp (mime, "audio/x-wavpack") 261 | || !strncasecmp (mime, "audio/x-wavpack;", 16) 262 | #endif 263 | 264 | return 0; 265 | } 266 | 267 | static void wav_get_name (const char *unused ATTR_UNUSED, char buf[4]) 268 | { 269 | strcpy (buf, "WV"); 270 | } 271 | 272 | static int wav_our_format_ext(const char *ext) 273 | { 274 | return 275 | !strcasecmp (ext, "WV"); 276 | } 277 | 278 | static struct decoder wv_decoder = { 279 | DECODER_API_VERSION, 280 | NULL,//wav_init 281 | NULL,//wav_destroy 282 | wav_open, 283 | NULL,//wav_open_stream, 284 | NULL,//wav_can_decode, 285 | wav_close, 286 | wav_decode, 287 | wav_seek, 288 | wav_info, 289 | wav_get_bitrate, 290 | wav_get_duration, 291 | wav_get_error, 292 | wav_our_format_ext, 293 | wav_our_mime, 294 | wav_get_name, 295 | NULL,//wav_current_tags, 296 | NULL,//wav_get_stream 297 | wav_get_avg_bitrate 298 | }; 299 | 300 | struct decoder *plugin_init () 301 | { 302 | return &wv_decoder; 303 | } 304 | -------------------------------------------------------------------------------- /decoder_plugins/wavpack/wavpack.m4: -------------------------------------------------------------------------------- 1 | dnl wavpack 2 | 3 | AC_ARG_WITH(wavpack, AS_HELP_STRING([--without-wavpack], 4 | [Compile without WavPack support])) 5 | 6 | if test "x$with_wavpack" != "xno" 7 | then 8 | PKG_CHECK_MODULES(WAVPACK, [wavpack >= 4.31], 9 | [AC_SUBST(WAVPACK_LIBS) 10 | AC_SUBST(WAVPACK_CFLAGS) 11 | want_wavpack="yes" 12 | DECODER_PLUGINS="$DECODER_PLUGINS wavpack"], 13 | [true]) 14 | fi 15 | 16 | AM_CONDITIONAL([BUILD_wavpack], [test "$want_wavpack"]) 17 | AC_CONFIG_FILES([decoder_plugins/wavpack/Makefile]) 18 | -------------------------------------------------------------------------------- /doxy_pages/main_page.doxy: -------------------------------------------------------------------------------- 1 | /** \mainpage Internal API documentation 2 | 3 | \author Damian Pietras 4 | 5 | \section introduction Introduction 6 | 7 | This document describes the part of the internal API that can be used to add 8 | support for a new file format or sound output method. Everything that is 9 | required or may be useful is documented, the rest changes too often. 10 | 11 | I hope this documentation is up-to-date enough and contains sufficiently few 12 | errors to make it useful... . 13 | 14 | \section documented_parts Documented parts of the API 15 | 16 | There are two main parts of the API you in which you could be interested: 17 | 18 | \li \ref decoder_api 19 | \li \ref sound_output_driver_api 20 | 21 | */ 22 | -------------------------------------------------------------------------------- /doxy_pages/sound_output_driver_api.doxy: -------------------------------------------------------------------------------- 1 | /** \page sound_output_driver_api Sound output driver API 2 | 3 | \section sound_output_driver_api_introduction Introduction 4 | 5 | This is the sound output driver API. Sorry, no introduction here, you must 6 | see hw_funcs description and some examples. (null_out.c does nothing, but 7 | it's the simplest driver and can be used as a template.) 8 | 9 | */ 10 | -------------------------------------------------------------------------------- /equalizer.h: -------------------------------------------------------------------------------- 1 | #ifndef EQUALIZER_H 2 | #define EQUALIZER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void equalizer_init(); 9 | void equalizer_shutdown(); 10 | void equalizer_process_buffer(char *buf, size_t size, const struct sound_params *sound_params); 11 | void equalizer_refresh(); 12 | int equalizer_is_active(); 13 | int equalizer_set_active(int active); 14 | char *equalizer_current_eqname(); 15 | void equalizer_next(); 16 | void equalizer_prev(); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /fifo_buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2005 Damian Pietras 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | */ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include "config.h" 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "common.h" 22 | #include "fifo_buf.h" 23 | 24 | struct fifo_buf 25 | { 26 | int size; /* Size of the buffer */ 27 | int pos; /* Current position */ 28 | int fill; /* Current fill */ 29 | char buf[]; /* The buffer content */ 30 | }; 31 | 32 | /* Initialize and return a new fifo_buf structure of the size requested. */ 33 | struct fifo_buf *fifo_buf_new (const size_t size) 34 | { 35 | struct fifo_buf *b; 36 | 37 | assert (size > 0); 38 | 39 | b = xmalloc (offsetof (struct fifo_buf, buf) + size); 40 | 41 | b->size = size; 42 | b->pos = 0; 43 | b->fill = 0; 44 | 45 | return b; 46 | } 47 | 48 | /* Destroy the buffer object. */ 49 | void fifo_buf_free (struct fifo_buf *b) 50 | { 51 | assert (b != NULL); 52 | 53 | free (b); 54 | } 55 | 56 | /* Put data into the buffer. Returns number of bytes actually put. */ 57 | size_t fifo_buf_put (struct fifo_buf *b, const char *data, size_t size) 58 | { 59 | size_t written = 0; 60 | 61 | assert (b != NULL); 62 | assert (b->buf != NULL); 63 | 64 | while (b->fill < b->size && written < size) { 65 | size_t write_from; 66 | size_t to_write; 67 | 68 | if (b->pos + b->fill < b->size) { 69 | write_from = b->pos + b->fill; 70 | to_write = b->size - (b->pos + b->fill); 71 | } 72 | else { 73 | write_from = b->fill - b->size + b->pos; 74 | to_write = b->size - b->fill; 75 | } 76 | 77 | if (to_write > size - written) 78 | to_write = size - written; 79 | 80 | memcpy (b->buf + write_from, data + written, to_write); 81 | b->fill += to_write; 82 | written += to_write; 83 | } 84 | 85 | return written; 86 | } 87 | 88 | /* Copy data from the beginning of the buffer to the user buffer. Returns the 89 | * number of bytes copied. */ 90 | size_t fifo_buf_peek (struct fifo_buf *b, char *user_buf, size_t user_buf_size) 91 | { 92 | size_t user_buf_pos = 0, written = 0; 93 | ssize_t left, pos; 94 | 95 | assert (b != NULL); 96 | assert (b->buf != NULL); 97 | 98 | left = b->fill; 99 | pos = b->pos; 100 | 101 | while (left && written < user_buf_size) { 102 | size_t to_copy = pos + left <= b->size 103 | ? left : b->size - pos; 104 | 105 | if (to_copy > user_buf_size - written) 106 | to_copy = user_buf_size - written; 107 | 108 | memcpy (user_buf + user_buf_pos, b->buf + pos, to_copy); 109 | user_buf_pos += to_copy; 110 | written += to_copy; 111 | 112 | left -= to_copy; 113 | pos += to_copy; 114 | if (pos == b->size) 115 | pos = 0; 116 | } 117 | 118 | return written; 119 | } 120 | 121 | size_t fifo_buf_get (struct fifo_buf *b, char *user_buf, size_t user_buf_size) 122 | { 123 | size_t user_buf_pos = 0, written = 0; 124 | 125 | assert (b != NULL); 126 | assert (b->buf != NULL); 127 | 128 | while (b->fill && written < user_buf_size) { 129 | size_t to_copy = b->pos + b->fill <= b->size 130 | ? b->fill : b->size - b->pos; 131 | 132 | if (to_copy > user_buf_size - written) 133 | to_copy = user_buf_size - written; 134 | 135 | memcpy (user_buf + user_buf_pos, b->buf + b->pos, to_copy); 136 | user_buf_pos += to_copy; 137 | written += to_copy; 138 | 139 | b->fill -= to_copy; 140 | b->pos += to_copy; 141 | if (b->pos == b->size) 142 | b->pos = 0; 143 | } 144 | 145 | return written; 146 | } 147 | 148 | /* Get the amount of free space in the buffer. */ 149 | size_t fifo_buf_get_space (const struct fifo_buf *b) 150 | { 151 | assert (b != NULL); 152 | assert (b->buf != NULL); 153 | 154 | return b->size - b->fill; 155 | 156 | } 157 | 158 | size_t fifo_buf_get_fill (const struct fifo_buf *b) 159 | { 160 | assert (b != NULL); 161 | return b->fill; 162 | } 163 | 164 | size_t fifo_buf_get_size (const struct fifo_buf *b) 165 | { 166 | assert (b != NULL); 167 | return b->size; 168 | } 169 | 170 | void fifo_buf_clear (struct fifo_buf *b) 171 | { 172 | assert (b != NULL); 173 | b->fill = 0; 174 | } 175 | -------------------------------------------------------------------------------- /fifo_buf.h: -------------------------------------------------------------------------------- 1 | #ifndef FIFO_BUF_H 2 | #define FIFO_BUF_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct fifo_buf; 9 | 10 | struct fifo_buf *fifo_buf_new (const size_t size); 11 | void fifo_buf_free (struct fifo_buf *b); 12 | size_t fifo_buf_put (struct fifo_buf *b, const char *data, size_t size); 13 | size_t fifo_buf_get (struct fifo_buf *b, char *user_buf, size_t user_buf_size); 14 | size_t fifo_buf_peek (struct fifo_buf *b, char *user_buf, size_t user_buf_size); 15 | size_t fifo_buf_get_space (const struct fifo_buf *b); 16 | void fifo_buf_clear (struct fifo_buf *b); 17 | size_t fifo_buf_get_fill (const struct fifo_buf *b); 18 | size_t fifo_buf_get_size (const struct fifo_buf *b); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /files.h: -------------------------------------------------------------------------------- 1 | #ifndef FILES_H 2 | #define FILES_H 3 | 4 | #include 5 | #include "lists.h" 6 | #include "playlist.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #define FILES_LIST_INIT_SIZE 64 13 | 14 | void files_init (); 15 | void files_cleanup (); 16 | int read_directory (const char *directory, lists_t_strs *dirs, 17 | lists_t_strs *playlists, struct plist *plist); 18 | int read_directory_recurr (const char *directory, struct plist *plist); 19 | void resolve_path (char *buf, size_t size, const char *file); 20 | char *ext_pos (const char *file); 21 | enum file_type file_type (const char *file); 22 | char *file_mime_type (const char *file); 23 | int is_url (const char *str); 24 | char *read_line (FILE *file); 25 | char *find_match_dir (char *dir); 26 | int file_exists (const char *file); 27 | time_t get_mtime (const char *file); 28 | struct file_tags *read_file_tags (const char *file, 29 | struct file_tags *present_tags, const int tags_sel); 30 | void switch_titles_file (struct plist *plist); 31 | void switch_titles_tags (struct plist *plist); 32 | void make_tags_title (struct plist *plist, const int num); 33 | void make_file_title (struct plist *plist, const int num, 34 | const bool hide_extension); 35 | int is_dir (const char *file); 36 | int can_read_file (const char *file); 37 | char *absolute_path (const char *path, const char *cwd); 38 | bool is_secure (const char *file); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /interface.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef INTERFACE_H 3 | #define INTERFACE_H 4 | 5 | #include "lists.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | /* The desired state of the client (and server). */ 12 | enum want_quit { 13 | NO_QUIT, /* don't want to quit */ 14 | QUIT_CLIENT, /* only quit the client */ 15 | QUIT_SERVER /* quit the client and the server */ 16 | }; 17 | 18 | /* Information about the currently played file. */ 19 | struct file_tags; 20 | struct file_info { 21 | char *file; 22 | struct file_tags *tags; 23 | char *title; 24 | int avg_bitrate; 25 | int bitrate; 26 | int rate; 27 | int curr_time; 28 | int total_time; 29 | int channels; 30 | int state; /* STATE_* */ 31 | char *block_file; 32 | int block_start; 33 | int block_end; 34 | }; 35 | 36 | void init_interface (const int sock, const int logging, lists_t_strs *args); 37 | void interface_loop (); 38 | void interface_end (); 39 | int user_wants_interrupt (); 40 | void interface_error (const char *msg); 41 | void interface_fatal (const char *format, ...) ATTR_PRINTF(1, 2); 42 | void interface_cmdline_clear_plist (int server_sock); 43 | void interface_cmdline_append (int server_sock, lists_t_strs *args); 44 | void interface_cmdline_play_first (int server_sock); 45 | void interface_cmdline_file_info (const int server_sock); 46 | void interface_cmdline_playit (int server_sock, lists_t_strs *args); 47 | void interface_cmdline_seek_by (int server_sock, const int seek_by); 48 | void interface_cmdline_jump_to_percent (int server_sock, const int percent); 49 | void interface_cmdline_jump_to (int server_sock, const int pos); 50 | void interface_cmdline_adj_volume (int server_sock, const char *arg); 51 | void interface_cmdline_set (int server_sock, char *arg, const int val); 52 | void interface_cmdline_formatted_info (const int server_sock, const char *format_str); 53 | void interface_cmdline_enqueue (int server_sock, lists_t_strs *args); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /interface_elements.h: -------------------------------------------------------------------------------- 1 | #ifndef INTERFACE_ELEMENTS_H 2 | #define INTERFACE_ELEMENTS_H 3 | 4 | #if defined HAVE_NCURSESW_CURSES_H 5 | # include 6 | #elif defined HAVE_NCURSESW_H 7 | # include 8 | #elif defined HAVE_NCURSES_CURSES_H 9 | # include 10 | #elif defined HAVE_NCURSES_H 11 | # include 12 | #elif defined HAVE_CURSES_H 13 | # include 14 | #endif 15 | 16 | #include 17 | #include 18 | 19 | #include "lists.h" 20 | #include "files.h" 21 | #include "keys.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Interface's menus */ 28 | enum iface_menu 29 | { 30 | IFACE_MENU_PLIST, 31 | IFACE_MENU_DIR 32 | }; 33 | 34 | typedef void t_user_reply_callback (const char *reply, void *data); 35 | 36 | enum entry_type 37 | { 38 | ENTRY_SEARCH, 39 | ENTRY_PLIST_SAVE, 40 | ENTRY_GO_DIR, 41 | ENTRY_GO_URL, 42 | ENTRY_ADD_URL, 43 | ENTRY_PLIST_OVERWRITE, 44 | ENTRY_USER_QUERY 45 | }; 46 | 47 | struct iface_key 48 | { 49 | /* Type of the key */ 50 | enum 51 | { 52 | IFACE_KEY_CHAR, /* Regular char */ 53 | IFACE_KEY_FUNCTION /* Function key (arrow, F12, etc.) */ 54 | } type; 55 | 56 | union { 57 | wchar_t ucs; /* IFACE_KEY_CHAR */ 58 | int func; /* IFACE_KEY_FUNCTION */ 59 | } key; 60 | }; 61 | 62 | void windows_init (); 63 | void windows_reset (); 64 | void windows_end (); 65 | void iface_set_option_state (const char *name, const bool value); 66 | void iface_set_mixer_name (const char *name); 67 | void iface_set_status (const char *msg); 68 | void iface_set_dir_content (const enum iface_menu iface_menu, 69 | const struct plist *files, 70 | const lists_t_strs *dirs, 71 | const lists_t_strs *playlists); 72 | void iface_update_dir_content (const enum iface_menu iface_menu, 73 | const struct plist *files, 74 | const lists_t_strs *dirs, 75 | const lists_t_strs *playlists); 76 | void iface_set_curr_item_title (const char *title); 77 | void iface_get_key (struct iface_key *k); 78 | int iface_key_is_resize (const struct iface_key *k); 79 | void iface_menu_key (const enum key_cmd cmd); 80 | enum file_type iface_curritem_get_type (); 81 | int iface_in_dir_menu (); 82 | int iface_in_plist_menu (); 83 | int iface_in_theme_menu (); 84 | char *iface_get_curr_file (); 85 | void iface_update_item (const enum iface_menu menu, const struct plist *plist, 86 | const int n); 87 | void iface_set_curr_time (const int time); 88 | void iface_set_total_time (const int time); 89 | void iface_set_block (const int start_time, const int end_time); 90 | void iface_set_state (const int state); 91 | void iface_set_bitrate (const int bitrate); 92 | void iface_set_rate (const int rate); 93 | void iface_set_channels (const int channels); 94 | void iface_set_played_file (const char *file); 95 | void iface_set_played_file_title (const char *title); 96 | void iface_set_mixer_value (const int value); 97 | void iface_set_files_in_queue (const int num); 98 | void iface_tick (); 99 | void iface_switch_to_plist (); 100 | void iface_switch_to_dir (); 101 | void iface_add_to_plist (const struct plist *plist, const int num); 102 | void iface_error (const char *msg); 103 | void iface_resize (); 104 | void iface_refresh (); 105 | void iface_update_show_time (); 106 | void iface_update_show_format (); 107 | void iface_clear_plist (); 108 | void iface_del_plist_item (const char *file); 109 | enum entry_type iface_get_entry_type (); 110 | int iface_in_entry (); 111 | void iface_make_entry (const enum entry_type type); 112 | void iface_entry_handle_key (const struct iface_key *k); 113 | void iface_entry_set_text (const char *text); 114 | char *iface_entry_get_text (); 115 | void iface_entry_history_add (); 116 | void iface_entry_disable (); 117 | void iface_entry_set_file (const char *file); 118 | char *iface_entry_get_file (); 119 | void iface_message (const char *msg); 120 | void iface_disable_message (); 121 | void iface_user_query (const char *msg, const char *prompt, t_user_reply_callback *callback, void *data); 122 | void iface_user_reply (const char *reply); 123 | void iface_user_history_add (const char *text); 124 | void iface_plist_set_total_time (const int time, const int for_all_files); 125 | void iface_set_title (const enum iface_menu menu, const char *title); 126 | void iface_select_file (const char *file); 127 | int iface_in_help (); 128 | void iface_switch_to_help (); 129 | void iface_handle_help_key (const struct iface_key *k); 130 | int iface_in_lyrics (); 131 | void iface_switch_to_lyrics (); 132 | void iface_handle_lyrics_key (const struct iface_key *k); 133 | void iface_toggle_layout (); 134 | void iface_toggle_percent (); 135 | void iface_swap_plist_items (const char *file1, const char *file2); 136 | void iface_make_visible (const enum iface_menu menu, const char *file); 137 | void iface_switch_to_theme_menu (); 138 | void iface_add_file (const char *file, const char *title, 139 | const enum file_type type); 140 | void iface_temporary_exit (); 141 | void iface_restore (); 142 | void iface_load_lyrics (const char *file); 143 | void iface_update_queue_positions (const struct plist *queue, 144 | struct plist *playlist, struct plist *dir_list, 145 | const char *deleted_file); 146 | void iface_clear_queue_positions (const struct plist *queue, 147 | struct plist *playlist, struct plist *dir_list); 148 | void iface_update_queue_position_last (const struct plist *queue, 149 | struct plist *playlist, struct plist *dir_list); 150 | void iface_update_attrs (); 151 | void iface_update_theme_selection (const char *file); 152 | 153 | #ifdef __cplusplus 154 | } 155 | #endif 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_H 2 | #define IO_H 3 | 4 | #include 5 | #include 6 | #ifdef HAVE_CURL 7 | # include /* curl sometimes needs this */ 8 | # include 9 | #endif 10 | 11 | #include "fifo_buf.h" 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | enum io_source 18 | { 19 | IO_SOURCE_FD, 20 | IO_SOURCE_MMAP, 21 | IO_SOURCE_CURL 22 | }; 23 | 24 | #ifdef HAVE_CURL 25 | struct io_stream_curl 26 | { 27 | CURLM *multi_handle; /* we use the multi interface to get the 28 | data in pieces */ 29 | CURL *handle; /* the actual used handle */ 30 | CURLMcode multi_status; /* curl status of the last multi operation */ 31 | CURLcode status; /* curl status of the last easy operation */ 32 | char *url; 33 | struct curl_slist *http_headers; /* HTTP headers to send with 34 | the request */ 35 | char *buf; /* buffer for data that curl gives us */ 36 | long buf_fill; 37 | int need_perform_loop; /* do we need the perform() loop? */ 38 | int got_locn; /* received a location header */ 39 | char *mime_type; /* mime type of the stream */ 40 | int wake_up_pipe[2]; /* pipes used to wake up the curl read 41 | loop that does select() */ 42 | struct curl_slist *http200_aliases; /* list of aliases for http 43 | response's status line */ 44 | size_t icy_meta_int; /* how often are icy metadata sent? 45 | 0 - disabled, in bytes */ 46 | size_t icy_meta_count; /* how many bytes was read from the last 47 | metadata packet */ 48 | }; 49 | #endif 50 | 51 | struct io_stream; 52 | 53 | typedef void (*buf_fill_callback_t) (struct io_stream *s, size_t fill, 54 | size_t buf_size, void *data_ptr); 55 | 56 | struct io_stream 57 | { 58 | enum io_source source; /* source of the file */ 59 | int fd; 60 | off_t size; /* size of the file */ 61 | int errno_val; /* errno value of the last operation - 0 if ok */ 62 | int read_error; /* set to != 0 if the last read operation dailed */ 63 | char *strerror; /* error string */ 64 | int opened; /* was the stream opened (open(), mmap(), etc.)? */ 65 | int eof; /* was the end of file reached? */ 66 | int after_seek; /* are we after seek and need to do fresh read()? */ 67 | int buffered; /* are we using the buffer? */ 68 | off_t pos; /* current position in the file from the user point of view */ 69 | size_t prebuffer; /* number of bytes left to prebuffer */ 70 | pthread_mutex_t io_mtx; /* mutex for IO operations */ 71 | 72 | #ifdef HAVE_MMAP 73 | void *mem; 74 | off_t mem_pos; 75 | #endif 76 | 77 | #ifdef HAVE_CURL 78 | struct io_stream_curl curl; 79 | #endif 80 | 81 | struct fifo_buf *buf; 82 | pthread_mutex_t buf_mtx; 83 | pthread_cond_t buf_free_cond; /* some space became available in the 84 | buffer */ 85 | pthread_cond_t buf_fill_cond; /* the buffer was filled with some data */ 86 | pthread_t read_thread; 87 | int stop_read_thread; /* request for stopping the read 88 | thread */ 89 | 90 | struct stream_metadata { 91 | pthread_mutex_t mtx; 92 | char *title; /* title of the stream */ 93 | char *url; 94 | } metadata; 95 | 96 | /* callbacks */ 97 | buf_fill_callback_t buf_fill_callback; 98 | void *buf_fill_callback_data; 99 | }; 100 | 101 | struct io_stream *io_open (const char *file, const int buffered); 102 | ssize_t io_read (struct io_stream *s, void *buf, size_t count); 103 | ssize_t io_peek (struct io_stream *s, void *buf, size_t count); 104 | off_t io_seek (struct io_stream *s, off_t offset, int whence); 105 | void io_close (struct io_stream *s); 106 | int io_ok (struct io_stream *s); 107 | char *io_strerror (struct io_stream *s); 108 | off_t io_file_size (const struct io_stream *s); 109 | off_t io_tell (struct io_stream *s); 110 | int io_eof (struct io_stream *s); 111 | void io_init (); 112 | void io_cleanup (); 113 | void io_abort (struct io_stream *s); 114 | char *io_get_mime_type (struct io_stream *s); 115 | char *io_get_title (struct io_stream *s); 116 | char *io_get_metadata_title (struct io_stream *s); 117 | char *io_get_metadata_url (struct io_stream *s); 118 | void io_set_metadata_title (struct io_stream *s, const char *title); 119 | void io_set_metadata_url (struct io_stream *s, const char *url); 120 | void io_prebuffer (struct io_stream *s, const size_t to_fill); 121 | void io_set_buf_fill_callback (struct io_stream *s, 122 | buf_fill_callback_t callback, void *data_ptr); 123 | int io_seekable (const struct io_stream *s); 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /io_curl.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_CURL_H 2 | #define IO_CURL_H 3 | 4 | #include "io.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void io_curl_init (); 11 | void io_curl_cleanup (); 12 | void io_curl_open (struct io_stream *s, const char *url); 13 | void io_curl_close (struct io_stream *s); 14 | ssize_t io_curl_read (struct io_stream *s, char *buf, size_t count); 15 | void io_curl_strerror (struct io_stream *s); 16 | void io_curl_wake_up (struct io_stream *s); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /jack.h: -------------------------------------------------------------------------------- 1 | #ifndef JACK_H 2 | #define JACK_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void moc_jack_funcs (struct hw_funcs *funcs); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /keymap.example: -------------------------------------------------------------------------------- 1 | # This is the example keymap file for MOC. You can define your own key 2 | # bindings for MOC commands by creating your own keymap file and setting 3 | # the 'Keymap' option in ~/.moc/config. 4 | # 5 | # The format of this file is: 6 | # 7 | # - Lines beginning with # are comments. 8 | # - Blank lines are ignored. 9 | # - Every other line is expected to be in one of the formats: 10 | # 11 | # COMMAND = [KEY ...] 12 | # COMMAND += KEY ... 13 | # 14 | # The KEY can be: 15 | # 16 | # - Just a char, like i, L, ", * 17 | # - CTRL-KEY sequence: ^k (CTRL-k), ^4 18 | # - ALT-KEY (meta) sequence: M-j (ALT-j), M-/ 19 | # - Special keys: DOWN, UP 20 | # LEFT, RIGHT 21 | # HOME, END 22 | # BACKSPACE 23 | # INS, DEL 24 | # ENTER 25 | # PAGE_UP, PAGE_DOWN 26 | # SPACE, TAB 27 | # KEYPAD_CENTER 28 | # ESCAPE 29 | # F1 - F12 30 | # 31 | # Note that the use of a digit as a KEY is deprecated. 32 | # 33 | # Maximum number of KEYs for one COMMAND is 5. 34 | # 35 | # Omitting the KEY for a COMMAND will unbind all its default keys. They 36 | # will also be automatically unbound when you bind new KEYs to it. Individual 37 | # default KEYs will be automatically unbound when they are explicitly bound 38 | # to some other COMMAND. 39 | # 40 | # Using the '+=' form will cause the KEYs to be appended to any existing 41 | # (default or explicit) bindings for the COMMAND. Appending an existing 42 | # default binding for the same COMMAND will cause MOC to think of that KEY 43 | # as then being explicitly bound. 44 | # 45 | # Only one binding for any given COMMAND can appear in the keymap file. One 46 | # exception to this is that if the default keys for a COMMAND are explicitly 47 | # unbound then a subsequent binding may appear for it. A second exception 48 | # is that multiple appending bindings may appear. 49 | # 50 | # Meta-key detection is sensitive to the ESCDELAY environment variable (see 51 | # the manpage for ncurses(3)). In its absence, MOC resets the default 52 | # delay to 25ms. If you need to emulate meta-key sequences using the ESC 53 | # key, then you may need to set the value of ESCDELAY back to its ncurses 54 | # default of 1000ms (but doing so will make the response to the ESC key 55 | # sluggish). 56 | # 57 | # If MOC's keypresses are being filtered through some other program (in a 58 | # GUI environment, for example) which also does meta-key detection, then 59 | # MOC is at the mercy of the timings with which that program presents them. 60 | # 61 | # Default key configuration for MOC (and a list of all available commands): 62 | 63 | # MOC control keys: 64 | quit_client = q 65 | quit = Q 66 | 67 | # Menu and interface control keys: 68 | go = ENTER 69 | menu_down = DOWN 70 | menu_up = UP 71 | menu_page_down = PAGE_DOWN 72 | menu_page_up = PAGE_UP 73 | menu_first_item = HOME 74 | menu_last_item = END 75 | search_menu = g / 76 | toggle_read_tags = f 77 | toggle_show_time = ^t 78 | toggle_show_format = ^f 79 | toggle_menu = TAB 80 | toggle_layout = l 81 | toggle_hidden_files = H 82 | show_lyrics = L 83 | theme_menu = T 84 | help = h ? 85 | refresh = ^r 86 | reload = r 87 | 88 | # Audio playing and positioning keys: 89 | seek_forward = RIGHT 90 | seek_backward = LEFT 91 | seek_forward_fast = ] 92 | seek_backward_fast = [ 93 | pause = p SPACE 94 | stop = s 95 | next = n 96 | previous = b 97 | toggle_shuffle = S 98 | toggle_repeat = R 99 | toggle_auto_next = X 100 | toggle_mixer = x 101 | go_url = o 102 | 103 | # Volume control keys: 104 | volume_down_1 = < 105 | volume_up_1 = > 106 | volume_down_5 = , 107 | volume_up_5 = . 108 | volume_10 = M-1 109 | volume_20 = M-2 110 | volume_30 = M-3 111 | volume_40 = M-4 112 | volume_50 = M-5 113 | volume_60 = M-6 114 | volume_70 = M-7 115 | volume_80 = M-8 116 | volume_90 = M-9 117 | 118 | # Directory navigation keys: defaults are Shift-number 119 | # (i.e., 'shift 1' -> '!' -> 'Fastdir1'). 120 | go_to_a_directory = i 121 | go_to_music_directory = m 122 | go_to_fast_dir1 = ! 123 | go_to_fast_dir2 = @ 124 | go_to_fast_dir3 = # 125 | go_to_fast_dir4 = $ 126 | go_to_fast_dir5 = % 127 | go_to_fast_dir6 = ^ 128 | go_to_fast_dir7 = & 129 | go_to_fast_dir8 = * 130 | go_to_fast_dir9 = ( 131 | go_to_fast_dir10 = ) 132 | go_to_playing_file = G 133 | go_up = U 134 | 135 | # Playlist specific keys: 136 | add_file = a 137 | add_directory = A 138 | plist_add_stream = ^u 139 | delete_from_playlist = d 140 | playlist_full_paths = P 141 | plist_move_up = u 142 | plist_move_down = j 143 | save_playlist = V 144 | remove_dead_entries = Y 145 | clear_playlist = C 146 | 147 | # Queue manipulation keys: 148 | enqueue_file = z 149 | clear_queue = Z 150 | 151 | # User interaction control: 152 | history_up = UP 153 | history_down = DOWN 154 | delete_to_start = ^u 155 | delete_to_end = ^k 156 | cancel = ^x ESCAPE 157 | hide_message = M 158 | 159 | # Softmixer specific keys: 160 | toggle_softmixer = w 161 | toggle_make_mono = J 162 | 163 | # Equalizer specific keys: 164 | toggle_equalizer = E 165 | equalizer_refresh = e 166 | equalizer_prev = K 167 | equalizer_next = k 168 | 169 | # External commands: 170 | mark_start = ' 171 | mark_end = " 172 | exec_command1 = F1 173 | exec_command2 = F2 174 | exec_command3 = F3 175 | exec_command4 = F4 176 | exec_command5 = F5 177 | exec_command6 = F6 178 | exec_command7 = F7 179 | exec_command8 = F8 180 | exec_command9 = F9 181 | exec_command10 = F10 182 | 183 | # The following commands are available but not assigned to any keys by 184 | # default: 185 | # 186 | # toggle_percent Switch on/off play progress bar time percentage 187 | # 188 | -------------------------------------------------------------------------------- /keys.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYS_H 2 | #define KEYS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | enum key_cmd 9 | { 10 | KEY_CMD_QUIT_CLIENT, 11 | KEY_CMD_GO, 12 | KEY_CMD_MENU_DOWN, 13 | KEY_CMD_MENU_UP, 14 | KEY_CMD_MENU_NPAGE, 15 | KEY_CMD_MENU_PPAGE, 16 | KEY_CMD_MENU_FIRST, 17 | KEY_CMD_MENU_LAST, 18 | KEY_CMD_QUIT, 19 | KEY_CMD_STOP, 20 | KEY_CMD_NEXT, 21 | KEY_CMD_PREVIOUS, 22 | KEY_CMD_PAUSE, 23 | KEY_CMD_TOGGLE_READ_TAGS, 24 | KEY_CMD_TOGGLE_REPEAT, 25 | KEY_CMD_TOGGLE_AUTO_NEXT, 26 | KEY_CMD_TOGGLE_MENU, 27 | KEY_CMD_TOGGLE_LAYOUT, 28 | KEY_CMD_TOGGLE_PERCENT, 29 | KEY_CMD_PLIST_ADD_FILE, 30 | KEY_CMD_PLIST_CLEAR, 31 | KEY_CMD_PLIST_ADD_DIR, 32 | KEY_CMD_PLIST_REMOVE_DEAD_ENTRIES, 33 | KEY_CMD_MIXER_DEC_1, 34 | KEY_CMD_MIXER_INC_1, 35 | KEY_CMD_MIXER_DEC_5, 36 | KEY_CMD_MIXER_INC_5, 37 | KEY_CMD_SEEK_FORWARD, 38 | KEY_CMD_SEEK_BACKWARD, 39 | KEY_CMD_SEEK_FORWARD_5, 40 | KEY_CMD_SEEK_BACKWARD_5, 41 | KEY_CMD_HELP, 42 | KEY_CMD_HIDE_MESSAGE, 43 | KEY_CMD_REFRESH, 44 | KEY_CMD_RELOAD, 45 | KEY_CMD_TOGGLE_SHOW_HIDDEN_FILES, 46 | KEY_CMD_GO_MUSIC_DIR, 47 | KEY_CMD_PLIST_DEL, 48 | KEY_CMD_MENU_SEARCH, 49 | KEY_CMD_PLIST_SAVE, 50 | KEY_CMD_TOGGLE_SHOW_FORMAT, 51 | KEY_CMD_TOGGLE_SHOW_TIME, 52 | KEY_CMD_GO_TO_PLAYING_FILE, 53 | KEY_CMD_GO_DIR, 54 | KEY_CMD_GO_DIR_UP, 55 | KEY_CMD_TOGGLE_SHUFFLE, 56 | KEY_CMD_CANCEL, 57 | KEY_CMD_GO_URL, 58 | KEY_CMD_VOLUME_10, 59 | KEY_CMD_VOLUME_20, 60 | KEY_CMD_VOLUME_30, 61 | KEY_CMD_VOLUME_40, 62 | KEY_CMD_VOLUME_50, 63 | KEY_CMD_VOLUME_60, 64 | KEY_CMD_VOLUME_70, 65 | KEY_CMD_VOLUME_80, 66 | KEY_CMD_VOLUME_90, 67 | KEY_CMD_MARK_START, 68 | KEY_CMD_MARK_END, 69 | KEY_CMD_FAST_DIR_1, 70 | KEY_CMD_FAST_DIR_2, 71 | KEY_CMD_FAST_DIR_3, 72 | KEY_CMD_FAST_DIR_4, 73 | KEY_CMD_FAST_DIR_5, 74 | KEY_CMD_FAST_DIR_6, 75 | KEY_CMD_FAST_DIR_7, 76 | KEY_CMD_FAST_DIR_8, 77 | KEY_CMD_FAST_DIR_9, 78 | KEY_CMD_FAST_DIR_10, 79 | KEY_CMD_TOGGLE_MIXER, 80 | KEY_CMD_HISTORY_UP, 81 | KEY_CMD_HISTORY_DOWN, 82 | KEY_CMD_DELETE_START, 83 | KEY_CMD_DELETE_END, 84 | KEY_CMD_PLIST_MOVE_UP, 85 | KEY_CMD_PLIST_MOVE_DOWN, 86 | KEY_CMD_ADD_STREAM, 87 | KEY_CMD_THEME_MENU, 88 | KEY_CMD_EXEC1, 89 | KEY_CMD_EXEC2, 90 | KEY_CMD_EXEC3, 91 | KEY_CMD_EXEC4, 92 | KEY_CMD_EXEC5, 93 | KEY_CMD_EXEC6, 94 | KEY_CMD_EXEC7, 95 | KEY_CMD_EXEC8, 96 | KEY_CMD_EXEC9, 97 | KEY_CMD_EXEC10, 98 | KEY_CMD_TOGGLE_PLAYLIST_FULL_PATHS, 99 | KEY_CMD_TOGGLE_SOFTMIXER, 100 | KEY_CMD_TOGGLE_EQUALIZER, 101 | KEY_CMD_EQUALIZER_REFRESH, 102 | KEY_CMD_EQUALIZER_PREV, 103 | KEY_CMD_EQUALIZER_NEXT, 104 | KEY_CMD_TOGGLE_MAKE_MONO, 105 | KEY_CMD_LYRICS, 106 | KEY_CMD_QUEUE_TOGGLE_FILE, 107 | KEY_CMD_QUEUE_CLEAR, 108 | KEY_CMD_WRONG 109 | }; 110 | 111 | /* Key context is the place where the user presses a key. A key can have 112 | * different meanings in different places. */ 113 | enum key_context 114 | { 115 | CON_MENU, 116 | CON_ENTRY_SEARCH, 117 | CON_ENTRY 118 | }; 119 | 120 | #ifndef KEY_ESCAPE 121 | # define KEY_ESCAPE 27 122 | #endif 123 | 124 | #define META_KEY_FLAG 0x80 125 | #define CTRL_KEY_CODE 0x1F 126 | 127 | struct iface_key; 128 | enum key_cmd get_key_cmd (const enum key_context context, const struct iface_key *key); 129 | void keys_init (); 130 | void keys_cleanup (); 131 | char **get_keys_help (int *num); 132 | bool is_help_still_h (); 133 | 134 | #ifdef __cplusplus 135 | } 136 | #endif 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /lists.h: -------------------------------------------------------------------------------- 1 | #ifndef LISTS_H 2 | #define LISTS_H 3 | 4 | #include "common.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef struct lists_strs lists_t_strs; 11 | typedef int lists_t_compare (const void *, const void *); 12 | 13 | /* List administration functions. */ 14 | lists_t_strs *lists_strs_new (int reserve); 15 | void lists_strs_clear (lists_t_strs *list); 16 | void lists_strs_free (lists_t_strs *list); 17 | int lists_strs_size (const lists_t_strs *list); 18 | int lists_strs_capacity (const lists_t_strs *list); 19 | bool lists_strs_empty (const lists_t_strs *list); 20 | 21 | /* List member access functions. */ 22 | char *lists_strs_at (const lists_t_strs *list, int index); 23 | 24 | /* List mutating functions. */ 25 | void lists_strs_sort (lists_t_strs *list, lists_t_compare *compare); 26 | void lists_strs_reverse (lists_t_strs *list); 27 | 28 | /* Ownership transferring functions. */ 29 | void lists_strs_push (lists_t_strs *list, char *s); 30 | char *lists_strs_pop (lists_t_strs *list); 31 | char *lists_strs_swap (lists_t_strs *list, int index, char *s); 32 | 33 | /* Ownership preserving functions. */ 34 | void lists_strs_append (lists_t_strs *list, const char *s); 35 | void lists_strs_remove (lists_t_strs *list); 36 | void lists_strs_replace (lists_t_strs *list, int index, char *s); 37 | 38 | /* Helper functions. */ 39 | int lists_strs_split (lists_t_strs *list, const char *s, const char *delim); 40 | int lists_strs_tokenise (lists_t_strs *list, const char *s); 41 | char *lists_strs_fmt (const lists_t_strs *list, const char *fmt); 42 | char *lists_strs_cat (const lists_t_strs *list); 43 | char **lists_strs_save (const lists_t_strs *list); 44 | int lists_strs_load (lists_t_strs *list, const char **saved); 45 | int lists_strs_find (lists_t_strs *list, const char *sought); 46 | bool lists_strs_exists (lists_t_strs *list, const char *sought); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_H 2 | #define LOG_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* Suppress overly-enthusiastic GNU variadic macro extensions warning. */ 11 | #if defined(__clang__) && HAVE_VARIADIC_MACRO_WARNING 12 | # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" 13 | #endif 14 | 15 | #ifdef DEBUG 16 | # define debug logit 17 | #else 18 | # define debug(...) do {} while (0) 19 | #endif 20 | 21 | #ifndef NDEBUG 22 | # define logit(...) \ 23 | internal_logit (__FILE__, __LINE__, __func__, ## __VA_ARGS__) 24 | #else 25 | # define logit(...) do {} while (0) 26 | #endif 27 | 28 | #ifndef STRERROR_FN 29 | # define STRERROR_FN xstrerror 30 | #endif 31 | 32 | #ifndef NDEBUG 33 | #define log_errno(format, errnum) \ 34 | do { \ 35 | char *err##__LINE__ = STRERROR_FN (errnum); \ 36 | logit (format ": %s", err##__LINE__); \ 37 | free (err##__LINE__); \ 38 | } while (0) 39 | #else 40 | # define log_errno(...) do {} while (0) 41 | #endif 42 | 43 | void internal_logit (const char *file, const int line, const char *function, 44 | const char *format, ...) ATTR_PRINTF(4, 5); 45 | 46 | #ifndef NDEBUG 47 | # define LOGIT_ONLY 48 | #else 49 | # define LOGIT_ONLY ATTR_UNUSED 50 | #endif 51 | 52 | #if !defined(NDEBUG) && defined(DEBUG) 53 | # define DEBUG_ONLY 54 | #else 55 | # define DEBUG_ONLY ATTR_UNUSED 56 | #endif 57 | 58 | void log_init_stream (FILE *f, const char *fn); 59 | void log_circular_start (); 60 | void log_circular_log (); 61 | void log_circular_reset (); 62 | void log_circular_stop (); 63 | void log_close (); 64 | 65 | #ifndef NDEBUG 66 | void log_signal (int sig); 67 | #else 68 | # define log_signal(...) do {} while (0) 69 | #endif 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /lyrics.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2008-2009 Geraud Le Falher and John Fitzgerald 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | */ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include "config.h" 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "common.h" 21 | #include "files.h" 22 | #include "log.h" 23 | #include "options.h" 24 | #include "lists.h" 25 | #include "lyrics.h" 26 | 27 | static lists_t_strs *raw_lyrics = NULL; 28 | static const char *lyrics_message = NULL; 29 | 30 | /* Return the list of lyrics lines, or NULL if none are loaded. */ 31 | lists_t_strs *lyrics_lines_get (void) 32 | { 33 | return raw_lyrics; 34 | } 35 | 36 | /* Store new lyrics lines as supplied. */ 37 | void lyrics_lines_set (lists_t_strs *lines) 38 | { 39 | assert (!raw_lyrics); 40 | assert (lines); 41 | 42 | raw_lyrics = lines; 43 | lyrics_message = NULL; 44 | } 45 | 46 | /* Return a list of lyrics lines loaded from a file, or NULL on error. */ 47 | lists_t_strs *lyrics_load_file (const char *filename) 48 | { 49 | int text_plain; 50 | FILE *lyrics_file = NULL; 51 | char *mime, *line; 52 | lists_t_strs *result; 53 | 54 | assert (filename); 55 | 56 | lyrics_message = "[No lyrics file!]"; 57 | if (!file_exists (filename)) 58 | return NULL; 59 | mime = file_mime_type (filename); 60 | text_plain = mime ? !strncmp (mime, "text/plain", 10) : 0; 61 | free (mime); 62 | if (!text_plain) 63 | return NULL; 64 | 65 | lyrics_file = fopen (filename, "r"); 66 | if (lyrics_file == NULL) { 67 | char *err = xstrerror (errno); 68 | logit ("Error reading '%s': %s", filename, err); 69 | free (err); 70 | lyrics_message = "[Lyrics file cannot be read!]"; 71 | return NULL; 72 | } 73 | 74 | result = lists_strs_new (0); 75 | while ((line = read_line (lyrics_file)) != NULL) 76 | lists_strs_push (result, line); 77 | fclose (lyrics_file); 78 | 79 | lyrics_message = NULL; 80 | return result; 81 | } 82 | 83 | /* Given an audio's file name, load lyrics from the default lyrics file name. */ 84 | void lyrics_autoload (const char *filename) 85 | { 86 | char *lyrics_filename, *extn; 87 | 88 | assert (!raw_lyrics); 89 | assert (lyrics_message); 90 | 91 | if (filename == NULL) { 92 | lyrics_message = "[No file playing!]"; 93 | return; 94 | } 95 | 96 | if (!options_get_bool ("AutoLoadLyrics")) { 97 | lyrics_message = "[Lyrics not autoloaded!]"; 98 | return; 99 | } 100 | 101 | if (is_url (filename)) { 102 | lyrics_message = "[Lyrics from URL is not supported!]"; 103 | return; 104 | } 105 | 106 | lyrics_filename = xstrdup (filename); 107 | extn = ext_pos (lyrics_filename); 108 | if (extn) { 109 | *--extn = '\0'; 110 | raw_lyrics = lyrics_load_file (lyrics_filename); 111 | } 112 | else 113 | lyrics_message = "[No lyrics file!]"; 114 | 115 | free (lyrics_filename); 116 | } 117 | 118 | /* Given a line, return a centred copy of it. */ 119 | static char *centre_line (const char* line, int max) 120 | { 121 | char *result; 122 | int len; 123 | 124 | len = strlen (line); 125 | if (len < (max - 1)) { 126 | int space; 127 | 128 | space = (max - len) / 2; 129 | result = (char *) xmalloc (space + len + 2); 130 | memset (result, ' ', space); 131 | strcpy (&result[space], line); 132 | len += space; 133 | } 134 | else { 135 | result = (char *) xmalloc (max + 2); 136 | strncpy (result, line, max); 137 | len = max; 138 | } 139 | strcpy (&result[len], "\n"); 140 | 141 | return result; 142 | } 143 | 144 | /* Centre all the lines in the lyrics. */ 145 | static lists_t_strs *centre_style (lists_t_strs *lines, int unused1 ATTR_UNUSED, 146 | int width, void *unused2 ATTR_UNUSED) 147 | { 148 | lists_t_strs *result; 149 | int ix, size; 150 | 151 | size = lists_strs_size (lines); 152 | result = lists_strs_new (size); 153 | for (ix = 0; ix < size; ix += 1) { 154 | char *old_line, *new_line; 155 | 156 | old_line = lists_strs_at (lines, ix); 157 | new_line = centre_line (old_line, width); 158 | lists_strs_push (result, new_line); 159 | } 160 | 161 | return result; 162 | } 163 | 164 | /* Formatting function information. */ 165 | static lyrics_t_formatter *lyrics_formatter = centre_style; 166 | static lyrics_t_reaper *formatter_reaper = NULL; 167 | static void *formatter_data = NULL; 168 | 169 | /* Register a new function to be used for formatting. A NULL formatter 170 | * resets formatting to the default centred style. */ 171 | void lyrics_use_formatter (lyrics_t_formatter formatter, 172 | lyrics_t_reaper reaper, void *data) 173 | { 174 | if (formatter_reaper) 175 | formatter_reaper (formatter_data); 176 | 177 | if (formatter) { 178 | lyrics_formatter = formatter; 179 | formatter_reaper = reaper; 180 | formatter_data = data; 181 | } 182 | else { 183 | lyrics_formatter = centre_style; 184 | formatter_reaper = NULL; 185 | formatter_data = NULL; 186 | } 187 | } 188 | 189 | /* Return a list of either the formatted lyrics if any are loaded or 190 | * a centred message. */ 191 | lists_t_strs *lyrics_format (int height, int width) 192 | { 193 | int ix; 194 | lists_t_strs *result; 195 | 196 | assert (raw_lyrics || lyrics_message); 197 | 198 | result = NULL; 199 | 200 | if (raw_lyrics) { 201 | result = lyrics_formatter (raw_lyrics, height, width - 1, 202 | formatter_data); 203 | if (!result) 204 | lyrics_message = "[Error formatting lyrics!]"; 205 | } 206 | 207 | if (!result) { 208 | char *line; 209 | 210 | result = lists_strs_new (1); 211 | line = centre_line (lyrics_message, width - 1); 212 | lists_strs_push (result, line); 213 | } 214 | 215 | for (ix = 0; ix < lists_strs_size (result); ix += 1) { 216 | int len; 217 | char *this_line; 218 | 219 | this_line = lists_strs_at (result, ix); 220 | len = strlen (this_line); 221 | if (len > width - 1) 222 | strcpy (&this_line[width - 1], "\n"); 223 | else if (this_line[len - 1] != '\n') { 224 | char *new_line; 225 | 226 | new_line = xmalloc (len + 2); 227 | strcpy (new_line, this_line); 228 | strcat (new_line, "\n"); 229 | lists_strs_swap (result, ix, new_line); 230 | free (this_line); 231 | } 232 | } 233 | 234 | return result; 235 | } 236 | 237 | /* Dispose of raw lyrics lines. */ 238 | void lyrics_cleanup (void) 239 | { 240 | if (raw_lyrics) { 241 | lists_strs_free (raw_lyrics); 242 | raw_lyrics = NULL; 243 | } 244 | 245 | lyrics_message = "[No lyrics loaded!]"; 246 | } 247 | -------------------------------------------------------------------------------- /lyrics.h: -------------------------------------------------------------------------------- 1 | #ifndef LYRICS_H 2 | #define LYRICS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef lists_t_strs *lyrics_t_formatter (lists_t_strs *lines, int height, int width, void *data); 9 | typedef void lyrics_t_reaper (void *data); 10 | 11 | lists_t_strs *lyrics_lines_get (void); 12 | void lyrics_lines_set (lists_t_strs *lines); 13 | lists_t_strs *lyrics_load_file (const char *filename); 14 | void lyrics_autoload (const char *filename); 15 | void lyrics_use_formatter (lyrics_t_formatter, lyrics_t_reaper, void *data); 16 | lists_t_strs *lyrics_format (int height, int width); 17 | void lyrics_cleanup (void); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /m4/ax_c___attribute__.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_c___attribute__.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_C___ATTRIBUTE__ 8 | # 9 | # DESCRIPTION 10 | # 11 | # Provides a test for the compiler support of __attribute__ extensions. 12 | # Defines HAVE___ATTRIBUTE__ if it is found. 13 | # 14 | # LICENSE 15 | # 16 | # Copyright (c) 2008 Stepan Kasal 17 | # Copyright (c) 2008 Christian Haggstrom 18 | # Copyright (c) 2008 Ryan McCabe 19 | # 20 | # This program is free software; you can redistribute it and/or modify it 21 | # under the terms of the GNU General Public License as published by the 22 | # Free Software Foundation; either version 2 of the License, or (at your 23 | # option) any later version. 24 | # 25 | # This program is distributed in the hope that it will be useful, but 26 | # WITHOUT ANY WARRANTY; without even the implied warranty of 27 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 28 | # Public License for more details. 29 | # 30 | # You should have received a copy of the GNU General Public License along 31 | # with this program. If not, see . 32 | # 33 | # As a special exception, the respective Autoconf Macro's copyright owner 34 | # gives unlimited permission to copy, distribute and modify the configure 35 | # scripts that are the output of Autoconf when processing the Macro. You 36 | # need not follow the terms of the GNU General Public License when using 37 | # or distributing such scripts, even though portions of the text of the 38 | # Macro appear in them. The GNU General Public License (GPL) does govern 39 | # all other use of the material that constitutes the Autoconf Macro. 40 | # 41 | # This special exception to the GPL applies to versions of the Autoconf 42 | # Macro released by the Autoconf Archive. When you make and distribute a 43 | # modified version of the Autoconf Macro, you may extend this special 44 | # exception to the GPL to apply to your modified version as well. 45 | 46 | #serial 8 47 | 48 | AC_DEFUN([AX_C___ATTRIBUTE__], [ 49 | AC_CACHE_CHECK([for __attribute__], [ax_cv___attribute__], 50 | [AC_COMPILE_IFELSE( 51 | [AC_LANG_PROGRAM( 52 | [[#include 53 | static void foo(void) __attribute__ ((unused)); 54 | static void 55 | foo(void) { 56 | exit(1); 57 | } 58 | ]], [])], 59 | [ax_cv___attribute__=yes], 60 | [ax_cv___attribute__=no] 61 | ) 62 | ]) 63 | if test "$ax_cv___attribute__" = "yes"; then 64 | AC_DEFINE([HAVE___ATTRIBUTE__], 1, [define if your compiler has __attribute__]) 65 | fi 66 | ]) 67 | -------------------------------------------------------------------------------- /m4/ax_cflags_gcc_option.m4: -------------------------------------------------------------------------------- 1 | dnl @synopsis AX_CFLAGS_GCC_OPTION (optionflag [,[shellvar][,[A][,[NA]]]) 2 | dnl 3 | dnl AX_CFLAGS_GCC_OPTION(-fvomit-frame) would show a message as like 4 | dnl "checking CFLAGS for gcc -fvomit-frame ... yes" and adds 5 | dnl the optionflag to CFLAGS if it is understood. You can override 6 | dnl the shellvar-default of CFLAGS of course. The order of arguments 7 | dnl stems from the explicit macros like AX_CFLAGS_WARN_ALL. 8 | dnl 9 | dnl The cousin AX_CXXFLAGS_GCC_OPTION would check for an option to add 10 | dnl to CXXFLAGS - and it uses the autoconf setup for C++ instead of C 11 | dnl (since it is possible to use different compilers for C and C++). 12 | dnl 13 | dnl The macro is a lot simpler than any special AX_CFLAGS_* macro (or 14 | dnl ac_cxx_rtti.m4 macro) but allows to check for arbitrary options. 15 | dnl However, if you use this macro in a few places, it would be great 16 | dnl if you would make up a new function-macro and submit it to the 17 | dnl ac-archive. 18 | dnl 19 | dnl - $1 option-to-check-for : required ("-option" as non-value) 20 | dnl - $2 shell-variable-to-add-to : CFLAGS (or CXXFLAGS in the other case) 21 | dnl - $3 action-if-found : add value to shellvariable 22 | dnl - $4 action-if-not-found : nothing 23 | dnl 24 | dnl note: in earlier versions, $1-$2 were swapped. We try to detect the 25 | dnl situation and accept a $2=~/-/ as being the old option-to-check-for. 26 | dnl 27 | dnl also: there are other variants that emerged from the original macro 28 | dnl variant which did just test an option to be possibly added. However, 29 | dnl some compilers accept an option silently, or possibly for just 30 | dnl another option that was not intended. Therefore, we have to do a 31 | dnl generic test for a compiler family. For gcc we check "-pedantic" 32 | dnl being accepted which is also understood by compilers who just want 33 | dnl to be compatible with gcc even when not being made from gcc sources. 34 | dnl 35 | dnl see also: 36 | dnl AX_CFLAGS_SUN_OPTION AX_CFLAGS_HPUX_OPTION 37 | dnl AX_CFLAGS_AIX_OPTION AX_CFLAGS_IRIX_OPTION 38 | dnl 39 | dnl @, tested, experimental 40 | dnl @version $Id: ax_cflags_gcc_option.m4,v 1.5 2003/11/29 08:13:25 guidod Exp $ 41 | dnl @author Guido Draheim 42 | dnl 43 | AC_DEFUN([AX_CFLAGS_GCC_OPTION_OLD], [dnl 44 | AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl 45 | AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$2])dnl 46 | AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)], 47 | VAR,[VAR="no, unknown" 48 | AC_LANG_SAVE 49 | AC_LANG_C 50 | ac_save_[]FLAGS="$[]FLAGS" 51 | for ac_arg dnl 52 | in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC 53 | # 54 | do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` 55 | AC_TRY_COMPILE([],[return 0;], 56 | [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) 57 | done 58 | FLAGS="$ac_save_[]FLAGS" 59 | AC_LANG_RESTORE 60 | ]) 61 | case ".$VAR" in 62 | .ok|.ok,*) m4_ifvaln($3,$3) ;; 63 | .|.no|.no,*) m4_ifvaln($4,$4) ;; 64 | *) m4_ifvaln($3,$3,[ 65 | if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null 66 | then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR]) 67 | else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"]) 68 | m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR" 69 | fi ]) ;; 70 | esac 71 | AS_VAR_POPDEF([VAR])dnl 72 | AS_VAR_POPDEF([FLAGS])dnl 73 | ]) 74 | 75 | 76 | dnl the only difference - the LANG selection... and the default FLAGS 77 | 78 | AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_OLD], [dnl 79 | AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl 80 | AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$2])dnl 81 | AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for gcc m4_ifval($2,$2,-option)], 82 | VAR,[VAR="no, unknown" 83 | AC_LANG_SAVE 84 | AC_LANG_CXX 85 | ac_save_[]FLAGS="$[]FLAGS" 86 | for ac_arg dnl 87 | in "-pedantic % m4_ifval($2,$2,-option)" dnl GCC 88 | # 89 | do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` 90 | AC_TRY_COMPILE([],[return 0;], 91 | [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) 92 | done 93 | FLAGS="$ac_save_[]FLAGS" 94 | AC_LANG_RESTORE 95 | ]) 96 | case ".$VAR" in 97 | .ok|.ok,*) m4_ifvaln($3,$3) ;; 98 | .|.no|.no,*) m4_ifvaln($4,$4) ;; 99 | *) m4_ifvaln($3,$3,[ 100 | if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null 101 | then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR]) 102 | else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"]) 103 | m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR" 104 | fi ]) ;; 105 | esac 106 | AS_VAR_POPDEF([VAR])dnl 107 | AS_VAR_POPDEF([FLAGS])dnl 108 | ]) 109 | 110 | dnl ------------------------------------------------------------------------- 111 | 112 | AC_DEFUN([AX_CFLAGS_GCC_OPTION_NEW], [dnl 113 | AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl 114 | AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_gcc_option_$1])dnl 115 | AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)], 116 | VAR,[VAR="no, unknown" 117 | AC_LANG_SAVE 118 | AC_LANG_C 119 | ac_save_[]FLAGS="$[]FLAGS" 120 | for ac_arg dnl 121 | in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC 122 | # 123 | do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` 124 | AC_TRY_COMPILE([],[return 0;], 125 | [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) 126 | done 127 | FLAGS="$ac_save_[]FLAGS" 128 | AC_LANG_RESTORE 129 | ]) 130 | case ".$VAR" in 131 | .ok|.ok,*) m4_ifvaln($3,$3) ;; 132 | .|.no|.no,*) m4_ifvaln($4,$4) ;; 133 | *) m4_ifvaln($3,$3,[ 134 | if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null 135 | then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR]) 136 | else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"]) 137 | m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR" 138 | fi ]) ;; 139 | esac 140 | AS_VAR_POPDEF([VAR])dnl 141 | AS_VAR_POPDEF([FLAGS])dnl 142 | ]) 143 | 144 | 145 | dnl the only difference - the LANG selection... and the default FLAGS 146 | 147 | AC_DEFUN([AX_CXXFLAGS_GCC_OPTION_NEW], [dnl 148 | AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl 149 | AS_VAR_PUSHDEF([VAR],[ac_cv_cxxflags_gcc_option_$1])dnl 150 | AC_CACHE_CHECK([m4_ifval($2,$2,FLAGS) for gcc m4_ifval($1,$1,-option)], 151 | VAR,[VAR="no, unknown" 152 | AC_LANG_SAVE 153 | AC_LANG_CXX 154 | ac_save_[]FLAGS="$[]FLAGS" 155 | for ac_arg dnl 156 | in "-pedantic % m4_ifval($1,$1,-option)" dnl GCC 157 | # 158 | do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'` 159 | AC_TRY_COMPILE([],[return 0;], 160 | [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break]) 161 | done 162 | FLAGS="$ac_save_[]FLAGS" 163 | AC_LANG_RESTORE 164 | ]) 165 | case ".$VAR" in 166 | .ok|.ok,*) m4_ifvaln($3,$3) ;; 167 | .|.no|.no,*) m4_ifvaln($4,$4) ;; 168 | *) m4_ifvaln($3,$3,[ 169 | if echo " $[]m4_ifval($2,$2,FLAGS) " | grep " $VAR " 2>&1 >/dev/null 170 | then AC_RUN_LOG([: m4_ifval($2,$2,FLAGS) does contain $VAR]) 171 | else AC_RUN_LOG([: m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR"]) 172 | m4_ifval($2,$2,FLAGS)="$m4_ifval($2,$2,FLAGS) $VAR" 173 | fi ]) ;; 174 | esac 175 | AS_VAR_POPDEF([VAR])dnl 176 | AS_VAR_POPDEF([FLAGS])dnl 177 | ]) 178 | 179 | AC_DEFUN([AX_CFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1, 180 | [AX_CFLAGS_GCC_OPTION_NEW($@)],[AX_CFLAGS_GCC_OPTION_OLD($@)])]) 181 | 182 | AC_DEFUN([AX_CXXFLAGS_GCC_OPTION],[ifelse(m4_bregexp([$2],[-]),-1, 183 | [AX_CXXFLAGS_GCC_OPTION_NEW($@)],[AX_CXXFLAGS_GCC_OPTION_OLD($@)])]) 184 | -------------------------------------------------------------------------------- /m4/ax_compare_version.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_compare_version.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro compares two version strings. Due to the various number of 12 | # minor-version numbers that can exist, and the fact that string 13 | # comparisons are not compatible with numeric comparisons, this is not 14 | # necessarily trivial to do in a autoconf script. This macro makes doing 15 | # these comparisons easy. 16 | # 17 | # The six basic comparisons are available, as well as checking equality 18 | # limited to a certain number of minor-version levels. 19 | # 20 | # The operator OP determines what type of comparison to do, and can be one 21 | # of: 22 | # 23 | # eq - equal (test A == B) 24 | # ne - not equal (test A != B) 25 | # le - less than or equal (test A <= B) 26 | # ge - greater than or equal (test A >= B) 27 | # lt - less than (test A < B) 28 | # gt - greater than (test A > B) 29 | # 30 | # Additionally, the eq and ne operator can have a number after it to limit 31 | # the test to that number of minor versions. 32 | # 33 | # eq0 - equal up to the length of the shorter version 34 | # ne0 - not equal up to the length of the shorter version 35 | # eqN - equal up to N sub-version levels 36 | # neN - not equal up to N sub-version levels 37 | # 38 | # When the condition is true, shell commands ACTION-IF-TRUE are run, 39 | # otherwise shell commands ACTION-IF-FALSE are run. The environment 40 | # variable 'ax_compare_version' is always set to either 'true' or 'false' 41 | # as well. 42 | # 43 | # Examples: 44 | # 45 | # AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) 46 | # AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) 47 | # 48 | # would both be true. 49 | # 50 | # AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) 51 | # AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) 52 | # 53 | # would both be false. 54 | # 55 | # AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) 56 | # 57 | # would be true because it is only comparing two minor versions. 58 | # 59 | # AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) 60 | # 61 | # would be true because it is only comparing the lesser number of minor 62 | # versions of the two values. 63 | # 64 | # Note: The characters that separate the version numbers do not matter. An 65 | # empty string is the same as version 0. OP is evaluated by autoconf, not 66 | # configure, so must be a string, not a variable. 67 | # 68 | # The author would like to acknowledge Guido Draheim whose advice about 69 | # the m4_case and m4_ifvaln functions make this macro only include the 70 | # portions necessary to perform the specific comparison specified by the 71 | # OP argument in the final configure script. 72 | # 73 | # LICENSE 74 | # 75 | # Copyright (c) 2008 Tim Toolan 76 | # 77 | # Copying and distribution of this file, with or without modification, are 78 | # permitted in any medium without royalty provided the copyright notice 79 | # and this notice are preserved. This file is offered as-is, without any 80 | # warranty. 81 | 82 | #serial 11 83 | 84 | dnl ######################################################################### 85 | AC_DEFUN([AX_COMPARE_VERSION], [ 86 | AC_REQUIRE([AC_PROG_AWK]) 87 | 88 | # Used to indicate true or false condition 89 | ax_compare_version=false 90 | 91 | # Convert the two version strings to be compared into a format that 92 | # allows a simple string comparison. The end result is that a version 93 | # string of the form 1.12.5-r617 will be converted to the form 94 | # 0001001200050617. In other words, each number is zero padded to four 95 | # digits, and non digits are removed. 96 | AS_VAR_PUSHDEF([A],[ax_compare_version_A]) 97 | A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 98 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 99 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 100 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 101 | -e 's/[[^0-9]]//g'` 102 | 103 | AS_VAR_PUSHDEF([B],[ax_compare_version_B]) 104 | B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ 105 | -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ 106 | -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 107 | -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ 108 | -e 's/[[^0-9]]//g'` 109 | 110 | dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary 111 | dnl # then the first line is used to determine if the condition is true. 112 | dnl # The sed right after the echo is to remove any indented white space. 113 | m4_case(m4_tolower($2), 114 | [lt],[ 115 | ax_compare_version=`echo "x$A 116 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` 117 | ], 118 | [gt],[ 119 | ax_compare_version=`echo "x$A 120 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` 121 | ], 122 | [le],[ 123 | ax_compare_version=`echo "x$A 124 | x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` 125 | ], 126 | [ge],[ 127 | ax_compare_version=`echo "x$A 128 | x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` 129 | ],[ 130 | dnl Split the operator from the subversion count if present. 131 | m4_bmatch(m4_substr($2,2), 132 | [0],[ 133 | # A count of zero means use the length of the shorter version. 134 | # Determine the number of characters in A and B. 135 | ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'` 136 | ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'` 137 | 138 | # Set A to no more than B's length and B to no more than A's length. 139 | A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` 140 | B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` 141 | ], 142 | [[0-9]+],[ 143 | # A count greater than zero means use only that many subversions 144 | A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 145 | B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` 146 | ], 147 | [.+],[ 148 | AC_WARNING( 149 | [illegal OP numeric parameter: $2]) 150 | ],[]) 151 | 152 | # Pad zeros at end of numbers to make same length. 153 | ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" 154 | B="$B`echo $A | sed 's/./0/g'`" 155 | A="$ax_compare_version_tmp_A" 156 | 157 | # Check for equality or inequality as necessary. 158 | m4_case(m4_tolower(m4_substr($2,0,2)), 159 | [eq],[ 160 | test "x$A" = "x$B" && ax_compare_version=true 161 | ], 162 | [ne],[ 163 | test "x$A" != "x$B" && ax_compare_version=true 164 | ],[ 165 | AC_WARNING([illegal OP parameter: $2]) 166 | ]) 167 | ]) 168 | 169 | AS_VAR_POPDEF([A])dnl 170 | AS_VAR_POPDEF([B])dnl 171 | 172 | dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. 173 | if test "$ax_compare_version" = "true" ; then 174 | m4_ifvaln([$4],[$4],[:])dnl 175 | m4_ifvaln([$5],[else $5])dnl 176 | fi 177 | ]) dnl AX_COMPARE_VERSION 178 | -------------------------------------------------------------------------------- /m4/ax_gcc_func_attribute.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_gcc_func_attribute.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_GCC_FUNC_ATTRIBUTE(ATTRIBUTE) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro checks if the compiler supports one of GCC's function 12 | # attributes; many other compilers also provide function attributes with 13 | # the same syntax. Compiler warnings are used to detect supported 14 | # attributes as unsupported ones are ignored by default so quieting 15 | # warnings when using this macro will yield false positives. 16 | # 17 | # The ATTRIBUTE parameter holds the name of the attribute to be checked. 18 | # 19 | # If ATTRIBUTE is supported define HAVE_FUNC_ATTRIBUTE_. 20 | # 21 | # The macro caches its result in the ax_cv_have_func_attribute_ 22 | # variable. 23 | # 24 | # The macro currently supports the following function attributes: 25 | # 26 | # alias 27 | # aligned 28 | # alloc_size 29 | # always_inline 30 | # artificial 31 | # cold 32 | # const 33 | # constructor 34 | # deprecated 35 | # destructor 36 | # dllexport 37 | # dllimport 38 | # error 39 | # externally_visible 40 | # flatten 41 | # format 42 | # format_arg 43 | # gnu_inline 44 | # hot 45 | # ifunc 46 | # leaf 47 | # malloc 48 | # noclone 49 | # noinline 50 | # nonnull 51 | # noreturn 52 | # nothrow 53 | # optimize 54 | # pure 55 | # unused 56 | # used 57 | # visibility 58 | # warning 59 | # warn_unused_result 60 | # weak 61 | # weakref 62 | # 63 | # Unsuppored function attributes will be tested with a prototype returning 64 | # an int and not accepting any arguments and the result of the check might 65 | # be wrong or meaningless so use with care. 66 | # 67 | # LICENSE 68 | # 69 | # Copyright (c) 2013 Gabriele Svelto 70 | # 71 | # Copying and distribution of this file, with or without modification, are 72 | # permitted in any medium without royalty provided the copyright notice 73 | # and this notice are preserved. This file is offered as-is, without any 74 | # warranty. 75 | 76 | #serial 2 77 | 78 | AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [ 79 | AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1]) 80 | 81 | AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [ 82 | AC_LINK_IFELSE([AC_LANG_PROGRAM([ 83 | m4_case([$1], 84 | [alias], [ 85 | int foo( void ) { return 0; } 86 | int bar( void ) __attribute__(($1("foo"))); 87 | ], 88 | [aligned], [ 89 | int foo( void ) __attribute__(($1(32))); 90 | ], 91 | [alloc_size], [ 92 | void *foo(int a) __attribute__(($1(1))); 93 | ], 94 | [always_inline], [ 95 | inline __attribute__(($1)) int foo( void ) { return 0; } 96 | ], 97 | [artificial], [ 98 | inline __attribute__(($1)) int foo( void ) { return 0; } 99 | ], 100 | [cold], [ 101 | int foo( void ) __attribute__(($1)); 102 | ], 103 | [const], [ 104 | int foo( void ) __attribute__(($1)); 105 | ], 106 | [constructor], [ 107 | int foo( void ) __attribute__(($1)); 108 | ], 109 | [deprecated], [ 110 | int foo( void ) __attribute__(($1(""))); 111 | ], 112 | [destructor], [ 113 | int foo( void ) __attribute__(($1)); 114 | ], 115 | [dllexport], [ 116 | __attribute__(($1)) int foo( void ) { return 0; } 117 | ], 118 | [dllimport], [ 119 | int foo( void ) __attribute__(($1)); 120 | ], 121 | [error], [ 122 | int foo( void ) __attribute__(($1(""))); 123 | ], 124 | [externally_visible], [ 125 | int foo( void ) __attribute__(($1)); 126 | ], 127 | [flatten], [ 128 | int foo( void ) __attribute__(($1)); 129 | ], 130 | [format], [ 131 | int foo(const char *p, ...) __attribute__(($1(printf, 1, 2))); 132 | ], 133 | [format_arg], [ 134 | char *foo(const char *p) __attribute__(($1(1))); 135 | ], 136 | [gnu_inline], [ 137 | inline __attribute__(($1)) int foo( void ) { return 0; } 138 | ], 139 | [hot], [ 140 | int foo( void ) __attribute__(($1)); 141 | ], 142 | [ifunc], [ 143 | int my_foo( void ) { return 0; } 144 | static int (*resolve_foo(void))(void) { return my_foo; } 145 | int foo( void ) __attribute__(($1("resolve_foo"))); 146 | ], 147 | [leaf], [ 148 | __attribute__(($1)) int foo( void ) { return 0; } 149 | ], 150 | [malloc], [ 151 | void *foo( void ) __attribute__(($1)); 152 | ], 153 | [noclone], [ 154 | int foo( void ) __attribute__(($1)); 155 | ], 156 | [noinline], [ 157 | __attribute__(($1)) int foo( void ) { return 0; } 158 | ], 159 | [nonnull], [ 160 | int foo(char *p) __attribute__(($1(1))); 161 | ], 162 | [noreturn], [ 163 | void foo( void ) __attribute__(($1)); 164 | ], 165 | [nothrow], [ 166 | int foo( void ) __attribute__(($1)); 167 | ], 168 | [optimize], [ 169 | __attribute__(($1(3))) int foo( void ) { return 0; } 170 | ], 171 | [pure], [ 172 | int foo( void ) __attribute__(($1)); 173 | ], 174 | [unused], [ 175 | int foo( void ) __attribute__(($1)); 176 | ], 177 | [used], [ 178 | int foo( void ) __attribute__(($1)); 179 | ], 180 | [visibility], [ 181 | int foo_def( void ) __attribute__(($1("default"))); 182 | int foo_hid( void ) __attribute__(($1("hidden"))); 183 | int foo_int( void ) __attribute__(($1("internal"))); 184 | int foo_pro( void ) __attribute__(($1("protected"))); 185 | ], 186 | [warning], [ 187 | int foo( void ) __attribute__(($1(""))); 188 | ], 189 | [warn_unused_result], [ 190 | int foo( void ) __attribute__(($1)); 191 | ], 192 | [weak], [ 193 | int foo( void ) __attribute__(($1)); 194 | ], 195 | [weakref], [ 196 | static int foo( void ) { return 0; } 197 | static int bar( void ) __attribute__(($1("foo"))); 198 | ], 199 | [ 200 | m4_warn([syntax], [Unsupported attribute $1, the test may fail]) 201 | int foo( void ) __attribute__(($1)); 202 | ] 203 | )], []) 204 | ], 205 | dnl GCC doesn't exit with an error if an unknown attribute is 206 | dnl provided but only outputs a warning, so accept the attribute 207 | dnl only if no warning were issued. 208 | [AS_IF([test -s conftest.err], 209 | [AS_VAR_SET([ac_var], [no])], 210 | [AS_VAR_SET([ac_var], [yes])])], 211 | [AS_VAR_SET([ac_var], [no])]) 212 | ]) 213 | 214 | AS_IF([test yes = AS_VAR_GET([ac_var])], 215 | [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FUNC_ATTRIBUTE_$1), 1, 216 | [Define to 1 if the system has the `$1' function attribute])], []) 217 | 218 | AS_VAR_POPDEF([ac_var]) 219 | ]) 220 | -------------------------------------------------------------------------------- /m4/ax_gcc_var_attribute.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_gcc_var_attribute.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_GCC_VAR_ATTRIBUTE(ATTRIBUTE) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro checks if the compiler supports one of GCC's variable 12 | # attributes; many other compilers also provide variable attributes with 13 | # the same syntax. Compiler warnings are used to detect supported 14 | # attributes as unsupported ones are ignored by default so quieting 15 | # warnings when using this macro will yield false positives. 16 | # 17 | # The ATTRIBUTE parameter holds the name of the attribute to be checked. 18 | # 19 | # If ATTRIBUTE is supported define HAVE_VAR_ATTRIBUTE_. 20 | # 21 | # The macro caches its result in the ax_cv_have_var_attribute_ 22 | # variable. 23 | # 24 | # The macro currently supports the following variable attributes: 25 | # 26 | # aligned 27 | # cleanup 28 | # common 29 | # nocommon 30 | # deprecated 31 | # mode 32 | # packed 33 | # tls_model 34 | # unused 35 | # used 36 | # vector_size 37 | # weak 38 | # dllimport 39 | # dllexport 40 | # 41 | # Unsuppored variable attributes will be tested against a global integer 42 | # variable and without any arguments given to the attribute itself; the 43 | # result of this check might be wrong or meaningless so use with care. 44 | # 45 | # LICENSE 46 | # 47 | # Copyright (c) 2013 Gabriele Svelto 48 | # 49 | # Copying and distribution of this file, with or without modification, are 50 | # permitted in any medium without royalty provided the copyright notice 51 | # and this notice are preserved. This file is offered as-is, without any 52 | # warranty. 53 | 54 | #serial 2 55 | 56 | AC_DEFUN([AX_GCC_VAR_ATTRIBUTE], [ 57 | AS_VAR_PUSHDEF([ac_var], [ax_cv_have_var_attribute_$1]) 58 | 59 | AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [ 60 | AC_LINK_IFELSE([AC_LANG_PROGRAM([ 61 | m4_case([$1], 62 | [aligned], [ 63 | int foo __attribute__(($1(32))); 64 | ], 65 | [cleanup], [ 66 | int bar(int *t) { return *t; }; 67 | ], 68 | [common], [ 69 | int foo __attribute__(($1)); 70 | ], 71 | [nocommon], [ 72 | int foo __attribute__(($1)); 73 | ], 74 | [deprecated], [ 75 | int foo __attribute__(($1)) = 0; 76 | ], 77 | [mode], [ 78 | long foo __attribute__(($1(word))); 79 | ], 80 | [packed], [ 81 | struct bar { 82 | int baz __attribute__(($1)); 83 | }; 84 | ], 85 | [tls_model], [ 86 | __thread int bar1 __attribute__(($1("global-dynamic"))); 87 | __thread int bar2 __attribute__(($1("local-dynamic"))); 88 | __thread int bar3 __attribute__(($1("initial-exec"))); 89 | __thread int bar4 __attribute__(($1("local-exec"))); 90 | ], 91 | [unused], [ 92 | int foo __attribute__(($1)); 93 | ], 94 | [used], [ 95 | int foo __attribute__(($1)); 96 | ], 97 | [vector_size], [ 98 | int foo __attribute__(($1(16))); 99 | ], 100 | [weak], [ 101 | int foo __attribute__(($1)); 102 | ], 103 | [dllimport], [ 104 | int foo __attribute__(($1)); 105 | ], 106 | [dllexport], [ 107 | int foo __attribute__(($1)); 108 | ], 109 | [ 110 | m4_warn([syntax], [Unsupported attribute $1, the test may fail]) 111 | int foo __attribute__(($1)); 112 | ] 113 | )], [ 114 | m4_case([$1], 115 | [cleanup], [ 116 | int foo __attribute__(($1(bar))) = 0; 117 | foo = foo + 1; 118 | ], 119 | [] 120 | )]) 121 | ], 122 | dnl GCC doesn't exit with an error if an unknown attribute is 123 | dnl provided but only outputs a warning, so accept the attribute 124 | dnl only if no warning were issued. 125 | [AS_IF([test -s conftest.err], 126 | [AS_VAR_SET([ac_var], [no])], 127 | [AS_VAR_SET([ac_var], [yes])])], 128 | [AS_VAR_SET([ac_var], [no])]) 129 | ]) 130 | 131 | AS_IF([test yes = AS_VAR_GET([ac_var])], 132 | [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_VAR_ATTRIBUTE_$1), 1, 133 | [Define to 1 if the system has the `$1' variable attribute])], []) 134 | 135 | AS_VAR_POPDEF([ac_var]) 136 | ]) 137 | -------------------------------------------------------------------------------- /m4/ax_require_defined.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_require_defined.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_REQUIRE_DEFINED(MACRO) 8 | # 9 | # DESCRIPTION 10 | # 11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have 12 | # been defined and thus are available for use. This avoids random issues 13 | # where a macro isn't expanded. Instead the configure script emits a 14 | # non-fatal: 15 | # 16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found 17 | # 18 | # It's like AC_REQUIRE except it doesn't expand the required macro. 19 | # 20 | # Here's an example: 21 | # 22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2014 Mike Frysinger 27 | # 28 | # Copying and distribution of this file, with or without modification, are 29 | # permitted in any medium without royalty provided the copyright notice 30 | # and this notice are preserved. This file is offered as-is, without any 31 | # warranty. 32 | 33 | #serial 1 34 | 35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl 36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) 37 | ])dnl AX_REQUIRE_DEFINED 38 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /* -*- buffer-read-only: t -*- vi: set ro: */ 2 | /* DO NOT EDIT! GENERATED AUTOMATICALLY! */ 3 | /* Declaration of functions and data types used for MD5 sum computing 4 | library functions. 5 | Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2010 Free Software 6 | Foundation, Inc. 7 | This file is part of the GNU C Library. 8 | 9 | This program is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by the 11 | Free Software Foundation; either version 3, or (at your option) any 12 | later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software Foundation, 21 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 | 23 | #ifndef _MD5_H 24 | #define _MD5_H 1 25 | 26 | #include 27 | #include 28 | 29 | #define MD5_DIGEST_SIZE 16 30 | #define MD5_BLOCK_SIZE 64 31 | 32 | #ifndef __GNUC_PREREQ 33 | # if defined __GNUC__ && defined __GNUC_MINOR__ 34 | # define __GNUC_PREREQ(maj, min) \ 35 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) 36 | # else 37 | # define __GNUC_PREREQ(maj, min) 0 38 | # endif 39 | #endif 40 | 41 | #ifndef __THROW 42 | # if defined __cplusplus && __GNUC_PREREQ (2,8) 43 | # define __THROW throw () 44 | # else 45 | # define __THROW 46 | # endif 47 | #endif 48 | 49 | #ifndef _LIBC 50 | # define __md5_buffer md5_buffer 51 | # define __md5_finish_ctx md5_finish_ctx 52 | # define __md5_init_ctx md5_init_ctx 53 | # define __md5_process_block md5_process_block 54 | # define __md5_process_bytes md5_process_bytes 55 | # define __md5_read_ctx md5_read_ctx 56 | # define __md5_stream md5_stream 57 | #endif 58 | 59 | # ifdef __cplusplus 60 | extern "C" { 61 | # endif 62 | 63 | /* Structure to save state of computation between the single steps. */ 64 | struct md5_ctx 65 | { 66 | uint32_t A; 67 | uint32_t B; 68 | uint32_t C; 69 | uint32_t D; 70 | 71 | uint32_t total[2]; 72 | uint32_t buflen; 73 | uint32_t buffer[32]; 74 | }; 75 | 76 | /* 77 | * The following three functions are build up the low level used in 78 | * the functions `md5_stream' and `md5_buffer'. 79 | */ 80 | 81 | /* Initialize structure containing state of computation. 82 | (RFC 1321, 3.3: Step 3) */ 83 | extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; 84 | 85 | /* Starting with the result of former calls of this function (or the 86 | initialization function update the context for the next LEN bytes 87 | starting at BUFFER. 88 | It is necessary that LEN is a multiple of 64!!! */ 89 | extern void __md5_process_block (const void *buffer, size_t len, 90 | struct md5_ctx *ctx) __THROW; 91 | 92 | /* Starting with the result of former calls of this function (or the 93 | initialization function update the context for the next LEN bytes 94 | starting at BUFFER. 95 | It is NOT required that LEN is a multiple of 64. */ 96 | extern void __md5_process_bytes (const void *buffer, size_t len, 97 | struct md5_ctx *ctx) __THROW; 98 | 99 | /* Process the remaining bytes in the buffer and put result from CTX 100 | in first 16 bytes following RESBUF. The result is always in little 101 | endian byte order, so that a byte-wise output yields to the wanted 102 | ASCII representation of the message digest. */ 103 | extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; 104 | 105 | 106 | /* Put result from CTX in first 16 bytes following RESBUF. The result is 107 | always in little endian byte order, so that a byte-wise output yields 108 | to the wanted ASCII representation of the message digest. */ 109 | extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; 110 | 111 | 112 | /* Compute MD5 message digest for bytes read from STREAM. The 113 | resulting message digest number will be written into the 16 bytes 114 | beginning at RESBLOCK. */ 115 | extern int __md5_stream (FILE *stream, void *resblock) __THROW; 116 | 117 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The 118 | result is always in little endian byte order, so that a byte-wise 119 | output yields to the wanted ASCII representation of the message 120 | digest. */ 121 | extern void *__md5_buffer (const char *buffer, size_t len, 122 | void *resblock) __THROW; 123 | 124 | # ifdef __cplusplus 125 | } 126 | # endif 127 | 128 | #endif /* md5.h */ 129 | -------------------------------------------------------------------------------- /menu.h: -------------------------------------------------------------------------------- 1 | #ifndef MENU_H 2 | #define MENU_H 3 | 4 | #if defined HAVE_NCURSESW_CURSES_H 5 | # include 6 | #elif defined HAVE_NCURSESW_H 7 | # include 8 | #elif defined HAVE_NCURSES_CURSES_H 9 | # include 10 | #elif defined HAVE_NCURSES_H 11 | # include 12 | #elif defined HAVE_CURSES_H 13 | # include 14 | #endif 15 | 16 | #include "files.h" 17 | #include "rbtree.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | enum menu_request 24 | { 25 | REQ_UP, 26 | REQ_DOWN, 27 | REQ_PGUP, 28 | REQ_PGDOWN, 29 | REQ_TOP, 30 | REQ_BOTTOM 31 | }; 32 | 33 | enum menu_align 34 | { 35 | MENU_ALIGN_RIGHT, 36 | MENU_ALIGN_LEFT 37 | }; 38 | 39 | #define FILE_TIME_STR_SZ 6 40 | #define FILE_FORMAT_SZ 4 41 | 42 | struct menu_item 43 | { 44 | char *title; /* Title of the item */ 45 | enum menu_align align; /* Align of the title */ 46 | int num; /* Position of the item starting from 0. */ 47 | 48 | /* Curses attributes in different states: */ 49 | int attr_normal; 50 | int attr_sel; 51 | int attr_marked; 52 | int attr_sel_marked; 53 | 54 | /* Associated file: */ 55 | char *file; 56 | enum file_type type; 57 | 58 | /* Additional information shown: */ 59 | char time[FILE_TIME_STR_SZ]; /* File time string */ 60 | char format[FILE_FORMAT_SZ]; /* File format */ 61 | int queue_pos; /* Position in the queue */ 62 | 63 | struct menu_item *next; 64 | struct menu_item *prev; 65 | }; 66 | 67 | struct menu 68 | { 69 | WINDOW *win; 70 | struct menu_item *items; 71 | int nitems; /* number of present items */ 72 | struct menu_item *top; /* first visible item */ 73 | struct menu_item *last; /* last item in the menu */ 74 | 75 | /* position and size */ 76 | int posx; 77 | int posy; 78 | int width; 79 | int height; 80 | 81 | struct menu_item *selected; /* selected item */ 82 | struct menu_item *marked; /* index of the marked item or -1 */ 83 | 84 | /* Flags for displaying information about the file. */ 85 | int show_time; 86 | bool show_format; 87 | 88 | int info_attr_normal; /* attributes for information about the file */ 89 | int info_attr_sel; 90 | int info_attr_marked; 91 | int info_attr_sel_marked; 92 | int number_items; /* display item number (position) */ 93 | 94 | struct rb_tree *search_tree; /* RB tree for searching by file name */ 95 | }; 96 | 97 | /* Menu state: relative (to the first item) positions of the top and selected 98 | * items. */ 99 | struct menu_state 100 | { 101 | int top_item; 102 | int selected_item; 103 | }; 104 | 105 | struct menu *menu_new (WINDOW *win, const int posx, const int posy, 106 | const int width, const int height); 107 | struct menu_item *menu_add (struct menu *menu, const char *title, 108 | const enum file_type type, const char *file); 109 | 110 | void menu_item_set_attr_normal (struct menu_item *mi, const int attr); 111 | void menu_item_set_attr_sel (struct menu_item *mi, const int attr); 112 | void menu_item_set_attr_sel_marked (struct menu_item *mi, const int attr); 113 | void menu_item_set_attr_marked (struct menu_item *mi, const int attr); 114 | 115 | void menu_item_set_time (struct menu_item *mi, const char *time); 116 | void menu_item_set_format (struct menu_item *mi, const char *format); 117 | void menu_item_set_queue_pos (struct menu_item *mi, const int pos); 118 | 119 | void menu_free (struct menu *menu); 120 | void menu_driver (struct menu *menu, const enum menu_request req); 121 | void menu_setcurritem_title (struct menu *menu, const char *title); 122 | void menu_setcurritem_file (struct menu *menu, const char *file); 123 | void menu_draw (const struct menu *menu, const int active); 124 | void menu_mark_item (struct menu *menu, const char *file); 125 | void menu_set_state (struct menu *menu, const struct menu_state *st); 126 | void menu_get_state (const struct menu *menu, struct menu_state *st); 127 | void menu_update_size (struct menu *menu, const int posx, const int posy, 128 | const int width, const int height); 129 | void menu_unmark_item (struct menu *menu); 130 | struct menu *menu_filter_pattern (const struct menu *menu, const char *pattern); 131 | void menu_set_show_time (struct menu *menu, const int t); 132 | void menu_set_show_format (struct menu *menu, const bool t); 133 | void menu_set_info_attr_normal (struct menu *menu, const int attr); 134 | void menu_set_info_attr_sel (struct menu *menu, const int attr); 135 | void menu_set_info_attr_marked (struct menu *menu, const int attr); 136 | void menu_set_info_attr_sel_marked (struct menu *menu, const int attr); 137 | void menu_set_items_numbering (struct menu *menu, const int number); 138 | enum file_type menu_item_get_type (const struct menu_item *mi); 139 | char *menu_item_get_file (const struct menu_item *mi); 140 | struct menu_item *menu_curritem (struct menu *menu); 141 | void menu_item_set_title (struct menu_item *mi, const char *title); 142 | int menu_nitems (const struct menu *menu); 143 | struct menu_item *menu_find (struct menu *menu, const char *fname); 144 | void menu_del_item (struct menu *menu, const char *fname); 145 | void menu_item_set_align (struct menu_item *mi, const enum menu_align align); 146 | int menu_is_visible (const struct menu *menu, const struct menu_item *mi); 147 | void menu_swap_items (struct menu *menu, const char *file1, const char *file2); 148 | void menu_make_visible (struct menu *menu, const char *file); 149 | void menu_set_cursor (const struct menu *m); 150 | 151 | #ifdef __cplusplus 152 | } 153 | #endif 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /null_out.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2004 Damian Pietras 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | */ 11 | 12 | /* Fake output device - only for testing. */ 13 | 14 | #ifdef HAVE_CONFIG_H 15 | # include "config.h" 16 | #endif 17 | 18 | #include 19 | 20 | #include "common.h" 21 | #include "audio.h" 22 | 23 | static struct sound_params params = { 0, 0, 0 }; 24 | 25 | static int null_open (struct sound_params *sound_params) 26 | { 27 | params = *sound_params; 28 | return 1; 29 | } 30 | 31 | static void null_close () 32 | { 33 | params.rate = 0; 34 | } 35 | 36 | static int null_play (const char *unused ATTR_UNUSED, const size_t size) 37 | { 38 | xsleep (size, audio_get_bps ()); 39 | return size; 40 | } 41 | 42 | static int null_read_mixer () 43 | { 44 | return 100; 45 | } 46 | 47 | static void null_set_mixer (int unused ATTR_UNUSED) 48 | { 49 | } 50 | 51 | static int null_get_buff_fill () 52 | { 53 | return 0; 54 | } 55 | 56 | static int null_reset () 57 | { 58 | return 1; 59 | } 60 | 61 | static int null_init (struct output_driver_caps *caps) 62 | { 63 | caps->formats = SFMT_S8 | SFMT_S16 | SFMT_LE; 64 | caps->min_channels = 1; 65 | caps->max_channels = 2; 66 | 67 | return 1; 68 | } 69 | 70 | static int null_get_rate () 71 | { 72 | return params.rate; 73 | } 74 | 75 | static void null_toggle_mixer_channel () 76 | { 77 | } 78 | 79 | static char *null_get_mixer_channel_name () 80 | { 81 | return xstrdup ("FakeMixer"); 82 | } 83 | 84 | void null_funcs (struct hw_funcs *funcs) 85 | { 86 | funcs->init = null_init; 87 | funcs->open = null_open; 88 | funcs->close = null_close; 89 | funcs->play = null_play; 90 | funcs->read_mixer = null_read_mixer; 91 | funcs->set_mixer = null_set_mixer; 92 | funcs->get_buff_fill = null_get_buff_fill; 93 | funcs->reset = null_reset; 94 | funcs->get_rate = null_get_rate; 95 | funcs->toggle_mixer_channel = null_toggle_mixer_channel; 96 | funcs->get_mixer_channel_name = null_get_mixer_channel_name; 97 | } 98 | -------------------------------------------------------------------------------- /null_out.h: -------------------------------------------------------------------------------- 1 | #ifndef NULL_OUT_H 2 | #define NULL_OUT_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void null_funcs (struct hw_funcs *funcs); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /options.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIONS_H 2 | #define OPTIONS_H 3 | 4 | #include "lists.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | enum option_type 11 | { 12 | OPTION_FREE = 0, 13 | OPTION_INT = 1, 14 | OPTION_BOOL = 2, 15 | OPTION_STR = 4, 16 | OPTION_SYMB = 8, 17 | OPTION_LIST = 16, 18 | OPTION_ANY = 255 19 | }; 20 | 21 | int options_get_int (const char *name); 22 | bool options_get_bool (const char *name); 23 | char *options_get_str (const char *name); 24 | char *options_get_symb (const char *name); 25 | lists_t_strs *options_get_list (const char *name); 26 | void options_set_int (const char *name, const int value); 27 | void options_set_bool (const char *name, const bool value); 28 | void options_set_str (const char *name, const char *value); 29 | void options_set_symb (const char *name, const char *value); 30 | void options_set_list (const char *name, const char *value, bool append); 31 | bool options_set_pair (const char *name, const char *value, bool append); 32 | void options_init (); 33 | void options_parse (const char *config_file); 34 | void options_free (); 35 | void options_ignore_config (const char *name); 36 | int options_check_str (const char *name, const char *val); 37 | int options_check_symb (const char *name, const char *val); 38 | int options_check_int (const char *name, const int val); 39 | int options_check_bool (const char *name, const bool val); 40 | int options_check_list (const char *name, const char *val); 41 | int options_was_defaulted (const char *name); 42 | enum option_type options_get_type (const char *name); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /oss.h: -------------------------------------------------------------------------------- 1 | #ifndef OSS_H 2 | #define OSS_H 3 | 4 | #include "audio.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void oss_funcs (struct hw_funcs *funcs); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /out_buf.h: -------------------------------------------------------------------------------- 1 | #ifndef BUF_H 2 | #define BUF_H 3 | 4 | #include "fifo_buf.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef void out_buf_free_callback (); 11 | 12 | struct out_buf; 13 | 14 | struct out_buf *out_buf_new (int size); 15 | void out_buf_free (struct out_buf *buf); 16 | int out_buf_put (struct out_buf *buf, const char *data, int size); 17 | void out_buf_pause (struct out_buf *buf); 18 | void out_buf_unpause (struct out_buf *buf); 19 | void out_buf_stop (struct out_buf *buf); 20 | void out_buf_reset (struct out_buf *buf); 21 | void out_buf_time_set (struct out_buf *buf, const float time); 22 | int out_buf_time_get (struct out_buf *buf); 23 | void out_buf_set_free_callback (struct out_buf *buf, 24 | out_buf_free_callback callback); 25 | int out_buf_get_free (struct out_buf *buf); 26 | int out_buf_get_fill (struct out_buf *buf); 27 | void out_buf_wait (struct out_buf *buf); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /player.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYER_H 2 | #define PLAYER_H 3 | 4 | #include "out_buf.h" 5 | #include "io.h" 6 | #include "playlist.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | void player_cleanup (); 13 | void player (const char *file, const char *next_file, struct out_buf *out_buf); 14 | void player_stop (); 15 | void player_seek (const int n); 16 | void player_jump_to (const int n); 17 | void player_reset (); 18 | void player_init (); 19 | struct file_tags *player_get_curr_tags (); 20 | void player_pause (); 21 | void player_unpause (); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /playlist.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYLIST_H 2 | #define PLAYLIST_H 3 | 4 | #include 5 | 6 | #include "rbtree.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Flags for the info decoder function. */ 13 | enum tags_select 14 | { 15 | TAGS_COMMENTS = 0x01, /* artist, title, etc. */ 16 | TAGS_TIME = 0x02 /* time of the file. */ 17 | }; 18 | 19 | struct file_tags 20 | { 21 | char *title; 22 | char *artist; 23 | char *album; 24 | int track; 25 | int time; 26 | int filled; /* Which tags are filled: TAGS_COMMENTS, TAGS_TIME. */ 27 | }; 28 | 29 | enum file_type 30 | { 31 | F_DIR, 32 | F_SOUND, 33 | F_URL, 34 | F_PLAYLIST, 35 | F_THEME, 36 | F_OTHER 37 | }; 38 | 39 | struct plist_item 40 | { 41 | char *file; 42 | enum file_type type; /* type of the file (F_OTHER if not read yet) */ 43 | char *title_file; /* title based on the file name */ 44 | char *title_tags; /* title based on the tags */ 45 | struct file_tags *tags; 46 | short deleted; 47 | time_t mtime; /* modification time */ 48 | int queue_pos; /* position in the queue */ 49 | }; 50 | 51 | struct plist 52 | { 53 | int num; /* Number of elements on the list */ 54 | int allocated; /* Number of allocated elements */ 55 | int not_deleted; /* Number of non-deleted items */ 56 | struct plist_item *items; 57 | int serial; /* Optional serial number of this playlist */ 58 | int total_time; /* Total time for files on the playlist */ 59 | int items_with_time; /* Number of items for which the time is set. */ 60 | 61 | struct rb_tree *search_tree; 62 | }; 63 | 64 | void plist_init (struct plist *plist); 65 | int plist_add (struct plist *plist, const char *file_name); 66 | int plist_add_from_item (struct plist *plist, const struct plist_item *item); 67 | char *plist_get_file (const struct plist *plist, int i); 68 | int plist_next (struct plist *plist, int num); 69 | int plist_prev (struct plist *plist, int num); 70 | void plist_clear (struct plist *plist); 71 | void plist_delete (struct plist *plist, const int num); 72 | void plist_free (struct plist *plist); 73 | void plist_sort_fname (struct plist *plist); 74 | int plist_find_fname (struct plist *plist, const char *file); 75 | struct file_tags *tags_new (); 76 | void tags_clear (struct file_tags *tags); 77 | void tags_copy (struct file_tags *dst, const struct file_tags *src); 78 | struct file_tags *tags_dup (const struct file_tags *tags); 79 | void tags_free (struct file_tags *tags); 80 | char *build_title_with_format (const struct file_tags *tags, const char *fmt); 81 | char *build_title (const struct file_tags *tags); 82 | int plist_count (const struct plist *plist); 83 | void plist_set_title_tags (struct plist *plist, const int num, 84 | const char *title); 85 | void plist_set_title_file (struct plist *plist, const int num, 86 | const char *title); 87 | void plist_set_file (struct plist *plist, const int num, const char *file); 88 | int plist_deleted (const struct plist *plist, const int num); 89 | void plist_cat (struct plist *a, struct plist *b); 90 | void update_file (struct plist_item *item); 91 | void plist_set_item_time (struct plist *plist, const int num, const int time); 92 | int get_item_time (const struct plist *plist, const int i); 93 | int plist_total_time (const struct plist *plisti, int *all_files); 94 | void plist_shuffle (struct plist *plist); 95 | void plist_swap_first_fname (struct plist *plist, const char *fname); 96 | struct plist_item *plist_new_item (); 97 | void plist_free_item_fields (struct plist_item *item); 98 | void plist_set_serial (struct plist *plist, const int serial); 99 | int plist_get_serial (const struct plist *plist); 100 | int plist_last (const struct plist *plist); 101 | int plist_find_del_fname (const struct plist *plist, const char *file); 102 | const char *plist_get_next_dead_entry (const struct plist *plist, 103 | int *last_index); 104 | void plist_item_copy (struct plist_item *dst, const struct plist_item *src); 105 | enum file_type plist_file_type (const struct plist *plist, const int num); 106 | void plist_remove_common_items (struct plist *a, struct plist *b); 107 | void plist_discard_tags (struct plist *plist); 108 | void plist_set_tags (struct plist *plist, const int num, 109 | const struct file_tags *tags); 110 | struct file_tags *plist_get_tags (const struct plist *plist, const int num); 111 | void plist_swap_files (struct plist *plist, const char *file1, 112 | const char *file2); 113 | int plist_get_position (const struct plist *plist, int num); 114 | 115 | #ifdef __cplusplus 116 | } 117 | #endif 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /playlist_file.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYLIST_FILE_H 2 | #define PLAYLIST_FILE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int plist_load (struct plist *plist, const char *fname, const char *cwd, 9 | const int load_serial); 10 | int plist_save (struct plist *plist, const char *file, const int save_serial); 11 | int is_plist_file (const char *name); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /protocol.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOCOL_H 2 | #define PROTOCOL_H 3 | 4 | #include "playlist.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | struct event 11 | { 12 | int type; /* type of the event (one of EV_*) */ 13 | void *data; /* optional data associated with the event */ 14 | struct event *next; 15 | }; 16 | 17 | struct event_queue 18 | { 19 | struct event *head; 20 | struct event *tail; 21 | }; 22 | 23 | /* Used as data field in the event queue for EV_FILE_TAGS. */ 24 | struct tag_ev_response 25 | { 26 | char *file; 27 | struct file_tags *tags; 28 | }; 29 | 30 | /* Used as data field in the event queue for EV_PLIST_MOVE. */ 31 | struct move_ev_data 32 | { 33 | /* Two files that are to be exchanged. */ 34 | char *from; 35 | char *to; 36 | }; 37 | 38 | /* Status of nonblock sending/receiving function. */ 39 | enum noblock_io_status 40 | { 41 | NB_IO_OK, 42 | NB_IO_BLOCK, 43 | NB_IO_ERR 44 | }; 45 | 46 | /* Definition of events sent by server to the client. */ 47 | #define EV_STATE 0x01 /* server has changed the state */ 48 | #define EV_CTIME 0x02 /* current time of the song has changed */ 49 | #define EV_SRV_ERROR 0x04 /* an error occurred */ 50 | #define EV_BUSY 0x05 /* another client is connected to the server */ 51 | #define EV_DATA 0x06 /* data in response to a request will arrive */ 52 | #define EV_BITRATE 0x07 /* the bitrate has changed */ 53 | #define EV_RATE 0x08 /* the rate has changed */ 54 | #define EV_CHANNELS 0x09 /* the number of channels has changed */ 55 | #define EV_EXIT 0x0a /* the server is about to exit */ 56 | #define EV_PONG 0x0b /* response for CMD_PING */ 57 | #define EV_OPTIONS 0x0c /* the options has changed */ 58 | #define EV_SEND_PLIST 0x0d /* request for sending the playlist */ 59 | #define EV_TAGS 0x0e /* tags for the current file have changed */ 60 | #define EV_STATUS_MSG 0x0f /* followed by a status message */ 61 | #define EV_MIXER_CHANGE 0x10 /* the mixer channel was changed */ 62 | #define EV_FILE_TAGS 0x11 /* tags in a response for tags request */ 63 | #define EV_AVG_BITRATE 0x12 /* average bitrate has changed (new song) */ 64 | #define EV_AUDIO_START 0x13 /* playing of audio has started */ 65 | #define EV_AUDIO_STOP 0x14 /* playing of audio has stopped */ 66 | 67 | /* Events caused by a client that wants to modify the playlist (see 68 | * CMD_CLI_PLIST* commands). */ 69 | #define EV_PLIST_ADD 0x50 /* add an item, followed by the file name */ 70 | #define EV_PLIST_DEL 0x51 /* delete an item, followed by the file name */ 71 | #define EV_PLIST_MOVE 0x52 /* move an item, followed by 2 file names */ 72 | #define EV_PLIST_CLEAR 0x53 /* clear the playlist */ 73 | 74 | /* These events, though similar to the four previous are caused by server 75 | * which takes care of clients' queue synchronization. */ 76 | #define EV_QUEUE_ADD 0x54 77 | #define EV_QUEUE_DEL 0x55 78 | #define EV_QUEUE_MOVE 0x56 79 | #define EV_QUEUE_CLEAR 0x57 80 | 81 | /* State of the server. */ 82 | #define STATE_PLAY 0x01 83 | #define STATE_STOP 0x02 84 | #define STATE_PAUSE 0x03 85 | 86 | /* Definition of server commands. */ 87 | #define CMD_PLAY 0x00 /* play the first element on the list */ 88 | #define CMD_LIST_CLEAR 0x01 /* clear the list */ 89 | #define CMD_LIST_ADD 0x02 /* add an item to the list */ 90 | #define CMD_STOP 0x04 /* stop playing */ 91 | #define CMD_PAUSE 0x05 /* pause */ 92 | #define CMD_UNPAUSE 0x06 /* unpause */ 93 | #define CMD_SET_OPTION 0x07 /* set an option */ 94 | #define CMD_GET_OPTION 0x08 /* get an option */ 95 | #define CMD_GET_CTIME 0x0d /* get the current song time */ 96 | #define CMD_GET_SNAME 0x0f /* get the stream file name */ 97 | #define CMD_NEXT 0x10 /* start playing next song if available */ 98 | #define CMD_QUIT 0x11 /* shutdown the server */ 99 | #define CMD_SEEK 0x12 /* seek in the current stream */ 100 | #define CMD_GET_STATE 0x13 /* get the state */ 101 | #define CMD_DISCONNECT 0x15 /* disconnect from the server */ 102 | #define CMD_GET_BITRATE 0x16 /* get the bitrate */ 103 | #define CMD_GET_RATE 0x17 /* get the rate */ 104 | #define CMD_GET_CHANNELS 0x18 /* get the number of channels */ 105 | #define CMD_PING 0x19 /* request for EV_PONG */ 106 | #define CMD_GET_MIXER 0x1a /* get the volume level */ 107 | #define CMD_SET_MIXER 0x1b /* set the volume level */ 108 | #define CMD_DELETE 0x1c /* delete an item from the playlist */ 109 | #define CMD_SEND_PLIST_EVENTS 0x1d /* request for playlist events */ 110 | #define CMD_PREV 0x20 /* start playing previous song if available */ 111 | #define CMD_SEND_PLIST 0x21 /* send the playlist to the requesting client */ 112 | #define CMD_GET_PLIST 0x22 /* get the playlist from one of the clients */ 113 | #define CMD_CAN_SEND_PLIST 0x23 /* mark the client as able to send 114 | playlist */ 115 | #define CMD_CLI_PLIST_ADD 0x24 /* add an item to the client's playlist */ 116 | #define CMD_CLI_PLIST_DEL 0x25 /* delete an item from the client's 117 | playlist */ 118 | #define CMD_CLI_PLIST_CLEAR 0x26 /* clear the client's playlist */ 119 | #define CMD_GET_SERIAL 0x27 /* get an unique serial number */ 120 | #define CMD_PLIST_SET_SERIAL 0x28 /* assign a serial number to the server's 121 | playlist */ 122 | #define CMD_LOCK 0x29 /* acquire a lock */ 123 | #define CMD_UNLOCK 0x2a /* release the lock */ 124 | #define CMD_PLIST_GET_SERIAL 0x2b /* get the serial number of the server's 125 | playlist */ 126 | #define CMD_GET_TAGS 0x2c /* get tags for the currently played file */ 127 | #define CMD_TOGGLE_MIXER_CHANNEL 0x2d /* toggle the mixer channel */ 128 | #define CMD_GET_MIXER_CHANNEL_NAME 0x2e /* get the mixer channel's name */ 129 | #define CMD_GET_FILE_TAGS 0x2f /* get tags for the specified file */ 130 | #define CMD_ABORT_TAGS_REQUESTS 0x30 /* abort previous CMD_GET_FILE_TAGS 131 | requests up to some file */ 132 | #define CMD_CLI_PLIST_MOVE 0x31 /* move an item */ 133 | #define CMD_LIST_MOVE 0x32 /* move an item */ 134 | #define CMD_GET_AVG_BITRATE 0x33 /* get the average bitrate */ 135 | 136 | #define CMD_TOGGLE_SOFTMIXER 0x34 /* toggle use of softmixer */ 137 | #define CMD_TOGGLE_EQUALIZER 0x35 /* toggle use of equalizer */ 138 | #define CMD_EQUALIZER_REFRESH 0x36 /* refresh EQ-presets */ 139 | #define CMD_EQUALIZER_PREV 0x37 /* select previous eq-preset */ 140 | #define CMD_EQUALIZER_NEXT 0x38 /* select next eq-preset */ 141 | 142 | #define CMD_TOGGLE_MAKE_MONO 0x39 /* toggle mono mixing */ 143 | #define CMD_JUMP_TO 0x3a /* jumps to a some position in the current stream */ 144 | #define CMD_QUEUE_ADD 0x3b /* add an item to the queue */ 145 | #define CMD_QUEUE_DEL 0x3c /* delete an item from the queue */ 146 | #define CMD_QUEUE_MOVE 0x3d /* move an item in the queue */ 147 | #define CMD_QUEUE_CLEAR 0x3e /* clear the queue */ 148 | #define CMD_GET_QUEUE 0x3f /* request the queue from the server */ 149 | 150 | char *socket_name (); 151 | int get_int (int sock, int *i); 152 | enum noblock_io_status get_int_noblock (int sock, int *i); 153 | int send_int (int sock, int i); 154 | char *get_str (int sock); 155 | int send_str (int sock, const char *str); 156 | int get_time (int sock, time_t *i); 157 | int send_time (int sock, time_t i); 158 | int send_item (int sock, const struct plist_item *item); 159 | struct plist_item *recv_item (int sock); 160 | struct file_tags *recv_tags (int sock); 161 | int send_tags (int sock, const struct file_tags *tags); 162 | 163 | void event_queue_init (struct event_queue *q); 164 | void event_queue_free (struct event_queue *q); 165 | void free_event_data (const int type, void *data); 166 | struct event *event_get_first (struct event_queue *q); 167 | void event_pop (struct event_queue *q); 168 | void event_push (struct event_queue *q, const int event, void *data); 169 | int event_queue_empty (const struct event_queue *q); 170 | enum noblock_io_status event_send_noblock (int sock, struct event_queue *q); 171 | void free_tag_ev_data (struct tag_ev_response *d); 172 | void free_move_ev_data (struct move_ev_data *m); 173 | struct move_ev_data *move_ev_data_dup (const struct move_ev_data *m); 174 | struct move_ev_data *recv_move_ev_data (int sock); 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /rbtree.h: -------------------------------------------------------------------------------- 1 | #ifndef RBTREE_H 2 | #define RBTREE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef int rb_t_compare (const void *, const void *, const void *); 9 | typedef int rb_t_compare_key (const void *, const void *, const void *); 10 | 11 | struct rb_tree; 12 | struct rb_node; 13 | 14 | /* Whole-of-tree functions. */ 15 | struct rb_tree *rb_tree_new (rb_t_compare *cmp_fn, 16 | rb_t_compare_key *cmp_key_fn, 17 | const void *adata); 18 | void rb_tree_clear (struct rb_tree *t); 19 | void rb_tree_free (struct rb_tree *t); 20 | 21 | /* Individual node functions. */ 22 | void rb_delete (struct rb_tree *t, const void *key); 23 | struct rb_node *rb_next (struct rb_node *x); 24 | struct rb_node *rb_min (struct rb_tree *t); 25 | int rb_is_null (const struct rb_node *n); 26 | const void *rb_get_data (const struct rb_node *n); 27 | void rb_set_data (struct rb_node *n, const void *data); 28 | struct rb_node *rb_search (struct rb_tree *t, const void *key); 29 | void rb_insert (struct rb_tree *t, void *data); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /rcc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * Copyright (C) 2005,2011 Damian Pietras 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | */ 11 | 12 | #ifdef HAVE_CONFIG_H 13 | # include "config.h" 14 | #endif 15 | 16 | #include 17 | 18 | #ifdef HAVE_RCC 19 | # include 20 | #endif 21 | 22 | #include 23 | 24 | #include "rcc.h" 25 | 26 | char *rcc_reencode (char *str) 27 | { 28 | char *result = str; 29 | 30 | assert (str != NULL); 31 | 32 | #ifdef HAVE_RCC 33 | rcc_string rccstring; 34 | 35 | rccstring = rccFrom (NULL, 0, str); 36 | if (rccstring) { 37 | if (*rccstring) { 38 | char *reencoded; 39 | 40 | reencoded = rccToCharset (NULL, "UTF-8", rccstring); 41 | if (reencoded) { 42 | free (result); 43 | result = reencoded; 44 | } 45 | } 46 | 47 | free (rccstring); 48 | } 49 | #endif /* HAVE_RCC */ 50 | 51 | return result; 52 | } 53 | 54 | void rcc_init () 55 | { 56 | #ifdef HAVE_RCC 57 | rcc_class classes[] = { 58 | {"input", RCC_CLASS_STANDARD, NULL, NULL, "Input Encoding", 0}, 59 | {"output", RCC_CLASS_KNOWN, NULL, NULL, "Output Encoding", 0}, 60 | {NULL, 0, NULL, NULL, NULL, 0} 61 | }; 62 | 63 | rccInit (); 64 | rccInitDefaultContext (NULL, 0, 0, classes, 0); 65 | rccLoad (NULL, "moc"); 66 | rccSetOption (NULL, RCC_OPTION_TRANSLATE, 67 | RCC_OPTION_TRANSLATE_SKIP_PARRENT); 68 | rccSetOption (NULL, RCC_OPTION_AUTODETECT_LANGUAGE, 1); 69 | #endif /* HAVE_RCC */ 70 | } 71 | 72 | void rcc_cleanup () 73 | { 74 | #ifdef HAVE_RCC 75 | rccFree (); 76 | #endif /* HAVE_RCC */ 77 | } 78 | -------------------------------------------------------------------------------- /rcc.h: -------------------------------------------------------------------------------- 1 | #ifndef RCC_H 2 | #define RCC_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | char *rcc_reencode (char *); 9 | void rcc_init (); 10 | void rcc_cleanup (); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /server.h: -------------------------------------------------------------------------------- 1 | #ifndef SERVER_H 2 | #define SERVER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "playlist.h" 9 | 10 | #define CLIENTS_MAX 10 11 | 12 | void server_init (int debug, int foreground); 13 | void server_loop (); 14 | void server_error (const char *file, int line, const char *function, 15 | const char *msg); 16 | void state_change (); 17 | void set_info_rate (const int rate); 18 | void set_info_channels (const int channels); 19 | void set_info_bitrate (const int bitrate); 20 | void set_info_avg_bitrate (const int avg_bitrate); 21 | void tags_change (); 22 | void ctime_change (); 23 | void status_msg (const char *msg); 24 | void tags_response (const int client_id, const char *file, 25 | const struct file_tags *tags); 26 | void ev_audio_start (); 27 | void ev_audio_stop (); 28 | void server_queue_pop (const char *filename); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /sndio_out.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MOC - music on console 3 | * 4 | * SNDIO sound driver for MOC by Alexander Polakov. 5 | * Copyright (C) 2011 Alexander Polakov 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | */ 13 | 14 | #ifdef HAVE_CONFIG_H 15 | # include "config.h" 16 | #endif 17 | 18 | #ifdef HAVE_SNDIO_H 19 | # include 20 | #endif 21 | 22 | #include 23 | 24 | #include "common.h" 25 | #include "audio.h" 26 | #include "log.h" 27 | 28 | #define PCT_TO_SIO(pct) ((127 * (pct) + 50) / 100) 29 | #define SIO_TO_PCT(vol) ((100 * (vol) + 64) / 127) 30 | 31 | static struct sio_hdl *hdl = NULL; 32 | static int curvol = 100; 33 | static struct sound_params params = { 0, 0, 0 }; 34 | 35 | static void sndio_close (); 36 | 37 | static void volume_cb (void *unused ATTR_UNUSED, unsigned int vol) 38 | { 39 | curvol = SIO_TO_PCT(vol); 40 | } 41 | 42 | static int sndio_init (struct output_driver_caps *caps) 43 | { 44 | assert (caps != NULL); 45 | 46 | caps->formats = SFMT_S8 | SFMT_U8 | SFMT_U16 | SFMT_S16 | SFMT_NE; 47 | caps->min_channels = 1; 48 | caps->max_channels = 2; 49 | 50 | return 1; 51 | } 52 | 53 | static void sndio_shutdown () 54 | { 55 | if (hdl) 56 | sndio_close (); 57 | } 58 | 59 | /* Return 0 on failure. */ 60 | static int sndio_open (struct sound_params *sound_params) 61 | { 62 | struct sio_par par; 63 | 64 | assert (hdl == NULL); 65 | 66 | if ((hdl = sio_open (NULL, SIO_PLAY, 0)) == NULL) 67 | return 0; 68 | 69 | params = *sound_params; 70 | sio_initpar (&par); 71 | /* Add volume change callback. */ 72 | sio_onvol (hdl, volume_cb, NULL); 73 | par.rate = sound_params->rate; 74 | par.pchan = sound_params->channels; 75 | par.bits = (((sound_params->fmt & SFMT_S8) || 76 | (sound_params->fmt & SFMT_U8)) ? 8 : 16); 77 | par.le = SIO_LE_NATIVE; 78 | par.sig = (((sound_params->fmt & SFMT_S16) || 79 | (sound_params->fmt & SFMT_S8)) ? 1 : 0); 80 | par.round = par.rate / 8; 81 | par.appbufsz = par.round * 2; 82 | logit ("rate %d pchan %d bits %d sign %d", 83 | par.rate, par.pchan, par.bits, par.sig); 84 | 85 | if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par) 86 | || !sio_start (hdl)) { 87 | logit ("Failed to set sndio parameters."); 88 | sio_close (hdl); 89 | hdl = NULL; 90 | return 0; 91 | } 92 | sio_setvol (hdl, PCT_TO_SIO(curvol)); 93 | 94 | return 1; 95 | } 96 | 97 | /* Return the number of bytes played, or -1 on error. */ 98 | static int sndio_play (const char *buff, const size_t size) 99 | { 100 | int count; 101 | 102 | assert (hdl != NULL); 103 | 104 | count = (int) sio_write (hdl, buff, size); 105 | if (!count && sio_eof (hdl)) 106 | return -1; 107 | 108 | return count; 109 | } 110 | 111 | static void sndio_close () 112 | { 113 | assert (hdl != NULL); 114 | 115 | sio_stop (hdl); 116 | sio_close (hdl); 117 | hdl = NULL; 118 | } 119 | 120 | static int sndio_read_mixer () 121 | { 122 | return curvol; 123 | } 124 | 125 | static void sndio_set_mixer (int vol) 126 | { 127 | if (hdl != NULL) 128 | sio_setvol (hdl, PCT_TO_SIO (vol)); 129 | } 130 | 131 | static int sndio_get_buff_fill () 132 | { 133 | assert (hdl != NULL); 134 | 135 | /* Since we cannot stop SNDIO playing the samples already in 136 | * its buffer, there will never be anything left unheard. */ 137 | 138 | return 0; 139 | } 140 | 141 | static int sndio_reset () 142 | { 143 | assert (hdl != NULL); 144 | 145 | /* SNDIO will continue to play the samples already in its buffer 146 | * regardless of what we do, so there's nothing we can do. */ 147 | 148 | return 1; 149 | } 150 | 151 | static int sndio_get_rate () 152 | { 153 | assert (hdl != NULL); 154 | 155 | return params.rate; 156 | } 157 | 158 | static void sndio_toggle_mixer_channel () 159 | { 160 | assert (hdl != NULL); 161 | } 162 | 163 | static char *sndio_get_mixer_channel_name () 164 | { 165 | return xstrdup ("moc"); 166 | } 167 | 168 | void sndio_funcs (struct hw_funcs *funcs) 169 | { 170 | funcs->init = sndio_init; 171 | funcs->shutdown = sndio_shutdown; 172 | funcs->open = sndio_open; 173 | funcs->close = sndio_close; 174 | funcs->play = sndio_play; 175 | funcs->read_mixer = sndio_read_mixer; 176 | funcs->set_mixer = sndio_set_mixer; 177 | funcs->get_buff_fill = sndio_get_buff_fill; 178 | funcs->reset = sndio_reset; 179 | funcs->get_rate = sndio_get_rate; 180 | funcs->toggle_mixer_channel = sndio_toggle_mixer_channel; 181 | funcs->get_mixer_channel_name = sndio_get_mixer_channel_name; 182 | } 183 | -------------------------------------------------------------------------------- /sndio_out.h: -------------------------------------------------------------------------------- 1 | #ifndef SNDIO_OUT_H 2 | #define SNDIO_OUT_H 3 | 4 | #include "audio.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void sndio_funcs (struct hw_funcs *funcs); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /softmixer.h: -------------------------------------------------------------------------------- 1 | #ifndef SOFTMIXER_H 2 | #define SOFTMIXER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define SOFTMIXER_MIN 0 9 | /* Allow amplification, might result in clipping... */ 10 | #define SOFTMIXER_MAX 200 11 | 12 | #define SOFTMIXER_NAME "Soft" 13 | #define SOFTMIXER_NAME_OFF "S.Off" 14 | 15 | #define SOFTMIXER_CFG_ACTIVE "Active:" 16 | #define SOFTMIXER_CFG_AMP "Amplification:" 17 | #define SOFTMIXER_CFG_VALUE "Value:" 18 | #define SOFTMIXER_CFG_MONO "Mono:" 19 | 20 | #define SOFTMIXER_SAVE_OPTION "Softmixer_SaveState" 21 | #define SOFTMIXER_SAVE_FILE "softmixer" 22 | 23 | char *softmixer_name(); 24 | 25 | void softmixer_init(); 26 | void softmixer_shutdown(); 27 | 28 | int softmixer_get_value(); 29 | void softmixer_set_value(const int val); 30 | 31 | int softmixer_is_active(); 32 | void softmixer_set_active(int act); 33 | 34 | int softmixer_is_mono(); 35 | void softmixer_set_mono(int mono); 36 | 37 | void softmixer_process_buffer(char *buf, const size_t size, const struct sound_params *sound_params); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /tags_cache.h: -------------------------------------------------------------------------------- 1 | #ifndef TAGS_CACHE_H 2 | #define TAGS_CACHE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct file_tags; 9 | struct tags_cache; 10 | 11 | /* Administrative functions: */ 12 | struct tags_cache *tags_cache_new (size_t max_size); 13 | void tags_cache_free (struct tags_cache *c); 14 | 15 | /* Request queue manipulation functions: */ 16 | void tags_cache_clear_queue (struct tags_cache *c, int client_id); 17 | void tags_cache_clear_up_to (struct tags_cache *c, const char *file, 18 | int client_id); 19 | 20 | /* Cache DB manipulation functions: */ 21 | void tags_cache_load (struct tags_cache *c, const char *cache_dir); 22 | void tags_cache_add_request (struct tags_cache *c, const char *file, 23 | int tags_sel, int client_id); 24 | struct file_tags *tags_cache_get_immediate (struct tags_cache *c, 25 | const char *file, int tags_sel); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /themes.h: -------------------------------------------------------------------------------- 1 | #ifndef THEMES_H 2 | #define THEMES_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | enum color_index 9 | { 10 | CLR_BACKGROUND, 11 | CLR_FRAME, 12 | CLR_WIN_TITLE, 13 | CLR_MENU_ITEM_DIR, 14 | CLR_MENU_ITEM_DIR_SELECTED, 15 | CLR_MENU_ITEM_PLAYLIST, 16 | CLR_MENU_ITEM_PLAYLIST_SELECTED, 17 | CLR_MENU_ITEM_FILE, 18 | CLR_MENU_ITEM_FILE_SELECTED, 19 | CLR_MENU_ITEM_FILE_MARKED, 20 | CLR_MENU_ITEM_FILE_MARKED_SELECTED, 21 | CLR_MENU_ITEM_INFO, 22 | CLR_MENU_ITEM_INFO_SELECTED, 23 | CLR_MENU_ITEM_INFO_MARKED, 24 | CLR_MENU_ITEM_INFO_MARKED_SELECTED, 25 | CLR_STATUS, 26 | CLR_TITLE, 27 | CLR_STATE, 28 | CLR_TIME_CURRENT, 29 | CLR_TIME_LEFT, 30 | CLR_TIME_TOTAL, 31 | CLR_TIME_TOTAL_FRAMES, 32 | CLR_SOUND_PARAMS, 33 | CLR_LEGEND, 34 | CLR_INFO_DISABLED, 35 | CLR_INFO_ENABLED, 36 | CLR_MIXER_BAR_EMPTY, 37 | CLR_MIXER_BAR_FILL, 38 | CLR_TIME_BAR_EMPTY, 39 | CLR_TIME_BAR_FILL, 40 | CLR_ENTRY, 41 | CLR_ENTRY_TITLE, 42 | CLR_ERROR, 43 | CLR_MESSAGE, 44 | CLR_PLIST_TIME, 45 | CLR_LAST, /* Fake element to get number of colors */ 46 | CLR_WRONG 47 | }; 48 | 49 | void theme_init (bool has_xterm); 50 | int get_color (const enum color_index); 51 | void themes_switch_theme (const char *file); 52 | const char *get_current_theme (); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /themes/Makefile.am: -------------------------------------------------------------------------------- 1 | themesdir = $(pkgdatadir)/themes 2 | themes_DATA = transparent-background \ 3 | example_theme \ 4 | nightly_theme \ 5 | green_theme \ 6 | yellow_red_theme \ 7 | black_theme \ 8 | moca_theme \ 9 | red_theme \ 10 | darkdot_theme 11 | EXTRA_DIST = $(themes_DATA) 12 | -------------------------------------------------------------------------------- /themes/black_theme: -------------------------------------------------------------------------------- 1 | # Black theme by Arn 2 | 3 | background = white black 4 | frame = white black 5 | window_title = white black 6 | directory = white black 7 | selected_directory = white black reverse 8 | playlist = white black 9 | selected_playlist = white black reverse 10 | file = white black 11 | selected_file = white black reverse 12 | marked_file = white black bold 13 | marked_selected_file = white black bold,reverse 14 | info = white black underline 15 | status = white black 16 | title = white black bold 17 | state = white black 18 | current_time = white black bold 19 | time_left = white black bold 20 | total_time = white black bold 21 | time_total_frames = white black 22 | sound_parameters = white black bold 23 | legend = white black 24 | disabled = white black 25 | enabled = white black bold 26 | empty_mixer_bar = white black 27 | filled_mixer_bar = white black reverse 28 | empty_time_bar = white black 29 | filled_time_bar = white black reverse 30 | entry = white black 31 | entry_title = white black 32 | error = white black bold,underline 33 | message = white black 34 | plist_time = white black 35 | -------------------------------------------------------------------------------- /themes/darkdot_theme: -------------------------------------------------------------------------------- 1 | # Theme to match the 'darkdot' vim theme, by David Lazar (david_bv|at|yahoo|com) 2 | 3 | background = default default 4 | frame = white default 5 | window_title = white default 6 | directory = blue default bold 7 | selected_directory = black cyan 8 | playlist = white default bold 9 | selected_playlist = black cyan 10 | file = white default 11 | selected_file = black cyan 12 | marked_file = white default bold 13 | marked_selected_file = white cyan bold 14 | info = white default 15 | status = white default 16 | title = white default bold 17 | state = white default bold 18 | current_time = white default bold 19 | time_left = black default bold 20 | total_time = white default 21 | time_total_frames = white default 22 | sound_parameters = white default bold 23 | legend = white default 24 | disabled = black default bold 25 | enabled = white default bold 26 | empty_mixer_bar = white default 27 | filled_mixer_bar = black white 28 | empty_time_bar = white default 29 | filled_time_bar = black white 30 | entry = white default 31 | entry_title = white default 32 | error = white red bold 33 | message = white default 34 | plist_time = white default 35 | -------------------------------------------------------------------------------- /themes/example_theme: -------------------------------------------------------------------------------- 1 | # Example color theme for MOC. 2 | # You can use a theme by copying it to ~/.moc/themes directory and using 3 | # Theme config option or -T command line option. 4 | # 5 | # Fill free to make your own themes and send me them. It will be included in 6 | # official MOC releases or on the MOC web site. 7 | # 8 | # The format of this file is: 9 | # Lines beginning with # are comments. 10 | # Blank lines are ignored. 11 | # Every other line is expected to be in format: 12 | # 13 | # ELEMENT = FOREGROUND_COLOR BACKGROUND_COLOR [ATTRIBUTE[,ATTRIBUTE,..]] 14 | # 15 | # or 16 | # 17 | # colordef COLOR = RED GREEN BLUE 18 | # 19 | # Where names are case insensitive. 20 | # 21 | # ELEMENT is an element of MOC interface. This can be: 22 | # background - default background for regions when nothing is displayed 23 | # frame - frames for windows 24 | # window_title - the title of the window (eg name of the current 25 | # directory) 26 | # directory - a directory in the menu 27 | # selected_directory - a directory that is selected using arrows 28 | # playlist - playlist file 29 | # selected_playlist - see selected directory 30 | # file - an ordinary file in the menu (mp3, ogg, ...) 31 | # selected_file - see selected directory 32 | # marked_file - a file that is currently being played 33 | # marked_selected_file - a file that is currently being played and is also 34 | # selected using arrows 35 | # info - information shown at the right side of files 36 | # selected_info - see selected directory 37 | # marked_info - a file (its time) that is currently being played 38 | # marked_selected_info - a file (its time) that is currently being played 39 | # and is also selected using arrows 40 | # status - the status line with a message 41 | # title - the title of the file that is currently being played 42 | # state - the state: play, stop, or paused (>, [], ||) 43 | # current_time - current time of playing 44 | # time_left - the time left to the end of playing the current file 45 | # total_time - the length of the currently played file 46 | # time_total_frames - the brackets outside the total time of a file ([10:13]) 47 | # sound_parameters - the frequency and bitrate numbers 48 | # legend - "KHz" and "Kbps" 49 | # disabled - disabled element ([STEREO]) 50 | # enabled - enabled element 51 | # empty_mixer_bar - "empty" part of the volume bar 52 | # filled_mixer_bar - "filled" part of the volume bar 53 | # empty_time_bar - "empty" part of the time bar 54 | # filled_time_bar - "filled" part of the time bar 55 | # entry - place wher user can type a search query or a file name 56 | # entry_title - the title of an entry 57 | # error - error message 58 | # message - information message 59 | # plist_time - total time of displayed items 60 | # 61 | # FOREGOUND_COLOR and BACKGROUND_COLOR can have one of the following values: 62 | # black, red, green, yellow, blue, magenta, cyan, white, default (can be 63 | # transparent), grey (not standard, but works) 64 | # 65 | # Optional ATTRIBUTE parameters can be (from ncurses manual): 66 | # normal - default (no highlight) 67 | # standout - best highlighting mode of the terminal 68 | # underline - underlining 69 | # reverse - reverse video 70 | # blink - blinking 71 | # dim - half bright 72 | # bold - extra bright or bold 73 | # protect - protected mode 74 | # 75 | # You can specify a list of attributes separated by commas: attr1,attr2,attr3. 76 | # Don't use spaces anywhere in such a list. 77 | # 78 | # With colordef you can change the definition of a color. It works only if 79 | # your terminal supports it, if not those lines will be silently ignored. 80 | # COLOR must be a valid color name and the RED GREEN and BLUE are numbers 81 | # from 0 to 1000. Example: 82 | # 83 | # colordef red = 1000 0 0 84 | # 85 | # HINT: you have only 8 colors, but combined with attributes bold and/or 86 | # reversed you actually get more colors. 87 | # 88 | # If you don't specify some elements, the default values will be used. 89 | # 90 | # Here follows the default configuration: 91 | background = white blue 92 | frame = white blue 93 | window_title = white blue 94 | directory = white blue bold 95 | selected_directory = white black bold 96 | playlist = white blue bold 97 | selected_playlist = white black bold 98 | file = white blue 99 | selected_file = white black 100 | marked_file = green blue bold 101 | marked_selected_file = green black bold 102 | info = blue blue bold 103 | selected_info = blue black bold 104 | marked_info = blue blue bold 105 | marked_selected_info = blue black bold 106 | status = white blue 107 | title = white blue bold 108 | state = white blue bold 109 | current_time = white blue bold 110 | time_left = white blue bold 111 | total_time = white blue bold 112 | time_total_frames = white blue 113 | sound_parameters = white blue bold 114 | legend = white blue 115 | disabled = blue blue bold 116 | enabled = white blue bold 117 | empty_mixer_bar = white blue 118 | filled_mixer_bar = black cyan 119 | empty_time_bar = white blue 120 | filled_time_bar = black cyan 121 | entry = white blue 122 | entry_title = black cyan 123 | error = red blue bold 124 | message = green blue bold 125 | plist_time = white blue 126 | -------------------------------------------------------------------------------- /themes/green_theme: -------------------------------------------------------------------------------- 1 | # green theme by Jacek Lehmann 2 | # best viewed on shaded or black terminal 3 | 4 | background = default default 5 | frame = black default 6 | window_title = green default 7 | directory = red default 8 | selected_directory = yellow default 9 | playlist = blue default 10 | selected_playlist = magenta default 11 | file = green default 12 | selected_file = cyan default 13 | marked_file = green default bold 14 | marked_selected_file = cyan default bold 15 | info = cyan default 16 | status = magenta default 17 | title = green default 18 | state = magenta default 19 | current_time = magenta default 20 | time_left = cyan default 21 | total_time = cyan default 22 | time_total_frames = magenta default 23 | sound_parameters = cyan default 24 | legend = magenta default 25 | disabled = black default 26 | enabled = yellow default 27 | empty_mixer_bar = green default 28 | filled_mixer_bar = black green 29 | empty_time_bar = green default 30 | filled_time_bar = black green 31 | entry = yellow default 32 | entry_title = red default 33 | error = red default 34 | message = yellow default 35 | plist_time = magenta default 36 | -------------------------------------------------------------------------------- /themes/moca_theme: -------------------------------------------------------------------------------- 1 | # 2 | # Theme: moca 3 | # Author: Nicola Vitale 4 | # 5 | background = white black 6 | frame = white black 7 | window_title = yellow black bold 8 | directory = white black 9 | selected_directory = white black bold 10 | playlist = white black 11 | selected_playlist = cyan black bold 12 | file = white black 13 | selected_file = yellow red bold 14 | marked_file = cyan black blink,bold 15 | marked_selected_file = cyan red blink,bold 16 | info = magenta black bold 17 | status = yellow black bold 18 | title = cyan black bold 19 | state = red black bold 20 | current_time = green black bold 21 | time_left = magenta black bold 22 | total_time = red black bold 23 | time_total_frames = red black bold 24 | sound_parameters = white black bold 25 | legend = white black 26 | disabled = white black bold 27 | enabled = blue black bold 28 | empty_mixer_bar = cyan blue 29 | filled_mixer_bar = blue cyan 30 | empty_time_bar = green magenta 31 | filled_time_bar = magenta green 32 | entry = white black 33 | entry_title = magenta black bold 34 | error = red black bold 35 | message = green black bold 36 | plist_time = red black bold 37 | -------------------------------------------------------------------------------- /themes/nightly_theme: -------------------------------------------------------------------------------- 1 | # Author: Wim Speekenbrink 2 | 3 | background = blue black 4 | frame = blue black bold 5 | window_title = blue black bold 6 | directory = blue black bold 7 | selected_directory = black magenta 8 | playlist = blue black bold 9 | selected_playlist = black magenta 10 | file = blue black bold 11 | selected_file = black magenta 12 | marked_file = green black bold 13 | marked_selected_file = green magenta bold 14 | info = green black bold 15 | status = blue black bold 16 | title = green black bold 17 | state = blue black bold 18 | current_time = magenta black bold 19 | time_left = magenta black bold 20 | total_time = magenta black bold 21 | time_total_frames = blue black bold 22 | sound_parameters = magenta black bold 23 | legend = blue black bold 24 | disabled = black black 25 | enabled = blue black bold 26 | empty_mixer_bar = blue black bold 27 | filled_mixer_bar = black magenta 28 | empty_time_bar = blue black bold 29 | filled_time_bar = black magenta 30 | entry = green black bold 31 | entry_title = green black bold 32 | error = red black bold 33 | message = green black bold 34 | plist_time = green black bold 35 | -------------------------------------------------------------------------------- /themes/red_theme: -------------------------------------------------------------------------------- 1 | # rednblack theme by yyz 2 | # works good on a light term 3 | 4 | #property fg bg fx 5 | background = default default 6 | frame = black default 7 | window_title = black default 8 | directory = red default 9 | selected_directory = black default bold 10 | playlist = blue default 11 | selected_playlist = black default bold 12 | file = red default 13 | selected_file = black default bold 14 | marked_file = red default underline 15 | marked_selected_file = black default bold 16 | info = red default 17 | status = black default 18 | title = red default 19 | state = black default 20 | current_time = black default 21 | time_left = black default 22 | total_time = black default 23 | time_total_frames = black default 24 | sound_parameters = black default 25 | legend = black default 26 | disabled = white default 27 | enabled = black default 28 | empty_mixer_bar = black default 29 | filled_mixer_bar = black red 30 | empty_time_bar = black default 31 | filled_time_bar = black red 32 | entry = black default 33 | entry_title = red default 34 | error = red default 35 | message = black default 36 | plist_time = black default 37 | -------------------------------------------------------------------------------- /themes/transparent-background: -------------------------------------------------------------------------------- 1 | # Transparent background theme by Marcin Michałowski 2 | 3 | background = default default 4 | frame = white default 5 | window_title = white default 6 | directory = white default bold 7 | selected_directory = white blue bold 8 | playlist = white default bold 9 | selected_playlist = white blue bold 10 | file = white default 11 | selected_file = white blue 12 | marked_file = green default bold 13 | marked_selected_file = green blue bold 14 | info = blue default bold 15 | status = white default 16 | title = white default bold 17 | state = white default bold 18 | current_time = white default bold 19 | time_left = white default bold 20 | total_time = white default bold 21 | time_total_frames = white default 22 | sound_parameters = white default bold 23 | legend = white default 24 | disabled = blue default bold 25 | enabled = white default bold 26 | empty_mixer_bar = white default 27 | filled_mixer_bar = black cyan 28 | empty_time_bar = white default 29 | filled_time_bar = black cyan 30 | entry = white default 31 | entry_title = black cyan 32 | error = red default bold 33 | message = green default bold 34 | plist_time = white default bold 35 | -------------------------------------------------------------------------------- /themes/transparent-background_screenshot_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonsafari/mocp/48b48e593690ef0c398d5e33dc119b0a4fc73a2b/themes/transparent-background_screenshot_thumb.png -------------------------------------------------------------------------------- /themes/variant_red_theme: -------------------------------------------------------------------------------- 1 | # Variant Red Theme by centralkidede 2 | 3 | background = default default 4 | frame = white default 5 | window_title = white default 6 | directory = white default bold 7 | selected_directory = white red bold 8 | playlist = white default bold 9 | selected_playlist = white red bold 10 | file = white default 11 | selected_file = white red 12 | marked_file = red default bold 13 | marked_selected_file = white red bold 14 | info = red default bold 15 | selected_info = red default bold 16 | status = black default 17 | title = black white bold 18 | state = black white bold 19 | current_time = black white bold 20 | time_left = black white bold 21 | total_time = black white bold 22 | time_total_frames = black white 23 | sound_parameters = black white bold 24 | legend = black white 25 | disabled = black default bold 26 | enabled = white default bold 27 | empty_mixer_bar = black white 28 | filled_mixer_bar = white red 29 | empty_time_bar = white default 30 | filled_time_bar = black red 31 | entry = white red 32 | entry_title = black red 33 | error = red default bold 34 | message = red default bold 35 | plist_time = black white bold 36 | -------------------------------------------------------------------------------- /themes/yellow_red_theme: -------------------------------------------------------------------------------- 1 | # Yellow/Red theme - mostly Yellow. By Morten Grunnet Buhl 2 | # Doesn't work on terminals when underline is not supported (like Linux console) 3 | 4 | background = red default 5 | frame = red default 6 | window_title = yellow default underline,dim 7 | directory = yellow default 8 | selected_directory = yellow default underline 9 | playlist = yellow default 10 | selected_playlist = yellow default 11 | file = yellow default 12 | selected_file = yellow default underline 13 | marked_file = yellow default bold 14 | marked_selected_file = red default bold,underline 15 | info = yellow default 16 | status = yellow default 17 | title = yellow default 18 | state = yellow default 19 | current_time = yellow default 20 | time_left = yellow default 21 | total_time = yellow default 22 | time_total_frames = yellow default 23 | sound_parameters = yellow default 24 | legend = yellow default 25 | disabled = red default dim 26 | enabled = yellow default bold 27 | empty_mixer_bar = yellow red 28 | filled_mixer_bar = red yellow 29 | empty_time_bar = yellow default 30 | filled_time_bar = default yellow 31 | entry = yellow default 32 | entry_title = yellow default bold 33 | error = cyan default 34 | message = yellow default 35 | plist_time = yellow default 36 | -------------------------------------------------------------------------------- /tools/README: -------------------------------------------------------------------------------- 1 | MOC TOOLS DIRECTORY 2 | 3 | 4 | 1. Introduction 5 | 6 | This directory contains debugging and testing tools which are intended for 7 | developers and maintainers. 8 | 9 | 10 | 2. The Tools 11 | 12 | 2.1 MD5 Check 13 | 14 | The 'md5check.sh' script is intended to verify that the samples which 15 | arrive at MOC's player code are the same as those produced by the 16 | library the decoder is using. It does this by having MOC compute the 17 | MD5 sum of the audio file as it is playing it and writing the result to 18 | the server's log file. The log file is then read by the 'md5check.sh' 19 | tool and the MD5 sum checked against one computed from the audio file 20 | using the library's native decoding program. 21 | 22 | It is important to use the program associated with the decoder library 23 | if one exists because other programs may not produce exactly the same 24 | samples, particularly for lossy formats. It is also possible that bugs 25 | in the library mean the samples produced are not correct, but the tool 26 | is intended to test the passage of the samples through the driver and 27 | not the fidelity of the library used. 28 | 29 | 2.2 Test File Generation 30 | 31 | The 'maketests.sh' script generates test files in the directory in which 32 | it is run. The test files are 10 seconds of sinewave audio generated by 33 | SoX. Each file's name is in a format which represents its characteristics 34 | and these can be checked against those MOC uses with the '-e' option of 35 | 'md5scheck.sh'. 36 | 37 | All filenames start with 'sinewave-' and the script will refuse to run if 38 | any files starting with that name already exist. It is wise to run this 39 | script in an empty directory. It generates a lot of files. 40 | -------------------------------------------------------------------------------- /tools/maketests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # MOC - music on console 5 | # Copyright (C) 2004-2005 Damian Pietras 6 | # 7 | # maketests.sh Copyright (C) 2012 John Fitzgerald 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2 of the License, or 12 | # (at your option) any later version. 13 | # 14 | 15 | # 16 | # TODO: - Add other supported formats. 17 | # 18 | 19 | AUDIO=false 20 | VIDEO=false 21 | FFMPEG="$(which avconv 2>/dev/null || which ffmpeg 2>/dev/null)" 22 | SOX="$(which sox 2>/dev/null)" 23 | SYNTH="synth 10 sine 440 vol 0.5" 24 | 25 | # Clean error termination. 26 | function die { 27 | echo $@ > /dev/stderr 28 | exit 1 29 | } 30 | 31 | [[ -x "$SOX" ]] || die This script requires the SoX package. 32 | 33 | # Provide usage information. 34 | function usage () { 35 | echo "Usage: ${0##*/} [-a] [--audio] [-h] [--video] [FORMAT ...]" 36 | } 37 | 38 | # Provide help information. 39 | function help () { 40 | echo 41 | echo "MOC test file generation tool" 42 | echo 43 | usage 44 | echo 45 | echo " -a|--all Generate all formats" 46 | echo " --audio Generate all audio formats" 47 | echo " -h|--help This help information" 48 | echo " --video Generate all video formats" 49 | echo 50 | echo "Supported audio formats: flac mp3 vorbis wav" 51 | echo "Supported video formats: vob" 52 | echo 53 | } 54 | 55 | # Generate FLAC audio test files. 56 | function flac { 57 | echo "Generating FLAC audio test files" 58 | for r in 8000 16000 24000 32000 48000 96000 192000 \ 59 | 11025 22050 44100 88200 176400 60 | do 61 | for b in 16 32 62 | do 63 | $SOX -b$b -c1 -r$r -e signed -n -L sinewave-s${b}le-1-$r.flac $SYNTH 64 | $SOX -b$b -c2 -r$r -e signed -n -L sinewave-s${b}le-2-$r.flac $SYNTH 65 | done 66 | done 67 | } 68 | 69 | # Generate MP3 audio test files. 70 | function mp3 { 71 | echo "Generating MP3 audio test files" 72 | for r in 8000 16000 24000 32000 48000 11025 22050 44100 73 | do 74 | for c in 1 2 75 | do 76 | $SOX -b8 -c$c -r$r -n sinewave-u8-$c-$r.mp3 $SYNTH 77 | for b in 16 24 32 78 | do 79 | $SOX -b$b -c$c -r$r -n -L sinewave-s${b}le-$c-$r.mp3 $SYNTH 80 | $SOX -b$b -c$c -r$r -n -B sinewave-s${b}be-$c-$r.mp3 $SYNTH 81 | done 82 | done 83 | done 84 | } 85 | 86 | # Generate VOB video test files. 87 | function vob { 88 | [[ -x "$FFMPEG" ]] || return 89 | echo "Generating VOB video test files" 90 | for r in 16000 22050 24000 32000 44100 48000 91 | do 92 | for c in 1 2 93 | do 94 | $FFMPEG -f rawvideo -pix_fmt yuv420p -s 320x240 -r 30000/1001 \ 95 | -i /dev/zero \ 96 | -f s16le -c pcm_s16le -ac 2 -ar 48000 \ 97 | -i <($SOX -q -b16 -c2 -r 48000 -e signed -n -L -t s16 - $SYNTH) \ 98 | -vcodec mpeg2video -acodec mp2 -shortest -ac $c -ar $r \ 99 | -y sinewave-s16le-$c-$r.vob > /dev/null 2>&1 100 | done 101 | done 102 | } 103 | 104 | # Generate Ogg/Vorbis audio test files. 105 | function vorbis { 106 | echo "Generating Ogg/Vorbis audio test files" 107 | for r in 8000 16000 24000 32000 48000 96000 192000 \ 108 | 11025 22050 44100 88200 176400 109 | do 110 | $SOX -b16 -c1 -r$r -e signed -n -L sinewave-s16le-1-$r.ogg $SYNTH 111 | $SOX -b16 -c2 -r$r -e signed -n -L sinewave-s16le-2-$r.ogg $SYNTH 112 | done 113 | } 114 | 115 | # Generate WAV audio test files. 116 | function wav { 117 | echo "Generating WAV audio test files" 118 | for r in 8000 16000 24000 32000 48000 96000 192000 \ 119 | 11025 22050 44100 88200 176400 120 | do 121 | for c in 1 2 122 | do 123 | $SOX -b8 -c$c -r$r -n sinewave-u8-$c-$r.wav $SYNTH 124 | $SOX -b16 -c$c -r$r -n -B sinewave-s16be-$c-$r.wav $SYNTH 125 | for b in 16 24 32 126 | do 127 | $SOX -b$b -c$c -r$r -n -L sinewave-s${b}le-$c-$r.wav $SYNTH 128 | done 129 | done 130 | done 131 | } 132 | 133 | # Directory safety check. 134 | ls sinewave-* > /dev/null 2>&1 && { 135 | echo 136 | echo "This script generates many filenames starting with 'sinewave-' in the" 137 | echo "current directory which already contains similarly named files." 138 | echo "Running it in this directory is a really, really bad idea. (In fact," 139 | echo "it's probably not wise to run this script in a non-empty directory at" 140 | echo "all.) So we're aborting in the interests of safety." 141 | echo 142 | exit 1 143 | } > /dev/stderr 144 | 145 | # Process command line options. 146 | for OPTS 147 | do 148 | case $1 in 149 | -a|--all) AUDIO=true 150 | VIDEO=true 151 | ;; 152 | --audio) AUDIO=true 153 | ;; 154 | -h|--help) help 155 | exit 0 156 | ;; 157 | --video) VIDEO=true 158 | ;; 159 | -*) echo Unrecognised option: $1 160 | usage > /dev/stderr 161 | exit 1 162 | ;; 163 | *) break 164 | ;; 165 | esac 166 | shift 167 | done 168 | 169 | # Generate all audio formats. 170 | $AUDIO && { 171 | flac 172 | mp3 173 | vorbis 174 | wav 175 | } 176 | 177 | # Generate all video formats. 178 | $VIDEO && { 179 | vob 180 | } 181 | 182 | # Generate specified formats. 183 | for ARGS 184 | do 185 | case $1 in 186 | flac|mp3|vorbis|wav) 187 | $1 188 | ;; 189 | vob) 190 | $1 191 | ;; 192 | *) echo "*** Unsupported format: $1" 193 | echo 194 | ;; 195 | esac 196 | shift 197 | done 198 | 199 | exit 0 200 | -------------------------------------------------------------------------------- /utf8.h: -------------------------------------------------------------------------------- 1 | #ifndef UTF8_H 2 | #define UTF8_H 3 | 4 | #if defined HAVE_NCURSESW_CURSES_H 5 | # include 6 | #elif defined HAVE_NCURSESW_H 7 | # include 8 | #elif defined HAVE_NCURSES_CURSES_H 9 | # include 10 | #elif defined HAVE_NCURSES_H 11 | # include 12 | #elif defined HAVE_CURSES_H 13 | # include 14 | #endif 15 | 16 | #include 17 | #ifdef HAVE_ICONV 18 | # include 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* parameter passed to wcswidth() as a maximum width */ 26 | #define WIDTH_MAX 2048 27 | 28 | void utf8_init (); 29 | void utf8_cleanup (); 30 | int xwaddstr (WINDOW *win, const char *str); 31 | int xwaddnstr (WINDOW *win, const char *str, const int n); 32 | int xmvwaddstr (WINDOW *win, const int y, const int x, const char *str); 33 | int xmvwaddnstr (WINDOW *win, const int y, const int x, const char *str, 34 | const int n); 35 | int xwprintw (WINDOW *win, const char *fmt, ...) ATTR_PRINTF(2, 3); 36 | size_t strwidth (const char *s); 37 | char *xstrtail (const char *str, const int len); 38 | char *iconv_str (const iconv_t desc, const char *str); 39 | char *files_iconv_str (const char *str); 40 | char *xterm_iconv_str (const char *str); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | --------------------------------------------------------------------------------