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