Cygwin: dsp: Implement select()/poll().
Previously, sound device /dev/dsp did not support select()/poll(). These have been implemented with this patch. Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
This commit is contained in:
parent
7a43763d24
commit
2c06014f12
|
@ -1483,3 +1483,41 @@ fhandler_dev_dsp::_fixup_after_exec ()
|
|||
audio_out_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_dev_dsp::_write_ready ()
|
||||
{
|
||||
audio_buf_info info;
|
||||
if (audio_out_)
|
||||
{
|
||||
audio_out_->buf_info (&info, audiofreq_, audiobits_, audiochannels_);
|
||||
return info.bytes > 0;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_dev_dsp::_read_ready ()
|
||||
{
|
||||
audio_buf_info info;
|
||||
if (audio_in_)
|
||||
{
|
||||
audio_in_->buf_info (&info, audiofreq_, audiobits_, audiochannels_);
|
||||
return info.bytes > 0;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_dev_dsp::write_ready ()
|
||||
{
|
||||
return base ()->_write_ready ();
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_dev_dsp::read_ready ()
|
||||
{
|
||||
return base ()->_read_ready ();
|
||||
}
|
||||
|
|
|
@ -2847,6 +2847,9 @@ class fhandler_dev_dsp: public fhandler_base
|
|||
void close_audio_in ();
|
||||
void close_audio_out (bool = false);
|
||||
|
||||
bool _read_ready();
|
||||
bool _write_ready();
|
||||
|
||||
public:
|
||||
bool use_archetype () const {return true;}
|
||||
|
||||
|
@ -2866,6 +2869,14 @@ class fhandler_dev_dsp: public fhandler_base
|
|||
fh->copy_from (this);
|
||||
return fh;
|
||||
}
|
||||
|
||||
/* select.cc */
|
||||
select_record *select_read (select_stuff *);
|
||||
select_record *select_write (select_stuff *);
|
||||
select_record *select_except (select_stuff *);
|
||||
|
||||
bool read_ready();
|
||||
bool write_ready();
|
||||
};
|
||||
|
||||
class fhandler_virtual : public fhandler_base
|
||||
|
|
|
@ -87,6 +87,11 @@ struct select_socket_info: public select_info
|
|||
select_socket_info (): select_info (), num_w4 (0), ser_num (0), w4 (NULL) {}
|
||||
};
|
||||
|
||||
struct select_dsp_info: public select_info
|
||||
{
|
||||
select_dsp_info (): select_info () {}
|
||||
};
|
||||
|
||||
class select_stuff
|
||||
{
|
||||
public:
|
||||
|
@ -112,6 +117,7 @@ public:
|
|||
select_pipe_info *device_specific_ptys;
|
||||
select_fifo_info *device_specific_fifo;
|
||||
select_socket_info *device_specific_socket;
|
||||
select_dsp_info *device_specific_dsp;
|
||||
|
||||
bool test_and_set (int, fd_set *, fd_set *, fd_set *);
|
||||
int poll (fd_set *, fd_set *, fd_set *);
|
||||
|
@ -125,7 +131,8 @@ public:
|
|||
device_specific_pipe (NULL),
|
||||
device_specific_ptys (NULL),
|
||||
device_specific_fifo (NULL),
|
||||
device_specific_socket (NULL)
|
||||
device_specific_socket (NULL),
|
||||
device_specific_dsp (NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -2255,3 +2255,133 @@ fhandler_timerfd::select_except (select_stuff *stuff)
|
|||
s->except_ready = false;
|
||||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_dsp (select_record *s, bool from_select)
|
||||
{
|
||||
int gotone = 0;
|
||||
fhandler_dev_dsp *fh = (fhandler_dev_dsp *)(fhandler_base *) s->fh;
|
||||
|
||||
if (s->read_selected)
|
||||
if (s->read_ready || fh->read_ready ())
|
||||
gotone += s->read_ready = true;
|
||||
if (s->write_selected)
|
||||
if (s->write_ready || fh->write_ready ())
|
||||
gotone += s->write_ready = true;
|
||||
return gotone;
|
||||
}
|
||||
|
||||
static int start_thread_dsp (select_record *me, select_stuff *stuff);
|
||||
|
||||
static DWORD
|
||||
thread_dsp (void *arg)
|
||||
{
|
||||
select_dsp_info *di = (select_dsp_info *) arg;
|
||||
DWORD sleep_time = 0;
|
||||
bool looping = true;
|
||||
|
||||
while (looping)
|
||||
{
|
||||
for (select_record *s = di->start; (s = s->next); )
|
||||
if (s->startup == start_thread_dsp)
|
||||
{
|
||||
if (peek_dsp (s, true))
|
||||
looping = false;
|
||||
if (di->stop_thread)
|
||||
{
|
||||
select_printf ("stopping");
|
||||
looping = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!looping)
|
||||
break;
|
||||
cygwait (sleep_time >> 3);
|
||||
if (sleep_time < 80)
|
||||
++sleep_time;
|
||||
if (di->stop_thread)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
start_thread_dsp (select_record *me, select_stuff *stuff)
|
||||
{
|
||||
select_dsp_info *di = stuff->device_specific_dsp;
|
||||
if (di->start)
|
||||
me->h = *((select_dsp_info *) stuff->device_specific_dsp)->thread;
|
||||
else
|
||||
{
|
||||
di->start = &stuff->start;
|
||||
di->stop_thread = false;
|
||||
di->thread = new cygthread (thread_dsp, di, "dspsel");
|
||||
me->h = *di->thread;
|
||||
if (!me->h)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
dsp_cleanup (select_record *aaa, select_stuff *stuff)
|
||||
{
|
||||
select_dsp_info *di = (select_dsp_info *) stuff->device_specific_dsp;
|
||||
if (!di)
|
||||
return;
|
||||
if (di->thread)
|
||||
{
|
||||
di->stop_thread = true;
|
||||
di->thread->detach ();
|
||||
}
|
||||
delete di;
|
||||
stuff->device_specific_dsp = NULL;
|
||||
}
|
||||
|
||||
select_record *
|
||||
fhandler_dev_dsp::select_read (select_stuff *stuff)
|
||||
{
|
||||
if (!stuff->device_specific_dsp
|
||||
&& (stuff->device_specific_dsp = new select_dsp_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = stuff->start.next;
|
||||
s->startup = start_thread_dsp;
|
||||
s->peek = peek_dsp;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = dsp_cleanup;
|
||||
s->read_selected = true;
|
||||
s->read_ready = false;
|
||||
return s;
|
||||
}
|
||||
|
||||
select_record *
|
||||
fhandler_dev_dsp::select_write (select_stuff *stuff)
|
||||
{
|
||||
if (!stuff->device_specific_dsp
|
||||
&& (stuff->device_specific_dsp = new select_dsp_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = stuff->start.next;
|
||||
s->startup = start_thread_dsp;
|
||||
s->peek = peek_dsp;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = dsp_cleanup;
|
||||
s->write_selected = true;
|
||||
s->write_ready = false;
|
||||
return s;
|
||||
}
|
||||
|
||||
select_record *
|
||||
fhandler_dev_dsp::select_except (select_stuff *stuff)
|
||||
{
|
||||
if (!stuff->device_specific_dsp
|
||||
&& (stuff->device_specific_dsp = new select_dsp_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = stuff->start.next;
|
||||
s->startup = start_thread_dsp;
|
||||
s->peek = peek_dsp;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = dsp_cleanup;
|
||||
s->except_selected = true;
|
||||
s->except_ready = false;
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue