0001
0002
0003
0004
0005
0006
0007 #include <linux/time.h>
0008 #include <linux/slab.h>
0009 #include <sound/core.h>
0010 #include "seq_timer.h"
0011 #include "seq_prioq.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 struct snd_seq_prioq *snd_seq_prioq_new(void)
0043 {
0044 struct snd_seq_prioq *f;
0045
0046 f = kzalloc(sizeof(*f), GFP_KERNEL);
0047 if (!f)
0048 return NULL;
0049
0050 spin_lock_init(&f->lock);
0051 f->head = NULL;
0052 f->tail = NULL;
0053 f->cells = 0;
0054
0055 return f;
0056 }
0057
0058
0059 void snd_seq_prioq_delete(struct snd_seq_prioq **fifo)
0060 {
0061 struct snd_seq_prioq *f = *fifo;
0062 *fifo = NULL;
0063
0064 if (f == NULL) {
0065 pr_debug("ALSA: seq: snd_seq_prioq_delete() called with NULL prioq\n");
0066 return;
0067 }
0068
0069
0070
0071
0072 if (f->cells > 0) {
0073
0074 while (f->cells > 0)
0075 snd_seq_cell_free(snd_seq_prioq_cell_out(f, NULL));
0076 }
0077
0078 kfree(f);
0079 }
0080
0081
0082
0083
0084
0085
0086 static inline int compare_timestamp(struct snd_seq_event *a,
0087 struct snd_seq_event *b)
0088 {
0089 if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
0090
0091 return (snd_seq_compare_tick_time(&a->time.tick, &b->time.tick));
0092 } else {
0093
0094 return (snd_seq_compare_real_time(&a->time.time, &b->time.time));
0095 }
0096 }
0097
0098
0099
0100
0101
0102
0103 static inline int compare_timestamp_rel(struct snd_seq_event *a,
0104 struct snd_seq_event *b)
0105 {
0106 if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
0107
0108 if (a->time.tick > b->time.tick)
0109 return 1;
0110 else if (a->time.tick == b->time.tick)
0111 return 0;
0112 else
0113 return -1;
0114 } else {
0115
0116 if (a->time.time.tv_sec > b->time.time.tv_sec)
0117 return 1;
0118 else if (a->time.time.tv_sec == b->time.time.tv_sec) {
0119 if (a->time.time.tv_nsec > b->time.time.tv_nsec)
0120 return 1;
0121 else if (a->time.time.tv_nsec == b->time.time.tv_nsec)
0122 return 0;
0123 else
0124 return -1;
0125 } else
0126 return -1;
0127 }
0128 }
0129
0130
0131 int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
0132 struct snd_seq_event_cell * cell)
0133 {
0134 struct snd_seq_event_cell *cur, *prev;
0135 unsigned long flags;
0136 int count;
0137 int prior;
0138
0139 if (snd_BUG_ON(!f || !cell))
0140 return -EINVAL;
0141
0142
0143 prior = (cell->event.flags & SNDRV_SEQ_PRIORITY_MASK);
0144
0145 spin_lock_irqsave(&f->lock, flags);
0146
0147
0148
0149
0150 if (f->tail && !prior) {
0151 if (compare_timestamp(&cell->event, &f->tail->event)) {
0152
0153 f->tail->next = cell;
0154 f->tail = cell;
0155 cell->next = NULL;
0156 f->cells++;
0157 spin_unlock_irqrestore(&f->lock, flags);
0158 return 0;
0159 }
0160 }
0161
0162
0163
0164 prev = NULL;
0165 cur = f->head;
0166
0167 count = 10000;
0168 while (cur != NULL) {
0169
0170 int rel = compare_timestamp_rel(&cell->event, &cur->event);
0171 if (rel < 0)
0172
0173 break;
0174 else if (rel == 0 && prior)
0175
0176 break;
0177
0178
0179 prev = cur;
0180 cur = cur->next;
0181 if (! --count) {
0182 spin_unlock_irqrestore(&f->lock, flags);
0183 pr_err("ALSA: seq: cannot find a pointer.. infinite loop?\n");
0184 return -EINVAL;
0185 }
0186 }
0187
0188
0189 if (prev != NULL)
0190 prev->next = cell;
0191 cell->next = cur;
0192
0193 if (f->head == cur)
0194 f->head = cell;
0195 if (cur == NULL)
0196 f->tail = cell;
0197 f->cells++;
0198 spin_unlock_irqrestore(&f->lock, flags);
0199 return 0;
0200 }
0201
0202
0203 static int event_is_ready(struct snd_seq_event *ev, void *current_time)
0204 {
0205 if ((ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK)
0206 return snd_seq_compare_tick_time(current_time, &ev->time.tick);
0207 else
0208 return snd_seq_compare_real_time(current_time, &ev->time.time);
0209 }
0210
0211
0212 struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f,
0213 void *current_time)
0214 {
0215 struct snd_seq_event_cell *cell;
0216 unsigned long flags;
0217
0218 if (f == NULL) {
0219 pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n");
0220 return NULL;
0221 }
0222 spin_lock_irqsave(&f->lock, flags);
0223
0224 cell = f->head;
0225 if (cell && current_time && !event_is_ready(&cell->event, current_time))
0226 cell = NULL;
0227 if (cell) {
0228 f->head = cell->next;
0229
0230
0231 if (f->tail == cell)
0232 f->tail = NULL;
0233
0234 cell->next = NULL;
0235 f->cells--;
0236 }
0237
0238 spin_unlock_irqrestore(&f->lock, flags);
0239 return cell;
0240 }
0241
0242
0243 int snd_seq_prioq_avail(struct snd_seq_prioq * f)
0244 {
0245 if (f == NULL) {
0246 pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n");
0247 return 0;
0248 }
0249 return f->cells;
0250 }
0251
0252 static inline int prioq_match(struct snd_seq_event_cell *cell,
0253 int client, int timestamp)
0254 {
0255 if (cell->event.source.client == client ||
0256 cell->event.dest.client == client)
0257 return 1;
0258 if (!timestamp)
0259 return 0;
0260 switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
0261 case SNDRV_SEQ_TIME_STAMP_TICK:
0262 if (cell->event.time.tick)
0263 return 1;
0264 break;
0265 case SNDRV_SEQ_TIME_STAMP_REAL:
0266 if (cell->event.time.time.tv_sec ||
0267 cell->event.time.time.tv_nsec)
0268 return 1;
0269 break;
0270 }
0271 return 0;
0272 }
0273
0274
0275 void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
0276 {
0277 register struct snd_seq_event_cell *cell, *next;
0278 unsigned long flags;
0279 struct snd_seq_event_cell *prev = NULL;
0280 struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
0281
0282
0283 spin_lock_irqsave(&f->lock, flags);
0284 cell = f->head;
0285 while (cell) {
0286 next = cell->next;
0287 if (prioq_match(cell, client, timestamp)) {
0288
0289 if (cell == f->head) {
0290 f->head = cell->next;
0291 } else {
0292 prev->next = cell->next;
0293 }
0294 if (cell == f->tail)
0295 f->tail = cell->next;
0296 f->cells--;
0297
0298 cell->next = NULL;
0299 if (freefirst == NULL) {
0300 freefirst = cell;
0301 } else {
0302 freeprev->next = cell;
0303 }
0304 freeprev = cell;
0305 } else {
0306 #if 0
0307 pr_debug("ALSA: seq: type = %i, source = %i, dest = %i, "
0308 "client = %i\n",
0309 cell->event.type,
0310 cell->event.source.client,
0311 cell->event.dest.client,
0312 client);
0313 #endif
0314 prev = cell;
0315 }
0316 cell = next;
0317 }
0318 spin_unlock_irqrestore(&f->lock, flags);
0319
0320
0321 while (freefirst) {
0322 freenext = freefirst->next;
0323 snd_seq_cell_free(freefirst);
0324 freefirst = freenext;
0325 }
0326 }
0327
0328 static int prioq_remove_match(struct snd_seq_remove_events *info,
0329 struct snd_seq_event *ev)
0330 {
0331 int res;
0332
0333 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
0334 if (ev->dest.client != info->dest.client ||
0335 ev->dest.port != info->dest.port)
0336 return 0;
0337 }
0338 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
0339 if (! snd_seq_ev_is_channel_type(ev))
0340 return 0;
0341
0342 if (ev->data.note.channel != info->channel)
0343 return 0;
0344 }
0345 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
0346 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
0347 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
0348 else
0349 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
0350 if (!res)
0351 return 0;
0352 }
0353 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
0354 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
0355 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
0356 else
0357 res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
0358 if (res)
0359 return 0;
0360 }
0361 if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
0362 if (ev->type != info->type)
0363 return 0;
0364 }
0365 if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
0366
0367 switch (ev->type) {
0368 case SNDRV_SEQ_EVENT_NOTEOFF:
0369
0370 return 0;
0371 default:
0372 break;
0373 }
0374 }
0375 if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
0376 if (info->tag != ev->tag)
0377 return 0;
0378 }
0379
0380 return 1;
0381 }
0382
0383
0384 void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client,
0385 struct snd_seq_remove_events *info)
0386 {
0387 struct snd_seq_event_cell *cell, *next;
0388 unsigned long flags;
0389 struct snd_seq_event_cell *prev = NULL;
0390 struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
0391
0392
0393 spin_lock_irqsave(&f->lock, flags);
0394 cell = f->head;
0395
0396 while (cell) {
0397 next = cell->next;
0398 if (cell->event.source.client == client &&
0399 prioq_remove_match(info, &cell->event)) {
0400
0401
0402 if (cell == f->head) {
0403 f->head = cell->next;
0404 } else {
0405 prev->next = cell->next;
0406 }
0407
0408 if (cell == f->tail)
0409 f->tail = cell->next;
0410 f->cells--;
0411
0412
0413 cell->next = NULL;
0414 if (freefirst == NULL) {
0415 freefirst = cell;
0416 } else {
0417 freeprev->next = cell;
0418 }
0419
0420 freeprev = cell;
0421 } else {
0422 prev = cell;
0423 }
0424 cell = next;
0425 }
0426 spin_unlock_irqrestore(&f->lock, flags);
0427
0428
0429 while (freefirst) {
0430 freenext = freefirst->next;
0431 snd_seq_cell_free(freefirst);
0432 freefirst = freenext;
0433 }
0434 }
0435
0436