bsd compatibility mods
[goodguy/history.git] / cinelerra-5.1 / cinelerra / audiooss.C
index f75ff0fbd7248f2eb7a95b020d9dfe710019bcf3..cb1fc0877dff906ea8413b5140522e0888f1872d 100644 (file)
@@ -80,6 +80,14 @@ OSSThread::~OSSThread()
 
 void OSSThread::run()
 {
+// this makes the longest (blocking) write 1024 samples
+//  if this is not done, the video can be jerky
+       AudioDevice *audio_device = device->device;
+       int frame_size = audio_device->get_ochannels() * audio_device->get_obits()/8;
+       int maxsz = 1024*frame_size, blksz = maxsz;
+       ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blksz);
+       if( blksz > maxsz ) blksz = maxsz;
+
        while(!done) {
                input_lock->lock("OSSThread::run 1");
                if(done) return;
@@ -88,11 +96,14 @@ void OSSThread::run()
                        read_lock->unlock();
                }
                else if(wr) {
+                       if( !bytes_written )
+                               timer->update();
                        int count = bytes;
                        unsigned char *bp = data;
-                       while( count > 0 ) {
+                       while( count > 0 && !done ) {
                                Thread::enable_cancel();
-                               int ret = write(fd, bp, bytes);
+                               int len = count>blksz ? blksz : count;
+                               int ret = write(fd, bp, len);
                                Thread::disable_cancel();
                                if( ret < 0 ) break;
                                bp += ret;
@@ -102,6 +113,7 @@ void OSSThread::run()
                                if( !ioctl(fd, SNDCTL_DSP_GETODELAY, &delay) )
                                        this->delay = delay;
                                bytes_written += ret;
+                               timer->update();
                                timer_lock->unlock();
                        }
                        write_lock->unlock();
@@ -347,6 +359,14 @@ int AudioOSS::set_cloexec_flag(int desc, int value)
 
 int64_t AudioOSS::device_position()
 {
+       for (int i = 0; i < MAXDEVICES; i++) {
+               if( thread[i] ) {
+                       int frame_size = device->get_ochannels() * device->get_obits()/8;
+                       int64_t pos = thread[i]->device_position() / frame_size;
+                       int64_t tmr = thread[i]->timer->get_scaled_difference(device->out_samplerate);
+                       return pos + tmr;
+               }
+       }
        count_info info;
        if(!ioctl(get_output(0), SNDCTL_DSP_GETOPTR, &info))
        {
@@ -355,16 +375,8 @@ int64_t AudioOSS::device_position()
 // the problem is that if the first write to sound device was not full lenght fragment then
 // _GETOPTR returns insanely large numbers at first moments of play
                if (info.bytes > 2100000000) return 0;
-               int frame = device->get_ochannels() * device->get_obits()/8;
-               return info.bytes / frame;
-       }
-       for (int i = 0; i < MAXDEVICES; i++)
-       {
-               if (thread[i])
-                       return thread[i]->device_position() /
-                               device->get_ochannels() /
-                               (device->get_obits()/8) +
-                               thread[i]->timer->get_scaled_difference(device->out_samplerate);
+               int frame_size = device->get_ochannels() * device->get_obits()/8;
+               return info.bytes / frame_size;
        }
        return 0;
 }
@@ -384,6 +396,17 @@ int AudioOSS::interrupt_playback()
        return 0;
 }
 
+int64_t AudioOSS::samples_output()
+{
+       for( int i=0; i<MAXDEVICES; ++i ) {
+               if( thread[i] ) {
+                       int frame_size = device->get_ochannels() * device->get_obits()/8;
+                       return thread[i]->bytes_written / frame_size;
+               }
+       }
+       return 0;
+}
+
 int AudioOSS::read_buffer(char *buffer, int bytes)
 {
        int sample_size = device->get_ibits() / 8;