// File: /workspace/github_cpp_makefile_star2_O3/tobias93[P]piano/rtaudio/RtAudio.cpp
// Function: RtApiPulse::probeDeviceOpen(unsigned int, RtApi::StreamMode, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int*, RtAudio::StreamOptions*)
bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,
                                  unsigned int channels, unsigned int firstChannel,
                                  unsigned int sampleRate, RtAudioFormat format,
                                  unsigned int *bufferSize, RtAudio::StreamOptions *options )
{
  PulseAudioHandle *pah = 0;
  unsigned long bufferBytes = 0;
  pa_sample_spec ss;

  if ( device != 0 ) return false;
  if ( mode != INPUT && mode != OUTPUT ) return false;
  if ( channels != 1 && channels != 2 ) {
    errorText_ = "RtApiPulse::probeDeviceOpen: unsupported number of channels.";
    return false;
  }
  ss.channels = channels;

  if ( firstChannel != 0 ) return false;

  bool sr_found = false;
  for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) {
    if ( sampleRate == *sr ) {
      sr_found = true;
      stream_.sampleRate = sampleRate;
      ss.rate = sampleRate;
      break;
    }
  }
  if ( !sr_found ) {
    errorText_ = "RtApiPulse::probeDeviceOpen: unsupported sample rate.";
    return false;
  }

  bool sf_found = 0;
  for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats;
        sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) {
    if ( format == sf->rtaudio_format ) {
      sf_found = true;
      stream_.userFormat = sf->rtaudio_format;
      stream_.deviceFormat[mode] = stream_.userFormat;
      ss.format = sf->pa_format;
      break;
    }
  }
  if ( !sf_found ) { // Use internal data format conversion.
    stream_.userFormat = format;
    stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;
    ss.format = PA_SAMPLE_FLOAT32LE;
  }

  // Set other stream parameters.
  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
  else stream_.userInterleaved = true;
  stream_.deviceInterleaved[mode] = true;
  stream_.nBuffers = 1;
  stream_.doByteSwap[mode] = false;
  stream_.nUserChannels[mode] = channels;
  stream_.nDeviceChannels[mode] = channels + firstChannel;
  stream_.channelOffset[mode] = 0;
  std::string streamName = "RtAudio";

  // Set flags for buffer conversion.
  stream_.doConvertBuffer[mode] = false;
  if ( stream_.userFormat != stream_.deviceFormat[mode] )
    stream_.doConvertBuffer[mode] = true;
  if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )
    stream_.doConvertBuffer[mode] = true;

  // Allocate necessary internal buffers.
  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
  if ( stream_.userBuffer[mode] == NULL ) {
    errorText_ = "RtApiPulse::probeDeviceOpen: error allocating user buffer memory.";
    goto error;
  }
  stream_.bufferSize = *bufferSize;

  if ( stream_.doConvertBuffer[mode] ) {

    bool makeBuffer = true;
    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
    if ( mode == INPUT ) {
      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
        if ( bufferBytes <= bytesOut ) makeBuffer = false;
      }
    }

    if ( makeBuffer ) {
      bufferBytes *= *bufferSize;
      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
      if ( stream_.deviceBuffer == NULL ) {
        errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory.";
        goto error;
      }
    }
  }

  stream_.device[mode] = device;

  // Setup the buffer conversion information structure.
  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );

  if ( !stream_.apiHandle ) {
    PulseAudioHandle *pah = new PulseAudioHandle;
    if ( !pah ) {
      errorText_ = "RtApiPulse::probeDeviceOpen: error allocating memory for handle.";
      goto error;
    }

    stream_.apiHandle = pah;
    if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) {
      errorText_ = "RtApiPulse::probeDeviceOpen: error creating condition variable.";
      goto error;
    }
  }
  pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );

  int error;
  if ( options && !options->streamName.empty() ) streamName = options->streamName;
  switch ( mode ) {
  case INPUT:
    pa_buffer_attr buffer_attr;
    buffer_attr.fragsize = bufferBytes;
    buffer_attr.maxlength = -1;

    pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD, NULL, "Record", &ss, NULL, &buffer_attr, &error );
    if ( !pah->s_rec ) {
      errorText_ = "RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server.";
      goto error;
    }
    break;
  case OUTPUT:
    pah->s_play = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_PLAYBACK, NULL, "Playback", &ss, NULL, NULL, &error );
    if ( !pah->s_play ) {
      errorText_ = "RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.";
      goto error;
    }
    break;
  default:
    goto error;
  }

  if ( stream_.mode == UNINITIALIZED )
    stream_.mode = mode;
  else if ( stream_.mode == mode )
    goto error;
  else
    stream_.mode = DUPLEX;

  if ( !stream_.callbackInfo.isRunning ) {
    stream_.callbackInfo.object = this;
    stream_.callbackInfo.isRunning = true;
    if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) {
      errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread.";
      goto error;
    }
  }

  stream_.state = STREAM_STOPPED;
  return true;
 
 error:
  if ( pah && stream_.callbackInfo.isRunning ) {
    pthread_cond_destroy( &pah->runnable_cv );
    delete pah;
    stream_.apiHandle = 0;
  }

  for ( int i=0; i<2; i++ ) {
    if ( stream_.userBuffer[i] ) {
      free( stream_.userBuffer[i] );
      stream_.userBuffer[i] = 0;
    }
  }

  if ( stream_.deviceBuffer ) {
    free( stream_.deviceBuffer );
    stream_.deviceBuffer = 0;
  }

  return FAILURE;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %edx, %ebp
testl %esi, %esi
setne %al
cmpl $0x2, %edx
setae %dl
orb %al, %dl
jne 0x76d1
movq %rdi, %rbx
leal -0x3(%rcx), %eax
cmpl $-0x3, %eax
ja 0x76c8
movq 0x188(%rbx), %rdx
addq $0x180, %rbx            # imm = 0x180
leaq 0x23c4(%rip), %rcx      # 0x9a77
xorl %r14d, %r14d
movl $0x3c, %r8d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x4310
jmp 0x76d4
movb %cl, 0x2c(%rsp)
testl %r8d, %r8d
je 0x76e6
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xb0(%rsp), %r14
movq 0xa8(%rsp), %r12
movq 0xa0(%rsp), %rax
movl $0x1f40, %esi           # imm = 0x1F40
leaq 0x1d9a(%rip), %rdx      # 0x94a4
cmpl %r9d, %esi
je 0x7739
movl (%rdx), %esi
addq $0x4, %rdx
testl %esi, %esi
jne 0x770a
movq 0x188(%rbx), %rdx
addq $0x180, %rbx            # imm = 0x180
leaq 0x2386(%rip), %rcx      # 0x9ab4
xorl %r14d, %r14d
movl $0x35, %r8d
jmp 0x76bc
movl %r9d, 0x1e0(%rbx)
movl %r9d, 0x28(%rsp)
movl $0x2, %esi
leaq 0x1d7f(%rip), %rdx      # 0x94d0
cmpq %rax, %rsi
je 0x776e
movq (%rdx), %rsi
addq $0x10, %rdx
testq %rsi, %rsi
jne 0x7751
movl $0x5, %edx
movl $0x10, %esi
jmp 0x7774
movl -0x8(%rdx), %edx
movq %rax, %rsi
movq %rax, 0x218(%rbx)
movl %ebp, %r13d
movq %rsi, 0x220(%rbx,%r13,8)
movl %edx, 0x24(%rsp)
testq %r14, %r14
je 0x7795
testb $0x1, (%r14)
jne 0x7799
movb $0x1, %al
jmp 0x779b
xorl %eax, %eax
movb %al, 0x1da(%rbx)
movb $0x1, 0x1db(%rbx,%r13)
movl $0x1, 0x1e8(%rbx)
movb $0x0, 0x1dd(%rbx,%r13)
movl %ecx, 0x1ec(%rbx,%r13,4)
movl %ecx, 0x1f4(%rbx,%r13,4)
movl $0x0, 0x1fc(%rbx,%r13,4)
leaq 0x40(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x2301(%rip), %rsi      # 0x9aea
leaq 0x2301(%rip), %rdx      # 0x9af1
leaq 0x30(%rsp), %rdi
callq 0x8298
movq 0x220(%rbx,%r13,8), %rax
cmpq %rax, 0x218(%rbx)
setne %al
movl 0x1ec(%rbx,%r13,4), %r15d
cmpl 0x1f4(%rbx,%r13,4), %r15d
setb %cl
orb %al, %cl
movb %cl, 0x1d8(%rbx,%r13)
movl (%r12), %r12d
movq 0x218(%rbx), %rsi
movq %rbx, %rdi
callq 0x582a
imull %r15d, %r12d
imull %eax, %r12d
movl $0x1, %esi
movq %r12, %rdi
callq 0x4120
movq %rax, 0x1c0(%rbx,%r13,8)
testq %rax, %rax
je 0x792f
movq 0xa8(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x1e4(%rbx)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x794a
movl 0x1f4(%rbx,%r13,4), %r12d
movq 0x220(%rbx,%r13,8), %rsi
movq %rbx, %rdi
callq 0x582a
movl %eax, %r15d
imull %r12d, %r15d
movl %ebp, %eax
xorl $0x1, %eax
orl 0x1b8(%rbx), %eax
setne %al
movq 0x1d0(%rbx), %rdi
testq %rdi, %rdi
sete %cl
orb %al, %cl
jne 0x78e5
movl 0x1f4(%rbx), %r12d
movq 0x220(%rbx), %rsi
movq %rbx, %rdi
callq 0x582a
imull %r12d, %eax
cmpl %eax, %r15d
jbe 0x7947
movq 0x1d0(%rbx), %rdi
movq 0xa8(%rsp), %rax
movl (%rax), %r12d
imulq %r15, %r12
testq %rdi, %rdi
je 0x78fe
callq 0x4230
movl $0x1, %esi
movq %r12, %rdi
callq 0x4120
movq %rax, 0x1d0(%rbx)
testq %rax, %rax
jne 0x794a
leaq 0x180(%rbx), %rdi
leaq 0x220f(%rip), %rsi      # 0x9b34
callq 0x4280
jmp 0x7b2b
leaq 0x180(%rbx), %rdi
leaq 0x21b5(%rip), %rsi      # 0x9af2
callq 0x4280
jmp 0x7b2b
movq %r15, %r12
movl $0x0, 0x1a8(%rbx,%r13,4)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x796d
movq %rbx, %rdi
movl %ebp, %esi
xorl %edx, %edx
callq 0x7bde
movq 0x1b0(%rbx), %r15
testq %r15, %r15
je 0x7a91
testq %r14, %r14
je 0x799a
cmpq $0x0, 0x10(%r14)
je 0x799a
addq $0x8, %r14
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x4100
testb $0x1, %bpl
je 0x79fa
leaq 0x54(%rsp), %rax
movl %r12d, 0x10(%rax)
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movq 0x30(%rsp), %rsi
leaq 0x20(%rsp), %rcx
movq %rcx, 0x10(%rsp)
movq %rax, 0x8(%rsp)
movq $0x0, (%rsp)
leaq 0x21e6(%rip), %r8       # 0x9bb8
leaq 0x24(%rsp), %r9
xorl %edi, %edi
movl $0x2, %edx
xorl %ecx, %ecx
callq 0x41b0
movq %rax, 0x8(%r15)
testq %rax, %rax
jne 0x7a36
leaq 0x21ca(%rip), %rsi      # 0x9bbf
jmp 0x7af5
movq 0x30(%rsp), %rsi
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, (%rsp)
leaq 0x21f2(%rip), %r8       # 0x9c09
leaq 0x24(%rsp), %r9
xorl %edi, %edi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x41b0
movq %rax, (%r15)
testq %rax, %rax
je 0x7aee
movl 0x1b8(%rbx), %eax
cmpl $-0x4b, %eax
je 0x7a4e
cmpl %ebp, %eax
movl $0x2, %ebp
je 0x7b01
movl %ebp, 0x1b8(%rbx)
cmpb $0x0, 0x288(%rbx)
jne 0x7ad7
leaq 0x258(%rbx), %rcx
movq %rbx, 0x258(%rbx)
movb $0x1, 0x288(%rbx)
leaq 0x10(%r15), %rdi
leaq 0x537(%rip), %rdx       # 0x7fb4
xorl %esi, %esi
callq 0x43e0
testl %eax, %eax
je 0x7ad7
leaq 0x21ce(%rip), %rsi      # 0x9c5d
jmp 0x7af5
movl $0x50, %edi
callq 0x41e0
movb $0x0, 0x48(%rax)
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq %rax, 0x1b0(%rbx)
addq $0x18, %rax
movq %rax, %rdi
xorl %esi, %esi
callq 0x4240
testl %eax, %eax
je 0x7ba4
leaq 0x180(%rbx), %rdi
leaq 0x20a8(%rip), %rsi      # 0x9b78
callq 0x4280
jmp 0x7b2b
movl $0x0, 0x1bc(%rbx)
movb $0x1, %r14b
leaq 0x40(%rsp), %r15
jmp 0x7b84
leaq 0x211d(%rip), %rsi      # 0x9c12
leaq 0x180(%rbx), %rdi
callq 0x4280
cmpb $0x0, 0x288(%rbx)
je 0x7b2b
leaq 0x18(%r15), %rdi
callq 0x4400
movl $0x50, %esi
movq %r15, %rdi
callq 0x41f0
movq $0x0, 0x1b0(%rbx)
movb $0x1, %bpl
xorl %r14d, %r14d
leaq 0x40(%rsp), %r15
movq 0x1c0(%rbx,%r14,8), %rdi
testq %rdi, %rdi
je 0x7b54
callq 0x4230
movq $0x0, 0x1c0(%rbx,%r14,8)
movl $0x1, %r14d
testb $0x1, %bpl
movl $0x0, %ebp
jne 0x7b36
movq 0x1d0(%rbx), %rdi
testq %rdi, %rdi
je 0x7b81
callq 0x4230
movq $0x0, 0x1d0(%rbx)
xorl %r14d, %r14d
movq 0x30(%rsp), %rdi
cmpq %r15, %rdi
je 0x76d4
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x41f0
jmp 0x76d4
movq 0x1b0(%rbx), %r15
jmp 0x797d
jmp 0x7bb6
jmp 0x7bb6
jmp 0x7bb6
movq %rax, %rbx
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x7bd5
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x41f0
movq %rbx, %rdi
callq 0x43b0
nop