📄 audio.c
字号:
status = ioctl(fd, OSS_SYSINFO, &sysinfo); sysinfo_ok = (status == 0); } if ((new_oss_running) && (sysinfo_ok)) { num_mixers = sysinfo.nummixers; num_dsps = sysinfo.numaudios; } close(fd); }#endif /* need to get which /dev/dsp lines match which /dev/mixer lines, * find out how many separate systems (soundcards) are available, * fill the audio_dsp and audio_mixer arrays with the system-related numbers, * since we have no way to tell from OSS info which mixers/dsps are the * main ones, we'll do some messing aound to try to deduce this info. * for example, SB uses two dsp ports and two mixers per card, whereas * Ensoniq uses 2 dsps and 1 mixer. * * the data we are gathering here: * int audio_dsp[MAX_SOUNDCARDS] -> main_dsp_port[MUS_AUDIO_PACK_SYSTEM(n)] (-1 => no such system dsp) * int audio_mixer[MAX_SOUNDCARDS] -> main_mixer_port[MUS_AUDIO_PACK_SYSTEM(n)] * int sound_cards = 0 -> usable systems * all auxiliary ports are currently ignored (SB equalizer, etc) */ sound_cards = 0; ndsp = 0; nmix = 0; while ((nmix < num_mixers) && (ndsp < num_dsps)) { /* for each mixer, find associated main dsp (assumed to be first in /dev/dsp ordering) */ /* if mixer's dsp overlaps or we run out of dsps first, ignore it (aux mixer) */ /* our by-guess-or-by-gosh method here is to try to open the mixer. * if that fails, quit (if very first, try at least to get the dsp setup) * find volume field, if none, go on, else read current volume * open next unchecked dsp, try to set volume, read current, if different we found a match -- set and go on. * if no change, move to next dsp and try again, if no more dsps, quit (checking for null case as before) */ mus_snprintf(dname, LABEL_BUFFER_SIZE, "%s%d", MIXER_NAME, nmix); md = open(dname, O_RDWR, 0); if (md == -1) { if (errno == EBUSY) { mus_print("%s is busy: can't access it [%s[%d] %s]", dname, __FILE__, __LINE__, c__FUNCTION__); nmix++; continue; } else break; } mus_snprintf(dname, LABEL_BUFFER_SIZE, "%s%d", DAC_NAME, ndsp); fd = open(dname, O_RDWR | O_NONBLOCK, 0); if (fd == -1) fd = open(dname, O_RDONLY | O_NONBLOCK, 0); if (fd == -1) fd = open(dname, O_WRONLY | O_NONBLOCK, 0); /* some output devices need this */ if (fd == -1) { close(md); if (errno == EBUSY) /* in linux /usr/include/asm/errno.h */ { fprintf(stderr, "%s is busy: can't access it\n", dname); ndsp++; continue; } else { if ((errno != ENXIO) && (errno != ENODEV)) fprintf(stderr, "%s: %s! ", dname, strerror(errno)); break; } }#ifdef NEW_OSS /* can't change volume yet of Sonorus, so the method above won't work -- * try to catch this case via the mixer's name */ status = ioctl(md, SOUND_MIXER_INFO, &mixinfo); if ((status == 0) && (mixinfo.name) && (*(mixinfo.name)) && (strlen(mixinfo.name) > 6)) { if (strncmp("STUDI/O", mixinfo.name, 7) == 0) { /* a special case in every regard */ audio_type[sound_cards] = SONORUS_STUDIO; audio_mixer[sound_cards] = nmix; nmix++; audio_dsp[sound_cards] = ndsp; if (num_dsps >= 21) { ndsp += 21; audio_mode[sound_cards] = 1; } else { ndsp += 9; audio_mode[sound_cards] = 0; } sound_cards++; close(fd); close(md); continue; } else { if (strncmp("RME Digi96", mixinfo.name, 10) == 0) { audio_type[sound_cards] = RME_HAMMERFALL; audio_mixer[sound_cards] = nmix; nmix++; audio_dsp[sound_cards] = ndsp; sound_cards++; close(fd); close(md); continue; } else { if (strncmp("M Audio Delta", mixinfo.name, 13) == 0) { audio_type[sound_cards] = DELTA_66; audio_mixer[sound_cards] = nmix; nmix++; ndsp += 6; /* just a guess */ audio_dsp[sound_cards] = ndsp; sound_cards++; close(fd); close(md); continue; } } } }#endif err = ioctl(md, SOUND_MIXER_READ_DEVMASK, &devmask); responsive_field = SOUND_MIXER_VOLUME; for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) if ((1 << i) & devmask) { responsive_field = i; break; } if (!err) { err = ioctl(md, MIXER_READ(responsive_field), &old_mixer_amp); if (!err) { err = ioctl(fd, MIXER_READ(responsive_field), &old_dsp_amp); if ((!err) && (old_dsp_amp == old_mixer_amp)) { if (old_mixer_amp == 0) amp = 50; else amp = 0; /* 0..100 */ err = ioctl(fd, MIXER_WRITE(responsive_field), &); if (!err) { err = ioctl(md, MIXER_READ(responsive_field), &new_mixer_amp); if (!err) { if (new_mixer_amp == amp) { /* found one! */ audio_dsp[sound_cards] = ndsp; ndsp++; audio_mixer[sound_cards] = nmix; nmix++; audio_type[sound_cards] = NORMAL_CARD; sound_cards++; } else ndsp++; err = ioctl(fd, MIXER_WRITE(responsive_field), &old_dsp_amp); } else nmix++; } else ndsp++; } else ndsp++; } else nmix++; } else nmix++; close(fd); close(md); } if (sound_cards == 0) { fd = open(DAC_NAME, O_WRONLY | O_NONBLOCK, 0); if (fd != -1) { sound_cards = 1; audio_dsp[0] = 0; audio_type[0] = NORMAL_CARD; audio_mixer[0] = -2; /* hmmm -- need a way to see /dev/dsp as lonely outpost */ close(fd); fd = open(MIXER_NAME, O_RDONLY | O_NONBLOCK, 0); if (fd == -1) audio_mixer[0] = -3; else close(fd); } } } return(MUS_NO_ERROR);}int mus_audio_reinitialize(void){ /* an experiment */ audio_initialized = false; return(mus_audio_initialize());}static int linux_audio_open(const char *pathname, int flags, mode_t mode, int system){ /* sometimes this is simply searching for a device (so failure is not a mus_error) */ if (audio_fd[system] == -1) { audio_fd[system] = open(pathname, flags, mode); audio_open_ctr[system] = 0; } else audio_open_ctr[system]++; return(audio_fd[system]);}static int linux_audio_open_with_error(const char *pathname, int flags, mode_t mode, int system){ int fd; fd = linux_audio_open(pathname, flags, mode, system); if (fd == -1) MUS_STANDARD_IO_ERROR(MUS_AUDIO_CANT_OPEN, ((mode == O_RDONLY) ? "open read" : (mode == O_WRONLY) ? "open write" : "open read/write"), pathname); return(fd);}static int find_system(int line){ int i; for (i = 0; i < sound_cards; i++) if (line == audio_fd[i]) return(i); return(MUS_ERROR);}static int linux_audio_close(int fd){ if (fd != -1) { int err = 0, sys; sys = find_system(fd); if (sys != -1) { if (audio_open_ctr[sys] > 0) audio_open_ctr[sys]--; else { err = close(fd); audio_open_ctr[sys] = 0; audio_fd[sys] = -1; } } else err = close(fd); if (err) RETURN_ERROR_EXIT(MUS_AUDIO_CANT_CLOSE, -1, mus_format("close %d failed: %s", fd, strerror(errno))); } /* is this an error? */ return(MUS_NO_ERROR);}static int to_oss_format(int snd_format){ switch (snd_format) { case MUS_BYTE: return(AFMT_S8); break; case MUS_BSHORT: return(AFMT_S16_BE); break; case MUS_UBYTE: return(AFMT_U8); break; case MUS_MULAW: return(AFMT_MU_LAW); break; case MUS_ALAW: return(AFMT_A_LAW); break; case MUS_LSHORT: return(AFMT_S16_LE); break; case MUS_UBSHORT: return(AFMT_U16_BE); break; case MUS_ULSHORT: return(AFMT_U16_LE); break;#ifdef NEW_OSS case MUS_LINT: return(AFMT_S32_LE); break; case MUS_BINT: return(AFMT_S32_BE); break;#endif } return(MUS_ERROR);}static char sonorus_buf[LABEL_BUFFER_SIZE];static char *sonorus_name(int sys, int offset){ mus_snprintf(sonorus_buf, LABEL_BUFFER_SIZE, "/dev/dsp%d", offset + audio_dsp[sys]); return(sonorus_buf);}static bool fragment_set_failed = false;static int oss_mus_audio_open_output(int ur_dev, int srate, int chans, int format, int size){ /* ur_dev is in general MUS_AUDIO_PACK_SYSTEM(n) | MUS_AUDIO_DEVICE */ int oss_format, buffer_info, audio_out = -1, sys, dev; char *dev_name;#ifndef NEW_OSS int stereo;#endif sys = MUS_AUDIO_SYSTEM(ur_dev); dev = MUS_AUDIO_DEVICE(ur_dev); oss_format = to_oss_format(format); if (oss_format == MUS_ERROR) RETURN_ERROR_EXIT(MUS_AUDIO_FORMAT_NOT_AVAILABLE, -1, mus_format("format %d (%s) not available", format, mus_data_format_name(format))); if (audio_type[sys] == SONORUS_STUDIO) { /* in this case the output devices are parcelled out to the /dev/dsp locs */ /* dev/dsp0 is always stereo */ switch (dev) { case MUS_AUDIO_DEFAULT: if (chans > 2) audio_out = open(sonorus_name(sys, 1), O_WRONLY, 0); else audio_out = open(sonorus_name(sys, 0), O_WRONLY, 0); /* probably should write to both outputs */ if (audio_out == -1) audio_out = open("/dev/dsp", O_WRONLY, 0); break; case MUS_AUDIO_SPEAKERS: audio_out = open(sonorus_name(sys, 0), O_WRONLY, 0); if (audio_out == -1) audio_out = open("/dev/dsp", O_WRONLY, 0); break; case MUS_AUDIO_ADAT_OUT: case MUS_AUDIO_SPDIF_OUT: audio_out = open(sonorus_name(sys, 1), O_WRONLY, 0); break; case MUS_AUDIO_AES_OUT: audio_out = open(sonorus_name(sys, 9), O_WRONLY, 0); break; default: RETURN_ERROR_EXIT(MUS_AUDIO_DEVICE_NOT_AVAILABLE, audio_out, mus_format("Sonorus device %d (%s) not available", dev, mus_audio_device_name(dev))); break; } if (audio_out == -1) RETURN_ERROR_EXIT(MUS_AUDIO_CANT_OPEN, audio_out, mus_format("can't open Sonorus output device %d (%s): %s", dev, mus_audio_device_name(dev), strerror(errno)));#ifdef NEW_OSS if (ioctl(audio_out, SNDCTL_DSP_CHANNELS, &chans) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_CHANNELS_NOT_AVAILABLE, audio_out, mus_format("can't get %d channels for Sonorus device %d (%s)", chans, dev, mus_audio_device_name(dev)));#endif return(audio_out); }#if HAVE_SAM_9407 if (audio_type[sys] == SAM9407_DSP) { char dname[LABEL_BUFFER_SIZE]; mus_snprintf(dname, LABEL_BUFFER_SIZE, "/dev/sam%d_dsp", audio_dsp[sys]); audio_out = open(dname, O_WRONLY); if(audio_out == -1) RETURN_ERROR_EXIT(MUS_AUDIO_CANT_OPEN, audio_out, mus_format("can't open %s: %s", dname, strerror(errno))); if ((ioctl(audio_out, SNDCTL_DSP_SETFMT, &oss_format) == -1) || (oss_format != to_oss_format(format))) RETURN_ERROR_EXIT(MUS_AUDIO_FORMAT_NOT_AVAILABLE, audio_out, mus_format("can't set %s format to %d (%s)", dname, format, mus_data_format_name(format))); if (ioctl(audio_out, SNDCTL_DSP_CHANNELS, &chans) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_CHANNELS_NOT_AVAILABLE, audio_out, mus_format("can't get %d channels on %s", chans, dname)); if (ioctl(audio_out, SNDCTL_DSP_SPEED, &srate) == -1) RETURN_ERROR_EXIT(MUS_AUDIO_SRATE_NOT_AVAILABLE, audio_out, mus_format("can't set srate to %d on %s", srate, dname)); FRAGMENT_SIZE = 14; buffer_info = (FRAGMENTS << 16) | (FRAGMENT_SIZE); ioctl(audio_out, SNDCTL_DSP_SETFRAGMENT, &buffer_info); return(audio_out); }#endif if (dev == MUS_AUDIO_DEFAULT) audio_out = linux_audio_open_with_error(dev_name = dac_name(sys, 0), O_WRONLY, 0, sys); else audio_out = linux_audio_open_with_error(dev_name = dac_nam
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -