Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2023-09-06 16:03:18 +0300
committerTakashi Yano <takashi.yano@nifty.ne.jp>2023-09-06 16:06:57 +0300
commit2c06014f12b0231e40d4256ae5f0d16a4b21be48 (patch)
treed176f78f13b6c4ad71c77241d356cc16aacb1631 /winsup
parent7a43763d24ab693502b0d0b1323d8cba1123e59a (diff)
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>
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/fhandler/dsp.cc38
-rw-r--r--winsup/cygwin/local_includes/fhandler.h11
-rw-r--r--winsup/cygwin/local_includes/select.h9
-rw-r--r--winsup/cygwin/select.cc130
4 files changed, 187 insertions, 1 deletions
diff --git a/winsup/cygwin/fhandler/dsp.cc b/winsup/cygwin/fhandler/dsp.cc
index 861443352..f1634f7a8 100644
--- a/winsup/cygwin/fhandler/dsp.cc
+++ b/winsup/cygwin/fhandler/dsp.cc
@@ -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 ();
+}
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index f2658a242..d7dc02e89 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -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
diff --git a/winsup/cygwin/local_includes/select.h b/winsup/cygwin/local_includes/select.h
index b794690b6..4e202128f 100644
--- a/winsup/cygwin/local_includes/select.h
+++ b/winsup/cygwin/local_includes/select.h
@@ -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)
{}
};
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index bad4c37f3..3ad12c262 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -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;
+}