XMMS2
unixshm.c
Go to the documentation of this file.
1/* XMMS2 - X Music Multiplexer System
2 * Copyright (C) 2003-2011 XMMS2 Team
3 *
4 * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 */
16
17#include <sys/shm.h>
18#include <sys/sem.h>
19#include <sys/stat.h>
20#include <errno.h>
21
22#include "common.h"
23
24#ifdef _SEM_SEMUN_UNDEFINED
25 union semun {
26 int val; /* Value for SETVAL */
27 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
28 unsigned short *array; /* Array for GETALL, SETALL */
29 struct seminfo *__buf; /* Buffer for IPC_INFO (Linux specific) */
30 };
31#endif
32
33int32_t
34init_shm (xmms_visualization_t *vis, int32_t id, int32_t shmid, xmms_error_t *err)
35{
36 struct shmid_ds shm_desc;
37 int32_t semid;
38 void *buffer;
39 int size;
42 union semun semopts;
43
44 x_fetch_client (id);
45
46 /* MR. DEBUG */
47 /* xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "lame, more lame, shm!");
48 x_release_client ();
49 return -1; */
50
51
52 /* test the shm */
53 buffer = shmat (shmid, NULL, 0);
54 if (buffer == (void*)-1) {
55 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "couldn't attach to shared memory");
57 return -1;
58 }
59 shmctl (shmid, IPC_STAT, &shm_desc);
60 size = shm_desc.shm_segsz / sizeof (xmmsc_vischunk_t);
61
62 /* setup the semaphore set */
63 semid = semget (IPC_PRIVATE, 2, S_IRWXU + S_IRWXG + S_IRWXO);
64 if (semid == -1) {
65 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "couldn't create semaphore set");
67 return -1;
68 }
69
70 /* initially set semaphores - nothing to read, buffersize to write
71 first semaphore is the server semaphore */
72 semopts.val = size;
73 semctl (semid, 0, SETVAL, semopts);
74 semopts.val = 0;
75 semctl (semid, 1, SETVAL, semopts);
76
77 /* set up client structure */
78 c->type = VIS_UNIXSHM;
79 t = &c->transport.shm;
80 t->semid = semid;
81 t->shmid = shmid;
82 t->buffer = buffer;
83 t->size = size;
84 t->pos = 0;
85
87
88 xmms_log_info ("Visualization client %d initialised using Unix SHM", id);
89 return semid;
90}
91
93{
94 shmdt (t->buffer);
95 semctl (t->semid, 0, IPC_RMID, 0);
96}
97
98/**
99 * Decrements the server's semaphor (to write the next chunk)
100 */
101static gboolean
102decrement_server (xmmsc_vis_unixshm_t *t)
103{
104 /* alter semaphore 0 by -1, don't block */
105 struct sembuf op = { 0, -1, IPC_NOWAIT };
106
107 while (semop (t->semid, &op, 1) == -1) {
108 switch (errno) {
109 case EINTR:
110 break;
111 case EAGAIN:
112 return FALSE;
113 default:
114 perror ("Skipping visualization package");
115 return FALSE;
116 }
117 }
118 return TRUE;
119}
120
121/**
122 * Increments the client's semaphor (after a chunk was written)
123 */
124static void
125increment_client (xmmsc_vis_unixshm_t *t)
126{
127 /* alter semaphore 1 by 1, no flags */
128 struct sembuf op = { 1, +1, 0 };
129
130 if (semop (t->semid, &op, 1) == -1) {
131 /* there should not occur any error */
132 g_error ("visualization increment_client: %s\n", strerror (errno));
133 }
134}
135
136gboolean
137write_shm (xmmsc_vis_unixshm_t *t, xmms_vis_client_t *c, int32_t id, struct timeval *time, int channels, int size, short *buf)
138{
139 xmmsc_vischunk_t *dest;
140 short res;
141
142 if (!write_start_shm (id, t, &dest))
143 return FALSE;
144
145 tv2net (dest->timestamp, time);
146 dest->format = htons (c->format);
147 res = fill_buffer (dest->data, &c->prop, channels, size, buf);
148 dest->size = htons (res);
149 write_finish_shm (id, t, dest);
150
151 return TRUE;
152}
153
154
155gboolean
157{
158 struct shmid_ds shm_desc;
159
160 /* first check if the client is still there */
161 if (shmctl (t->shmid, IPC_STAT, &shm_desc) == -1) {
162 g_error ("Checking SHM attachments failed: %s\n", strerror (errno));
163 }
164 if (shm_desc.shm_nattch == 1) {
165 delete_client (id);
166 return FALSE;
167 }
168 if (shm_desc.shm_nattch != 2) {
169 g_error ("Unbelievable # of SHM attachments: %lu\n",
170 (unsigned long) shm_desc.shm_nattch);
171 }
172
173 if (!decrement_server (t)) {
174 return FALSE;
175 }
176
177 *dest = &t->buffer[t->pos];
178 return TRUE;
179}
180
181void
183{
184 t->pos = (t->pos + 1) % t->size;
185 increment_client (t);
186}
short fill_buffer(int16_t *dest, xmmsc_vis_properties_t *prop, int channels, int size, short *src)
Definition format.c:149
#define x_fetch_client(id)
Definition common.h:63
#define x_release_client()
Definition common.h:71
void delete_client(int32_t id)
Definition object.c:84
void tv2net(int32_t *d, struct timeval *t)
Definition timestamp.c:29
@ VIS_UNIXSHM
The structures for a vis client.
Definition common.h:30
unsigned short format
Definition common.h:36
xmmsc_vis_transport_t type
Definition common.h:35
xmmsc_vis_properties_t prop
Definition common.h:37
union xmms_vis_client_t::@2 transport
xmmsc_vis_unixshm_t shm
Definition common.h:32
The structures for the vis module.
Definition common.h:78
data describing a unixshm transport
xmmsc_vischunk_t * buffer
Package format for vis data, encapsulated by unixshm or udp transport.
int16_t data[2 *XMMSC_VISUALIZATION_WINDOW_SIZE]
void write_finish_shm(int32_t id, xmmsc_vis_unixshm_t *t, xmmsc_vischunk_t *dest)
Definition unixshm.c:182
gboolean write_start_shm(int32_t id, xmmsc_vis_unixshm_t *t, xmmsc_vischunk_t **dest)
Definition unixshm.c:156
void cleanup_shm(xmmsc_vis_unixshm_t *t)
Definition unixshm.c:92
int32_t init_shm(xmms_visualization_t *vis, int32_t id, int32_t shmid, xmms_error_t *err)
Definition unixshm.c:34
gboolean write_shm(xmmsc_vis_unixshm_t *t, xmms_vis_client_t *c, int32_t id, struct timeval *time, int channels, int size, short *buf)
Definition unixshm.c:137
#define xmms_log_info(fmt,...)
Definition xmms_log.h:34
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
@ XMMS_ERROR_NO_SAUSAGE