Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/sound/core/seq/oss/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  seq_oss_readq.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OSS compatible sequencer driver
 *
 * seq_oss_readq.c - MIDI input queue
 *
 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
 */


#include "seq_oss_readq.h"
#include "seq_oss_event.h"
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include <linux/wait.h>
#include <linux/slab.h>

/*
 * constants
 */

//#define SNDRV_SEQ_OSS_MAX_TIMEOUT (unsigned long)(-1)
#define SNDRV_SEQ_OSS_MAX_TIMEOUT (HZ * 3600)


/*
 * prototypes
 */



/*
 * create a read queue
 */

struct seq_oss_readq *
snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
{
 struct seq_oss_readq *q;

 q = kzalloc(sizeof(*q), GFP_KERNEL);
 if (!q)
  return NULL;

 q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL);
 if (!q->q) {
  kfree(q);
  return NULL;
 }

 q->maxlen = maxlen;
 q->qlen = 0;
 q->head = q->tail = 0;
 init_waitqueue_head(&q->midi_sleep);
 spin_lock_init(&q->lock);
 q->pre_event_timeout = SNDRV_SEQ_OSS_MAX_TIMEOUT;
 q->input_time = (unsigned long)-1;

 return q;
}

/*
 * delete the read queue
 */

void
snd_seq_oss_readq_delete(struct seq_oss_readq *q)
{
 if (q) {
  kfree(q->q);
  kfree(q);
 }
}

/*
 * reset the read queue
 */

void
snd_seq_oss_readq_clear(struct seq_oss_readq *q)
{
 if (q->qlen) {
  q->qlen = 0;
  q->head = q->tail = 0;
 }
 /* if someone sleeping, wake'em up */
 wake_up(&q->midi_sleep);
 q->input_time = (unsigned long)-1;
}

/*
 * put a midi byte
 */

int
snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len)
{
 union evrec rec;
 int result;

 memset(&rec, 0, sizeof(rec));
 rec.c[0] = SEQ_MIDIPUTC;
 rec.c[2] = dev;

 while (len-- > 0) {
  rec.c[1] = *data++;
  result = snd_seq_oss_readq_put_event(q, &rec);
  if (result < 0)
   return result;
 }
 return 0;
}

/*
 * put MIDI sysex bytes; the event buffer may be chained, thus it has
 * to be expanded via snd_seq_dump_var_event().
 */

struct readq_sysex_ctx {
 struct seq_oss_readq *readq;
 int dev;
};

static int readq_dump_sysex(void *ptr, void *buf, int count)
{
 struct readq_sysex_ctx *ctx = ptr;

 return snd_seq_oss_readq_puts(ctx->readq, ctx->dev, buf, count);
}

int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
       struct snd_seq_event *ev)
{
 struct readq_sysex_ctx ctx = {
  .readq = q,
  .dev = dev
 };

 if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
  return 0;
 return snd_seq_dump_var_event(ev, readq_dump_sysex, &ctx);
}

/*
 * copy an event to input queue:
 * return zero if enqueued
 */

int
snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
 unsigned long flags;

 spin_lock_irqsave(&q->lock, flags);
 if (q->qlen >= q->maxlen - 1) {
  spin_unlock_irqrestore(&q->lock, flags);
  return -ENOMEM;
 }

 memcpy(&q->q[q->tail], ev, sizeof(*ev));
 q->tail = (q->tail + 1) % q->maxlen;
 q->qlen++;

 /* wake up sleeper */
 wake_up(&q->midi_sleep);

 spin_unlock_irqrestore(&q->lock, flags);

 return 0;
}


/*
 * pop queue
 * caller must hold lock
 */

int
snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec)
{
 if (q->qlen == 0)
  return -EAGAIN;
 memcpy(rec, &q->q[q->head], sizeof(*rec));
 return 0;
}

/*
 * sleep until ready
 */

void
snd_seq_oss_readq_wait(struct seq_oss_readq *q)
{
 wait_event_interruptible_timeout(q->midi_sleep,
      (q->qlen > 0 || q->head == q->tail),
      q->pre_event_timeout);
}

/*
 * drain one record
 * caller must hold lock
 */

void
snd_seq_oss_readq_free(struct seq_oss_readq *q)
{
 if (q->qlen > 0) {
  q->head = (q->head + 1) % q->maxlen;
  q->qlen--;
 }
}

/*
 * polling/select:
 * return non-zero if readq is not empty.
 */

unsigned int
snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait)
{
 poll_wait(file, &q->midi_sleep, wait);
 return q->qlen;
}

/*
 * put a timestamp
 */

int
snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
{
 if (curt != q->input_time) {
  union evrec rec;
  memset(&rec, 0, sizeof(rec));
  switch (seq_mode) {
  case SNDRV_SEQ_OSS_MODE_SYNTH:
   rec.echo = (curt << 8) | SEQ_WAIT;
   snd_seq_oss_readq_put_event(q, &rec);
   break;
  case SNDRV_SEQ_OSS_MODE_MUSIC:
   rec.t.code = EV_TIMING;
   rec.t.cmd = TMR_WAIT_ABS;
   rec.t.time = curt;
   snd_seq_oss_readq_put_event(q, &rec);
   break;
  }
  q->input_time = curt;
 }
 return 0;
}


#ifdef CONFIG_SND_PROC_FS
/*
 * proc interface
 */

void
snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf)
{
 snd_iprintf(buf, " read queue [%s] length = %d : tick = %ld\n",
      (waitqueue_active(&q->midi_sleep) ? "sleeping":"running"),
      q->qlen, q->input_time);
}
#endif /* CONFIG_SND_PROC_FS */

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.