]>
Commit | Line | Data |
---|---|---|
0129db08 JL |
1 | /* |
2 | * pipe output driver. This file is part of Shairport. | |
3 | * Copyright (c) James Laird 2013 | |
4 | * All rights reserved. | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person | |
7 | * obtaining a copy of this software and associated documentation | |
8 | * files (the "Software"), to deal in the Software without | |
9 | * restriction, including without limitation the rights to use, | |
10 | * copy, modify, merge, publish, distribute, sublicense, and/or | |
11 | * sell copies of the Software, and to permit persons to whom the | |
12 | * Software is furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be | |
15 | * included in all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
24 | * OTHER DEALINGS IN THE SOFTWARE. | |
25 | */ | |
26 | ||
27 | #include <stdio.h> | |
28 | #include <unistd.h> | |
29 | #include <fcntl.h> | |
30 | #include <memory.h> | |
2e27c885 | 31 | #include <stdlib.h> |
4cd3f5c3 | 32 | #include <errno.h> |
0cc29d63 MB |
33 | #include <sys/types.h> |
34 | #include <sys/stat.h> | |
0129db08 JL |
35 | #include "common.h" |
36 | #include "audio.h" | |
37 | ||
28a5afc9 | 38 | static int fd = -1; |
0129db08 JL |
39 | |
40 | char *pipename = NULL; | |
41 | ||
42 | static void start(int sample_rate) { | |
fdbf64e9 MB |
43 | // this will leave fd as -1 if a reader hasn't been attached |
44 | fd = open(pipename, O_WRONLY | O_NONBLOCK); | |
0129db08 JL |
45 | } |
46 | ||
fdbf64e9 MB |
47 | static void play(short buf[], int samples) { |
48 | // if the file is not open, try to open it. | |
49 | if (fd == -1) { | |
50 | fd = open(pipename, O_WRONLY | O_NONBLOCK); | |
51 | } | |
52 | // if it's got a reader, write to it. | |
53 | if (fd != -1) { | |
54 | int ignore = non_blocking_write(fd, buf, samples * 4); | |
55 | } | |
56 | } | |
0129db08 JL |
57 | |
58 | static void stop(void) { | |
fdbf64e9 MB |
59 | // Don't close the pipe just because a play session has stopped. |
60 | // if (fd > 0) | |
61 | // close(fd); | |
0129db08 JL |
62 | } |
63 | ||
54250f75 | 64 | static int init(int argc, char **argv) { |
fdbf64e9 | 65 | debug(1, "pipe init"); |
38281dd1 MB |
66 | const char *str; |
67 | int value; | |
fdbf64e9 | 68 | |
87a0475c | 69 | config.audio_backend_buffer_desired_length = 44100; // one second. |
54250f75 | 70 | config.audio_backend_latency_offset = 0; |
0129db08 | 71 | |
87a0475c MB |
72 | if (config.cfg != NULL) { |
73 | /* Get the Output Pipename. */ | |
74 | const char *str; | |
75 | if (config_lookup_string(config.cfg, "pipe.name", &str)) { | |
76 | pipename = (char *)str; | |
77 | } | |
fdbf64e9 MB |
78 | |
79 | if ((pipename) && (strcasecmp(pipename, "STDOUT") == 0)) | |
80 | die("Can't use \"pipe\" backend for STDOUT. Use the \"stdout\" backend instead."); | |
38281dd1 MB |
81 | |
82 | /* Get the desired buffer size setting. */ | |
83 | if (config_lookup_int(config.cfg, "pipe.audio_backend_buffer_desired_length", &value)) { | |
58a13cf8 MB |
84 | if ((value < 0) || (value > 132300)) |
85 | die("Invalid pipe audio backend buffer desired length \"%d\". It should be between 0 and 132300, default is 44100", | |
38281dd1 MB |
86 | value); |
87 | else | |
88 | config.audio_backend_buffer_desired_length = value; | |
89 | } | |
90 | ||
91 | /* Get the latency offset. */ | |
92 | if (config_lookup_int(config.cfg, "pipe.audio_backend_latency_offset", &value)) { | |
58a13cf8 MB |
93 | if ((value < -66150) || (value > 66150)) |
94 | die("Invalid pipe audio backend buffer latency offset \"%d\". It should be between -66150 and +66150, default is 0", | |
38281dd1 MB |
95 | value); |
96 | else | |
97 | config.audio_backend_latency_offset = value; | |
98 | } | |
4cd3f5c3 | 99 | } |
fdbf64e9 | 100 | |
87a0475c MB |
101 | if ((pipename == NULL) && (argc != 1)) |
102 | die("bad or missing argument(s) to pipe"); | |
4cd3f5c3 | 103 | |
87a0475c MB |
104 | if (argc == 1) |
105 | pipename = strdup(argv[0]); | |
fdbf64e9 MB |
106 | |
107 | ||
87a0475c | 108 | // here, create the pipe |
fdbf64e9 MB |
109 | if (mkfifo(pipename, 0644) && errno != EEXIST) |
110 | die("Could not create output pipe \"%s\"", pipename); | |
4cd3f5c3 | 111 | |
87a0475c | 112 | debug(1, "Pipename is \"%s\"", pipename); |
0129db08 | 113 | |
87a0475c | 114 | return 0; |
0129db08 JL |
115 | } |
116 | ||
117 | static void deinit(void) { | |
fdbf64e9 | 118 | if (fd > 0) |
87a0475c | 119 | close(fd); |
0129db08 JL |
120 | } |
121 | ||
122 | static void help(void) { | |
38281dd1 | 123 | printf(" pipe takes 1 argument: the name of the FIFO to write to.\n"); |
0129db08 JL |
124 | } |
125 | ||
87a0475c MB |
126 | audio_output audio_pipe = {.name = "pipe", |
127 | .help = &help, | |
128 | .init = &init, | |
129 | .deinit = &deinit, | |
130 | .start = &start, | |
131 | .stop = &stop, | |
132 | .flush = NULL, | |
133 | .delay = NULL, | |
134 | .play = &play, | |
135 | .volume = NULL, | |
136 | .parameters = NULL}; |