1 #include "pipe_backend.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include "common/logger.h"
10
11 #ifndef _WIN32
12 #define FIFO_FILENAME "/tmp/vban_0"
13 #else
14 // name of named pipe is \\.\pipe\vban_0
15 #include <windef.h> // for DWORD and others
16 #include <winbase.h>
17 #define FIFO_FILENAME "\\\\.\\pipe\\vban_0"
18 #endif
19
20 struct pipe_backend_t
21 {
22 struct audio_backend_t parent;
23 int fd;
24 };
25
26 static int pipe_open(audio_backend_handle_t handle, char const* output_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config);
27 static int pipe_close(audio_backend_handle_t handle);
28 static int pipe_write(audio_backend_handle_t handle, char const* data, size_t size);
29 static int pipe_read(audio_backend_handle_t handle, char* data, size_t size);
30
jack_start(struct jack_backend_t * jack_backend)31 int pipe_backend_init(audio_backend_handle_t* handle)
32 {
33 struct pipe_backend_t* pipe_backend = 0;
34
35 if (handle == 0)
36 {
37 logger_log(LOG_FATAL, "%s: null handle pointer", __func__);
38 return -EINVAL;
39 }
40
41 pipe_backend = calloc(1, sizeof(struct pipe_backend_t));
42 if (pipe_backend == 0)
43 {
44 logger_log(LOG_FATAL, "%s: could not allocate memory", __func__);
45 return -ENOMEM;
46 }
47
48 pipe_backend->parent.open = pipe_open;
49 pipe_backend->parent.close = pipe_close;
50 pipe_backend->parent.write = pipe_write;
51 pipe_backend->parent.read = pipe_read;
52
53 *handle = (audio_backend_handle_t)pipe_backend;
54
55 return 0;
56
57 }
58
59 int pipe_open(audio_backend_handle_t handle, char const* output_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config)
60 {
61 int ret;
62 struct pipe_backend_t* const pipe_backend = (struct pipe_backend_t*)handle;
63
64 if (handle == 0)
65 {
66 logger_log(LOG_FATAL, "%s: handle pointer is null", __func__);
67 return -EINVAL;
68 }
69
70 #ifndef _WIN32
71 ret = mkfifo(FIFO_FILENAME, 0666);
72 if (ret < 0)
73 {
74 logger_log(LOG_FATAL, "%s: ???", __func__);
75 //todo:strerror
76 perror("mknod");
77 pipe_backend->fd = 0;
78 return ret;
79 }
80 #else
81 // Windows has no mkfifo function. Use named pipes instead
82 HANDLE named_pipe = CreateNamedPipeA(
83 /* lpName */ FIFO_FILENAME,
84 /* dwOpenMode */ PIPE_ACCESS_DUPLEX,
85 /* dwPipeMode */ PIPE_TYPE_MESSAGE, // or maybe PIPE_TYPE_BYTE, let's see
86 /* nMaxInstances */ 1,
87 /* nOutBufferSize */ 0,
88 /* nInBufferSize */ 0,
89 /* nDefaultTimeOut */ 0,
90 /* lpSecurityAttributes */ 0);
91 if (named_pipe == INVALID_HANDLE_VALUE)
jack_backend_init(audio_backend_handle_t * handle)92 {
93 logger_log(LOG_FATAL, "%s: ???", __func__);
94 //todo:strerror
95 perror("mknod");
96 pipe_backend->fd = 0;
97 ret = GetLastError();
98 return ret;
99 }
100 #endif // _WIN32
101
102 pipe_backend->fd = open((output_name[0] == 0) ? FIFO_FILENAME : output_name, (direction == AUDIO_OUT) ? O_WRONLY : O_RDONLY);
103 if (pipe_backend->fd == -1)
104 {
105 logger_log(LOG_FATAL, "%s: open error", __func__); //
106 perror("open");
107 return ret;
108 }
109
110 return 0;
111 }
112
113 int pipe_close(audio_backend_handle_t handle)
114 {
115 int ret = 0;
116 struct pipe_backend_t* const pipe_backend = (struct pipe_backend_t*)handle;
117
jack_open(audio_backend_handle_t handle,char const * output_name,enum audio_direction direction,size_t buffer_size,struct stream_config_t const * config)118 if (handle == 0)
119 {
120 logger_log(LOG_FATAL, "%s: handle pointer is null", __func__);
121 return -EINVAL;
122 }
123
124 if (pipe_backend== 0)
125 {
126 /** nothing to do */
127 return 0;
128 }
129
130 ret = close(pipe_backend->fd);
131 unlink(FIFO_FILENAME);
132 return ret;
133 }
134
135 int pipe_write(audio_backend_handle_t handle, char const* data, size_t size)
136 {
137 int ret = 0;
138 struct pipe_backend_t* const pipe_backend = (struct pipe_backend_t*)handle;
139
140 if ((handle == 0) || (data == 0))
141 {
142 logger_log(LOG_ERROR, "%s: handle or data pointer is null", __func__);
143 return -EINVAL;
144 }
145
146 ret = write(pipe_backend->fd, (const void *)data, size);
147 if (ret < 0)
148 {
149 logger_log(LOG_ERROR, "%s:", __func__);
150 perror("write");
151 }
152 return ret;
153 }
154
155 int pipe_read(audio_backend_handle_t handle, char* data, size_t size)
156 {
157 int ret = 0;
158 struct pipe_backend_t* const pipe_backend = (struct pipe_backend_t*)handle;
159
160 if ((handle == 0) || (data == 0))
161 {
162 logger_log(LOG_ERROR, "%s: handle or data pointer is null", __func__);
163 return -EINVAL;
164 }
165
166 ret = read(pipe_backend->fd, (void *)data, size);
167 if (ret < 0)
jack_close(audio_backend_handle_t handle)168 {
169 logger_log(LOG_ERROR, "%s:", __func__);
170 perror("read");
171 }
172 return ret;
173 }
174