~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmidi/b_out.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        $Id: b_out.cpp,v 1.19 2001/04/12 09:09:23 garbanzo Exp $
 
3
*/
 
4
 
 
5
/* #if defined(__linux__) || defined(__FreeBSD__) || defined(sun) */
 
6
 
 
7
#include <stdio.h>
 
8
#include <stdlib.h>
 
9
#include <unistd.h>
 
10
#include <errno.h>
 
11
#include <string.h>
 
12
 
 
13
#ifdef AU_OSS
 
14
#ifdef __linux__
 
15
#include <sys/ioctl.h> /* new with 1.2.0? Didn't need this under 1.1.64 */
 
16
#include <linux/soundcard.h>
 
17
#endif
 
18
 
 
19
#ifdef __FreeBSD__
 
20
#include <machine/soundcard.h>
 
21
#endif
 
22
 
 
23
#ifdef __bsdi__
 
24
#include <sys/soundcard.h>
 
25
#endif
 
26
#endif
 
27
 
 
28
#include "config.h"
 
29
#include "common.h"
 
30
#include "instrum.h"
 
31
#include "playmidi.h"
 
32
#include "output.h"
 
33
#include "controls.h"
 
34
 
 
35
#define PRESUMED_FULLNESS 20
 
36
 
 
37
/* #define BB_SIZE (AUDIO_BUFFER_SIZE*128) */
 
38
/* #define BB_SIZE (AUDIO_BUFFER_SIZE*256) */
 
39
static unsigned char *bbuf = 0;
 
40
static int bboffset = 0, bbcount = 0;
 
41
static int outchunk = 0;
 
42
static int starting_up = 1, flushing = 0;
 
43
static int out_count = 0;
 
44
static int total_bytes = 0;
 
45
static int fragsize = 0;
 
46
static int fragstotal = 0;
 
47
 
 
48
/*
 
49
#if defined(AU_OSS) || defined(AU_SUN) || defined(AU_BSDI) || defined(AU_ESD)
 
50
#define WRITEDRIVER(fd,buf,cnt) write(fd,buf,cnt)
 
51
#else
 
52
*/
 
53
#define WRITEDRIVER(fd,buf,cnt) play_mode->driver_output_data(buf,cnt)
 
54
/*
 
55
#endif
 
56
*/
 
57
 
 
58
int b_out_count()
 
59
{
 
60
  return out_count;
 
61
}
 
62
 
 
63
void b_out(char id, int fd, int *buf, int ocount)
 
64
{
 
65
  int ret;
 
66
  uint32 ucount;
 
67
 
 
68
  if (ocount < 0) {
 
69
        out_count = bboffset = bbcount = outchunk = 0;
 
70
        starting_up = 1;
 
71
        flushing = 0;
 
72
        output_buffer_full = PRESUMED_FULLNESS;
 
73
        total_bytes = 0;
 
74
        return;
 
75
  }
 
76
 
 
77
  ucount = (uint32)ocount;
 
78
 
 
79
  if (!bbuf) {
 
80
    bbcount = bboffset = 0;
 
81
    bbuf = (unsigned char *)malloc(BB_SIZE);
 
82
    if (!bbuf) {
 
83
            fprintf(stderr, "malloc output error");
 
84
            #ifdef ADAGIO
 
85
            X_EXIT
 
86
            #else
 
87
            exit(1);
 
88
            #endif
 
89
    }
 
90
  }
 
91
 
 
92
  if (!total_bytes) {
 
93
#ifdef AU_OSS
 
94
#ifdef SNDCTL_DSP_GETOSPACE
 
95
    audio_buf_info info;
 
96
    if ( (id == 'd' || id == 'D') &&
 
97
         (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) != -1)) {
 
98
        fragstotal = info.fragstotal;
 
99
        fragsize = info.fragsize;
 
100
        total_bytes = fragstotal * fragsize;
 
101
        outchunk = fragsize;
 
102
    }
 
103
    else
 
104
#endif /* SNDCTL_DSP_GETOSPACE */
 
105
#endif
 
106
#ifdef AU_ALSA
 
107
    if (id == 's') {
 
108
        extern void alsa_tell(int *, int *);
 
109
        alsa_tell(&fragsize, &fragstotal);
 
110
        outchunk = fragsize;
 
111
        total_bytes = fragstotal * fragsize;
 
112
    }
 
113
    else
 
114
#endif
 
115
        total_bytes = AUDIO_BUFFER_SIZE*2;
 
116
  }
 
117
 
 
118
  if (ucount && !outchunk) outchunk = ucount;
 
119
  if (starting_up && ucount + bboffset + bbcount >= BB_SIZE) starting_up = 0;
 
120
  if (!ucount) { outchunk = starting_up = 0; flushing = 1; }
 
121
  else flushing = 0;
 
122
 
 
123
  if (starting_up || flushing) output_buffer_full = PRESUMED_FULLNESS;
 
124
  else {
 
125
        int samples_queued;
 
126
#ifdef AU_OSS
 
127
#ifdef SNDCTL_DSP_GETODELAY
 
128
        if ( (id == 'd' || id == 'D') &&
 
129
             (ioctl(fd, SNDCTL_DSP_GETODELAY, &samples_queued) == -1))
 
130
#endif
 
131
#endif
 
132
            samples_queued = 0;
 
133
 
 
134
        if (!samples_queued) output_buffer_full = PRESUMED_FULLNESS;
 
135
        else output_buffer_full = ((bbcount+samples_queued) * 100) / (BB_SIZE + total_bytes);
 
136
/* fprintf(stderr," %d",output_buffer_full); */
 
137
  }
 
138
 
 
139
  ret = 0;
 
140
 
 
141
  if (!starting_up)
 
142
  while (bbcount) {
 
143
    if (check_for_rc()) return;
 
144
    if (outchunk && bbcount >= outchunk)
 
145
        ret = WRITEDRIVER(fd, bbuf + bboffset, outchunk);
 
146
    else if (flushing) {
 
147
        if (fragsize) ret = bbcount;
 
148
        else ret = WRITEDRIVER(fd, bbuf + bboffset, bbcount);
 
149
    }
 
150
    if (bboffset) {
 
151
        memcpy(bbuf, bbuf + bboffset, bbcount);
 
152
        bboffset = 0;
 
153
    }
 
154
    if (ret < 0) {
 
155
        if (errno == EINTR) continue;
 
156
        else if (errno == EWOULDBLOCK) {
 
157
/*          if (bboffset) {
 
158
                memcpy(bbuf, bbuf + bboffset, bbcount);
 
159
                bboffset = 0;
 
160
            }  */
 
161
        /* fprintf(stderr, "BLOCK %d ", bbcount); */
 
162
            if (ucount && bboffset + bbcount + ucount <= BB_SIZE && !flushing) break;
 
163
            ctl->refresh();
 
164
#ifdef HAVE_USLEEP
 
165
            usleep(100);
 
166
#else
 
167
            sleep(1);
 
168
#endif
 
169
        }
 
170
        else {
 
171
            perror("error writing to dsp device");
 
172
            #ifdef ADAGIO
 
173
            X_EXIT
 
174
            #else
 
175
            exit(1);
 
176
            #endif
 
177
        }
 
178
    }
 
179
    else {
 
180
        if (!ret && bboffset + bbcount + ucount <= BB_SIZE && !flushing) break;
 
181
        if (!ret) usleep(250);
 
182
        else {
 
183
            out_count += ret;
 
184
            bboffset += ret;
 
185
            bbcount -= ret;
 
186
        }
 
187
        /* fprintf(stderr, "[%d:%d:f=%d/%d]\n", bbcount, ucount, output_buffer_full, BB_SIZE); */
 
188
        if (!bbcount) bboffset = 0;
 
189
        else if (bbcount < 0 || bboffset + bbcount > BB_SIZE) {
 
190
            fprintf(stderr, "b_out.c:Uh oh.\n");
 
191
            fprintf(stderr, "output error\n");
 
192
            bbcount = bboffset = 0;
 
193
            return;
 
194
        }
 
195
        if (bbcount < outchunk && !flushing) break;
 
196
    }
 
197
  }
 
198
 
 
199
  if (!ucount) { flushing = 0; starting_up = 1; out_count = bbcount = bboffset = 0; return; }
 
200
 
 
201
  memcpy(bbuf + bboffset + bbcount, buf, ucount);
 
202
  bbcount += ucount;
 
203
 
 
204
#ifndef KMIDI
 
205
  if (starting_up) return;
 
206
#endif
 
207
 
 
208
  if (ret >= 0) while (bbcount) {
 
209
    if (outchunk && bbcount >= outchunk)
 
210
        ret = WRITEDRIVER(fd, bbuf + bboffset, outchunk);
 
211
    /*else if (fragsize)  ret = bbcount;*/
 
212
    else if (fragsize)  { ret = 0; break; }
 
213
    else
 
214
        ret = WRITEDRIVER(fd, bbuf + bboffset, bbcount);
 
215
    ctl->refresh();
 
216
    if (ret < 0) {
 
217
        if (errno == EINTR) continue;
 
218
        else if (errno == EWOULDBLOCK) {
 
219
            /* fprintf(stderr, "block %d ", bbcount); */
 
220
            break;
 
221
        }
 
222
        else {
 
223
            perror("error writing to dsp device");
 
224
            #ifdef ADAGIO
 
225
            X_EXIT
 
226
            #else
 
227
            exit(1);
 
228
            #endif
 
229
        }
 
230
    }
 
231
    else {
 
232
        if (!ret && bboffset + bbcount + ucount <= BB_SIZE && !flushing) break;
 
233
        out_count += ret;
 
234
        bboffset += ret;
 
235
        bbcount -= ret;
 
236
        /*fprintf(stderr, "{%d:%d:r=%d}\n", bbcount,ucount,ret); */
 
237
        if (!bbcount) bboffset = 0;
 
238
        else if (bbcount < 0 || bboffset + bbcount > BB_SIZE) {
 
239
            fprintf(stderr, "b_out.c:output error\n");
 
240
            bbcount = bboffset = 0;
 
241
            return;
 
242
        }
 
243
    }
 
244
  }
 
245
}
 
246
/* #endif */