This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: oss_audio_device.write(data) produces short writes
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.4
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: akira, ashkop, iritkatriel
Priority: normal Keywords:

Created on 2014-07-28 10:29 by akira, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg224159 - (view) Author: Akira Li (akira) * Date: 2014-07-28 10:29
$ ./python -mtest -uaudio test_ossaudiodev
[1/1] test_ossaudiodev
test test_ossaudiodev failed -- Traceback (most recent call last):
  File "./Lib/test/test_ossaudiodev.py", line 148, in test_playback
    self.play_sound_file(*sound_info)
  File "./Lib/test/test_ossaudiodev.py", line 89, in play_sound_file
    (elapsed_time, expected_time))
AssertionError: False is not true : elapsed time (0.0590214729309082) > 10% off of expected time (3.5127309036445333)

1 test failed:
    test_ossaudiodev

The failure is caused by dsp.write(data) that doesn't write all data
on my machine.  If it is replaced with dsp.writeall(data) then the test
passes.

The docs [1] say that dsp.write() should write all data by default:

  oss_audio_device.write(data)
  Write the Python string data to the audio device and return the
  number of bytes written. If the audio device is in blocking mode
  (the default), the entire string is always written

[1] https://docs.python.org/3.4/library/ossaudiodev.html


The comments in Modules/ossaudiodev.c suggest that dsp.write(data) should
write *all* data unless dsp.nonblock() is called:

    /* Open with O_NONBLOCK to avoid hanging on devices that only allow
       one open at a time.  This does *not* affect later I/O; OSS
       provides a special ioctl() for non-blocking read/write, which is
       exposed via oss_nonblock() below. */
    fd = _Py_open(devicename, imode|O_NONBLOCK);
    ...
    /* And (try to) put it back in blocking mode so we get the
       expected write() semantics. */
    if (fcntl(fd, F_SETFL, 0) == -1) {
        close(fd);
        PyErr_SetFromErrnoWithFilename(PyExc_IOError, devicename);
        return NULL;
    }
msg224160 - (view) Author: Akira Li (akira) * Date: 2014-07-28 10:35
From Modules/ossaudiodev.c:

    /* NB. writeall() is only useful in non-blocking mode: according to
       Guenter Geiger <geiger@xdv.org> on the linux-audio-dev list
       (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that
       write() in blocking mode consumes the whole buffer.  In blocking
       mode, the behaviour of write() and writeall() from Python is
       indistinguishable. */
msg236573 - (view) Author: Alex Shkop (ashkop) * Date: 2015-02-25 12:56
It seems to me that OSS device doesn't accept more than SNDCTL_DSP_GETOSPACE. Looks like this depends on OSS version because OSS docs state that since 4.x one shouldn't use SNDCTL_DSP_GETOSPACE at all [http://manuals.opensound.com/developer/SNDCTL_DSP_GETOSPACE.html].

I have OSS 3.8.2 and I can reproduce the bug. Can someone with OSS >= 4.0 confirm that dsp.write() works as expected?
msg415067 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2022-03-13 17:52
ossaudiodev is deprecated as per PEP 594, so there won't be further enhancements to it.
History
Date User Action Args
2022-04-11 14:58:06adminsetgithub: 66292
2022-03-13 17:52:33iritkatrielsetstatus: open -> closed

nosy: + iritkatriel
messages: + msg415067

resolution: wont fix
stage: resolved
2015-02-25 12:56:23ashkopsetnosy: + ashkop
messages: + msg236573
2014-07-28 10:48:57akirasetcomponents: + Library (Lib), - Tests
2014-07-28 10:35:40akirasetmessages: + msg224160
2014-07-28 10:30:16akirasettitle: test_ossaudiodev fails unnecessarily -> oss_audio_device.write(data) produces short writes
2014-07-28 10:29:20akiracreate