File: SndUnix.cxx

package info (click to toggle)
stella 0.7-2
  • links: PTS
  • area: non-free
  • in suites: hamm, slink
  • size: 864 kB
  • ctags: 1,158
  • sloc: cpp: 6,615; ansic: 492; makefile: 224; asm: 31
file content (214 lines) | stat: -rw-r--r-- 4,723 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
//============================================================================
//
//    SSSS    tt          lll  lll              
//   SS  SS   tt           ll   ll                
//   SS     tttttt  eeee   ll   ll   aaaa    "An Atari 2600 VCS Emulator"
//    SSSS    tt   ee  ee  ll   ll      aa      
//       SS   tt   eeeeee  ll   ll   aaaaa   Copyright (c) 1995,1996,1997
//   SS  SS   tt   ee      ll   ll  aa  aa         Bradford W. Mott
//    SSSS     ttt  eeeee llll llll  aaaaa    
//
//============================================================================

/**
  This class implements the sound API for the Unix operating system.
  Under Unix the real work of the sound system is in another process
  called "stella-sound".  This process is started when an instance
  of the SoundUnix class is created.  Communicattion with the
  "stella-sound" process is done through a pipe.

  @author  Bradford W. Mott
  @version $Id: SndUnix.cxx,v 1.2 1997/05/17 19:00:07 bwmott Exp $
*/

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>

#include "SndUnix.hxx"

//============================================================================
// Constructor
//============================================================================
SoundUnix::SoundUnix()
    : myDisabled(false)
{
  // Initialize to impossible values so they will be reset 
  // on the first call to the set method
  myAUDC0 = myAUDC1 = myAUDF0 = myAUDF1 = myAUDV0 = myAUDV1 = 255;

  int pfd[2];

  // Create pipe for interprocess communication
  if(pipe(pfd))
  {
    // Oops. We were not able to create pipe so disable myself and return
    myDisabled = true;
    return;
  }

  // Create new process, setup pipe, and start stella-sound
  myProcessId = fork();

  if(myProcessId == 0)
  {
    // Close STDIN and put the read end of the pipe in its place
    dup2(pfd[0], 0);

    // Close unused file descriptors in child process
    close(pfd[0]);
    close(pfd[1]);
 
    // Execute the stella-sound server
    if(execlp("stella-sound", "stella-sound", (char*)0))
      exit(1);
  }
  else if(myProcessId > 0)
  {
    // Close unused file descriptors in parent process
    close(pfd[0]);

    // Save the pipe's write file descriptor
    myFd = pfd[1];
  }
  else
  {
    // Couldn't fork so cleanup and disabled myself
    close(pfd[0]);
    close(pfd[1]);

    myDisabled = true;
  }
}
 
//============================================================================
// Destructor
//============================================================================
SoundUnix::~SoundUnix()
{
  if(!myDisabled)
  {
    // Send quit command to the sound server
    unsigned char command = 0xC0;
    write(myFd, &command, 1);

    // Kill the sound server
    kill(myProcessId, SIGHUP);

    // Close descriptors
    close(myFd);
  }
}

//============================================================================
// Set the given sound register to the specified value
//============================================================================
void SoundUnix::set(Sound::Register reg, uByte value)
{
  // Return if I'm currently disabled or if the stella-sound process has died
  if(myDisabled || (waitpid(myProcessId, 0, WNOHANG) == myProcessId))
  {
    myDisabled = true;
    return;
  }

  uByte command;

  switch(reg)
  {
    case AUDC0:
    {
      if(myAUDC0 != (value & 0x0f))
      {
        myAUDC0 = (value & 0x0f);
        command = myAUDC0 | 0x00;
      }
      else
      {
        return;
      } 
      break;
    }

    case AUDC1:
    {
      if(myAUDC1 != (value & 0x0f))
      {
        myAUDC1 = (value & 0x0f);
        command = myAUDC1 | 0x20;
      }
      else
      {
        return;
      } 
      break;
    }

    case AUDF0:
    {
      if(myAUDF0 != (value & 0x1f))
      {
        myAUDF0 = (value & 0x1f);
        command = myAUDF0 | 0x40;
      }
      else
      {
        return;
      } 
      break;
    }

    case AUDF1:
    {
      if(myAUDF1 != (value & 0x1f))
      {
        myAUDF1 = (value & 0x1f);
        command = myAUDF1 | 0x60;
      }
      else
      {
        return;
      } 
      break;
    }

    case AUDV0:
    {
      if(myAUDV0 != (value & 0x0f))
      {
        myAUDV0 = (value & 0x0f);
        command = myAUDV0 | 0x80;
      }
      else
      {
        return;
      } 
      break;
    }

    case AUDV1:
    {
      if(myAUDV1 != (value & 0x0f))
      {
        myAUDV1 = (value & 0x0f);
        command = myAUDV1 | 0xA0;
      }
      else
      {
        return;
      } 
      break;
    }

    default:
    {
      return;
      break;
    }
  }

  // Send sound command to the stella-sound process
  write(myFd, &command, 1);
}