00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define _GNU_SOURCE
00017 #include <sys/shm.h>
00018 #include <sys/sem.h>
00019 #include <sys/stat.h>
00020 #include <errno.h>
00021
00022 #include "common.h"
00023
00024 #ifdef _SEM_SEMUN_UNDEFINED
00025 union semun {
00026 int val;
00027 struct semid_ds *buf;
00028 unsigned short *array;
00029 struct seminfo *__buf;
00030 };
00031 #endif
00032
00033 int32_t
00034 init_shm (xmms_visualization_t *vis, int32_t id, int32_t shmid, xmms_error_t *err)
00035 {
00036 struct shmid_ds shm_desc;
00037 int32_t semid;
00038 void *buffer;
00039 int size;
00040 xmms_vis_client_t *c;
00041 xmmsc_vis_unixshm_t *t;
00042 union semun semopts;
00043
00044 x_fetch_client (id);
00045
00046
00047
00048
00049
00050
00051
00052
00053 buffer = shmat (shmid, NULL, 0);
00054 if (buffer == (void*)-1) {
00055 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "couldn't attach to shared memory");
00056 x_release_client ();
00057 return -1;
00058 }
00059 shmctl (shmid, IPC_STAT, &shm_desc);
00060 size = shm_desc.shm_segsz / sizeof (xmmsc_vischunk_t);
00061
00062
00063 semid = semget (IPC_PRIVATE, 2, S_IRWXU + S_IRWXG + S_IRWXO);
00064 if (semid == -1) {
00065 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "couldn't create semaphore set");
00066 x_release_client ();
00067 return -1;
00068 }
00069
00070
00071
00072 semopts.val = size;
00073 semctl (semid, 0, SETVAL, semopts);
00074 semopts.val = 0;
00075 semctl (semid, 1, SETVAL, semopts);
00076
00077
00078 c->type = VIS_UNIXSHM;
00079 t = &c->transport.shm;
00080 t->semid = semid;
00081 t->shmid = shmid;
00082 t->buffer = buffer;
00083 t->size = size;
00084 t->pos = 0;
00085
00086 x_release_client ();
00087
00088 xmms_log_info ("Visualization client %d initialised using Unix SHM", id);
00089 return semid;
00090 }
00091
00092 void cleanup_shm (xmmsc_vis_unixshm_t *t)
00093 {
00094 shmdt (t->buffer);
00095 semctl (t->semid, 0, IPC_RMID, 0);
00096 }
00097
00098
00099
00100
00101 static gboolean
00102 decrement_server (xmmsc_vis_unixshm_t *t)
00103 {
00104
00105 struct sembuf op = { 0, -1, IPC_NOWAIT };
00106
00107 while (semop (t->semid, &op, 1) == -1) {
00108 switch (errno) {
00109 case EINTR:
00110 break;
00111 case EAGAIN:
00112 return FALSE;
00113 default:
00114 perror ("Skipping visualization package");
00115 return FALSE;
00116 }
00117 }
00118 return TRUE;
00119 }
00120
00121
00122
00123
00124 static void
00125 increment_client (xmmsc_vis_unixshm_t *t)
00126 {
00127
00128 struct sembuf op = { 1, +1, 0 };
00129
00130 if (semop (t->semid, &op, 1) == -1) {
00131
00132 g_error ("visualization increment_client: %s\n", strerror (errno));
00133 }
00134 }
00135
00136 gboolean
00137 write_shm (xmmsc_vis_unixshm_t *t, xmms_vis_client_t *c, int32_t id, struct timeval *time, int channels, int size, short *buf)
00138 {
00139 xmmsc_vischunk_t *dest;
00140 short res;
00141
00142 if (!write_start_shm (id, t, &dest))
00143 return FALSE;
00144
00145 tv2net (dest->timestamp, time);
00146 dest->format = htons (c->format);
00147 res = fill_buffer (dest->data, &c->prop, channels, size, buf);
00148 dest->size = htons (res);
00149 write_finish_shm (id, t, dest);
00150
00151 return TRUE;
00152 }
00153
00154
00155 gboolean
00156 write_start_shm (int32_t id, xmmsc_vis_unixshm_t *t, xmmsc_vischunk_t **dest)
00157 {
00158 struct shmid_ds shm_desc;
00159
00160
00161 if (shmctl (t->shmid, IPC_STAT, &shm_desc) == -1) {
00162 g_error ("Checking SHM attachments failed: %s\n", strerror (errno));
00163 }
00164 if (shm_desc.shm_nattch == 1) {
00165 delete_client (id);
00166 return FALSE;
00167 }
00168 if (shm_desc.shm_nattch != 2) {
00169 g_error ("Unbelievable # of SHM attachments: %lu\n",
00170 (unsigned long) shm_desc.shm_nattch);
00171 }
00172
00173 if (!decrement_server (t)) {
00174 return FALSE;
00175 }
00176
00177 *dest = &t->buffer[t->pos];
00178 return TRUE;
00179 }
00180
00181 void
00182 write_finish_shm (int32_t id, xmmsc_vis_unixshm_t *t, xmmsc_vischunk_t *dest)
00183 {
00184 t->pos = (t->pos + 1) % t->size;
00185 increment_client (t);
00186 }