1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 
5 #ifdef WANT_ESD
6 
7 #include	<stdio.h>
8 #include	<unistd.h>
9 #include	<stdlib.h>
10 #ifdef HAVE_ERRNO_H
11 #  include	<errno.h>
12 #endif /* HAVE_ERRNO_H */
13 #include	<ctype.h>
14 #include	<fcntl.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 
19 #include <esd.h>
20 
21 #include "mpegsound.h"
22 #include "mpegsound_locals.h"
23 
24 //blocksize to use when writing to esd
25 #define ESD_BLOCK_SIZE 32768
26 
EsdPlayer(const char * host)27 EsdPlayer::EsdPlayer(const char *host)
28 {
29 	this->esd_handle = -1;
30 	this->host = host;
31 }
32 
~EsdPlayer()33 EsdPlayer::~EsdPlayer()
34 {
35 	if (esd_handle > -1)
36 	{
37 		(void)esd_close(esd_handle);
38 	}
39 }
40 
41 void
abort()42 EsdPlayer::abort()
43 {
44 	//doesn't seem like esd can be made to flush any caches.
45 }
46 
47 bool
setsoundtype(int stereo,int samplesize,int speed)48 EsdPlayer::setsoundtype(int stereo, int samplesize, int speed)
49 {
50 	if (esd_handle != -1)
51 	{
52 		debug("setsoundtype() called while esd_handle exists");
53 		seterrorcode(SOUND_ERROR_UNKNOWN);
54 		return false; //can only set soundtype once
55 	}
56 
57 	rawstereo = stereo;
58 	rawsamplesize = samplesize;
59 	rawspeed = speed;
60 
61 	return resetsoundtype();
62 }
63 
64 void
set8bitmode()65 EsdPlayer::set8bitmode()
66 {
67 	//ignore forced 8bits output requests ; esd must downsample itself.
68 }
69 
70 bool
resetsoundtype()71 EsdPlayer::resetsoundtype()
72 {
73 	int esd_format = 0;
74 
75 	debug("esdplayer::resetsoundtype\n");
76 	esd_format |= (rawstereo ? ESD_STEREO : ESD_MONO);
77 	esd_format |= (rawsamplesize == 8 ? ESD_BITS8 : ESD_BITS16);
78 
79 	if (esd_handle != -1)
80 	{
81 		//connection still exists. close it.
82 		(void)esd_close(esd_handle);
83 	}
84 
85 	//[re]open connection to esd
86 	esd_handle = esd_play_stream(esd_format, rawspeed, NULL, "mp3blaster");
87 
88 	if (esd_handle < 0)
89 	{
90 		debug("esd_play_stream failed: %s\n", strerror(errno));
91 		seterrorcode(SOUND_ERROR_DEVOPENFAIL);
92 		return false;
93 	}
94 
95 	return true;
96 }
97 
98 void
releasedevice()99 EsdPlayer::releasedevice()
100 {
101 	/* releasing sound device is pointless when using a sound daemon */
102 }
103 
104 bool
attachdevice()105 EsdPlayer::attachdevice()
106 {
107 	/* releasing sound device is pointless when using a sound daemon */
108 	return true;
109 }
110 
111 bool
putblock(void * buffer,int size)112 EsdPlayer::putblock(void *buffer, int size)
113 {
114 	int bytes_written = 0;
115 
116 	if (esd_handle < 0)
117 		return false;
118 
119 #if defined(AUDIO_NONBLOCKING) || defined(NEWTHREAD)
120 	while (bytes_written != size)
121 	{
122 		int tmp_bytes_written = putblock_nt((char*)buffer + bytes_written,
123 			size - bytes_written);
124 
125 		if (tmp_bytes_written < 0)
126 		{
127 			seterrorcode(SOUND_ERROR_DEVBUSY);
128 			return false;
129 		}
130 		bytes_written += tmp_bytes_written;
131 	}
132 #else
133 	bytes_written = putblock_nt(buffer, size);
134 
135 	if (bytes_written < 0)
136 	{
137 		seterrorcode(SOUND_ERROR_DEVBUSY);
138 		return false;
139 	}
140 #endif
141 
142 	return true;
143 }
144 
145 int
putblock_nt(void * buffer,int size)146 EsdPlayer::putblock_nt(void *buffer, int size)
147 {
148 #ifdef LIBPTH
149 	return pth_write(esd_handle, buffer, size);
150 #else
151 	return write(esd_handle, buffer, size);
152 #endif
153 }
154 
155 int
getblocksize()156 EsdPlayer::getblocksize()
157 {
158 	return ESD_BLOCK_SIZE; //XXX: config?
159 }
160 
161 int
fix_samplesize(void * buffer,int size)162 EsdPlayer::fix_samplesize(void *buffer, int size)
163 {
164 	(void)buffer;
165 
166 	//esd takes care of downsampling, no need to mangle samples
167 	return size;
168 }
169 #endif /* WANT_ESD */
170