linux/sound/synth/emux/emux.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
   3 *
   4 *  Routines for control of EMU WaveTable chip
   5 *
   6 *   This program is free software; you can redistribute it and/or modify
   7 *   it under the terms of the GNU General Public License as published by
   8 *   the Free Software Foundation; either version 2 of the License, or
   9 *   (at your option) any later version.
  10 *
  11 *   This program 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
  14 *   GNU General Public License for more details.
  15 *
  16 *   You should have received a copy of the GNU General Public License
  17 *   along with this program; if not, write to the Free Software
  18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19 */
  20
  21#include <linux/wait.h>
  22#include <linux/slab.h>
  23#include <linux/string.h>
  24#include <sound/core.h>
  25#include <sound/emux_synth.h>
  26#include <linux/init.h>
  27#include "emux_voice.h"
  28
  29MODULE_AUTHOR("Takashi Iwai");
  30MODULE_DESCRIPTION("Routines for control of EMU WaveTable chip");
  31MODULE_LICENSE("GPL");
  32
  33/*
  34 * create a new hardware dependent device for Emu8000/Emu10k1
  35 */
  36int snd_emux_new(struct snd_emux **remu)
  37{
  38        struct snd_emux *emu;
  39
  40        *remu = NULL;
  41        emu = kzalloc(sizeof(*emu), GFP_KERNEL);
  42        if (emu == NULL)
  43                return -ENOMEM;
  44
  45        spin_lock_init(&emu->voice_lock);
  46        mutex_init(&emu->register_mutex);
  47
  48        emu->client = -1;
  49#ifdef CONFIG_SND_SEQUENCER_OSS
  50        emu->oss_synth = NULL;
  51#endif
  52        emu->max_voices = 0;
  53        emu->use_time = 0;
  54
  55        init_timer(&emu->tlist);
  56        emu->tlist.function = snd_emux_timer_callback;
  57        emu->tlist.data = (unsigned long)emu;
  58        emu->timer_active = 0;
  59
  60        *remu = emu;
  61        return 0;
  62}
  63
  64EXPORT_SYMBOL(snd_emux_new);
  65
  66/*
  67 */
  68static int sf_sample_new(void *private_data, struct snd_sf_sample *sp,
  69                                  struct snd_util_memhdr *hdr,
  70                                  const void __user *buf, long count)
  71{
  72        struct snd_emux *emu = private_data;
  73        return emu->ops.sample_new(emu, sp, hdr, buf, count);
  74        
  75}
  76
  77static int sf_sample_free(void *private_data, struct snd_sf_sample *sp,
  78                                   struct snd_util_memhdr *hdr)
  79{
  80        struct snd_emux *emu = private_data;
  81        return emu->ops.sample_free(emu, sp, hdr);
  82        
  83}
  84
  85static void sf_sample_reset(void *private_data)
  86{
  87        struct snd_emux *emu = private_data;
  88        emu->ops.sample_reset(emu);
  89}
  90
  91int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name)
  92{
  93        int err;
  94        struct snd_sf_callback sf_cb;
  95
  96        if (snd_BUG_ON(!emu->hw || emu->max_voices <= 0))
  97                return -EINVAL;
  98        if (snd_BUG_ON(!card || !name))
  99                return -EINVAL;
 100
 101        emu->card = card;
 102        emu->name = kstrdup(name, GFP_KERNEL);
 103        emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice),
 104                              GFP_KERNEL);
 105        if (emu->voices == NULL)
 106                return -ENOMEM;
 107
 108        /* create soundfont list */
 109        memset(&sf_cb, 0, sizeof(sf_cb));
 110        sf_cb.private_data = emu;
 111        if (emu->ops.sample_new)
 112                sf_cb.sample_new = sf_sample_new;
 113        if (emu->ops.sample_free)
 114                sf_cb.sample_free = sf_sample_free;
 115        if (emu->ops.sample_reset)
 116                sf_cb.sample_reset = sf_sample_reset;
 117        emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
 118        if (emu->sflist == NULL)
 119                return -ENOMEM;
 120
 121        if ((err = snd_emux_init_hwdep(emu)) < 0)
 122                return err;
 123
 124        snd_emux_init_voices(emu);
 125
 126        snd_emux_init_seq(emu, card, index);
 127#ifdef CONFIG_SND_SEQUENCER_OSS
 128        snd_emux_init_seq_oss(emu);
 129#endif
 130        snd_emux_init_virmidi(emu, card);
 131
 132#ifdef CONFIG_PROC_FS
 133        snd_emux_proc_init(emu, card, index);
 134#endif
 135        return 0;
 136}
 137
 138EXPORT_SYMBOL(snd_emux_register);
 139
 140/*
 141 */
 142int snd_emux_free(struct snd_emux *emu)
 143{
 144        unsigned long flags;
 145
 146        if (! emu)
 147                return -EINVAL;
 148
 149        spin_lock_irqsave(&emu->voice_lock, flags);
 150        if (emu->timer_active)
 151                del_timer(&emu->tlist);
 152        spin_unlock_irqrestore(&emu->voice_lock, flags);
 153
 154#ifdef CONFIG_PROC_FS
 155        snd_emux_proc_free(emu);
 156#endif
 157        snd_emux_delete_virmidi(emu);
 158#ifdef CONFIG_SND_SEQUENCER_OSS
 159        snd_emux_detach_seq_oss(emu);
 160#endif
 161        snd_emux_detach_seq(emu);
 162
 163        snd_emux_delete_hwdep(emu);
 164
 165        if (emu->sflist)
 166                snd_sf_free(emu->sflist);
 167
 168        kfree(emu->voices);
 169        kfree(emu->name);
 170        kfree(emu);
 171        return 0;
 172}
 173
 174EXPORT_SYMBOL(snd_emux_free);
 175
 176
 177/*
 178 *  INIT part
 179 */
 180
 181static int __init alsa_emux_init(void)
 182{
 183        return 0;
 184}
 185
 186static void __exit alsa_emux_exit(void)
 187{
 188}
 189
 190module_init(alsa_emux_init)
 191module_exit(alsa_emux_exit)
 192