// File: /workspace/github_cpp_makefile_star2_O2/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 0x6fa1
movq %rdi, %rbx
leal -0x3(%rcx), %eax
cmpl $-0x3, %eax
ja 0x6f98
addq $0x180, %rbx            # imm = 0x180
leaq 0x2ae9(%rip), %rsi      # 0x9a77
movq %rbx, %rdi
callq 0x43e0
jmp 0x6fa1
movb %cl, 0x2c(%rsp)
testl %r8d, %r8d
je 0x6fb4
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xb0(%rsp), %r14
movq 0xa8(%rsp), %r15
movq 0xa0(%rsp), %rax
leaq 0x24cd(%rip), %rdx      # 0x94a0
movl (%rdx), %esi
testl %esi, %esi
je 0x7037
addq $0x4, %rdx
cmpl %r9d, %esi
jne 0x6fd3
movl %r9d, 0x1e0(%rbx)
movl %r9d, 0x28(%rsp)
leaq 0x24cb(%rip), %rdi      # 0x94c0
pushq $0x5
popq %rdx
pushq $0x10
popq %rsi
movq (%rdi), %r8
testq %r8, %r8
je 0x7012
addq $0x10, %rdi
cmpq %rax, %r8
jne 0x6ffb
movl -0x8(%rdi), %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 0x7033
testb $0x1, (%r14)
jne 0x704a
movb $0x1, %al
jmp 0x704c
addq $0x180, %rbx            # imm = 0x180
leaq 0x2a6f(%rip), %rsi      # 0x9ab4
jmp 0x6f8e
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)
andl $0x0, 0x1fc(%rbx,%r13,4)
leaq 0x2a5c(%rip), %rsi      # 0x9aea
leaq 0x30(%rsp), %rdi
leaq 0x1f(%rsp), %rdx
callq 0x77ae
movq 0x220(%rbx,%r13,8), %rax
cmpq %rax, 0x218(%rbx)
setne %al
movl 0x1ec(%rbx,%r13,4), %r12d
cmpl 0x1f4(%rbx,%r13,4), %r12d
setb %cl
orb %al, %cl
movb %cl, 0x1d8(%rbx,%r13)
movl (%r15), %r15d
movq 0x218(%rbx), %rsi
movq %rbx, %rdi
callq 0x5564
imull %r12d, %r15d
imull %eax, %r15d
pushq $0x1
popq %rsi
movq %r15, %rdi
callq 0x4120
movq %rax, 0x1c0(%rbx,%r13,8)
testq %rax, %rax
je 0x7259
movq 0xa8(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x1e4(%rbx)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x71b3
movl 0x1f4(%rbx,%r13,4), %r12d
movq 0x220(%rbx,%r13,8), %rsi
movq %rbx, %rdi
callq 0x5564
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 0x7185
movl 0x1f4(%rbx), %r12d
movq 0x220(%rbx), %rsi
movq %rbx, %rdi
callq 0x5564
imull %r12d, %eax
cmpl %eax, %r15d
jbe 0x71b3
movq 0x1d0(%rbx), %rdi
movq 0xa8(%rsp), %rax
movl (%rax), %eax
imulq %rax, %r15
callq 0x4220
pushq $0x1
popq %rsi
movq %r15, %rdi
callq 0x4120
movq %rax, 0x1d0(%rbx)
testq %rax, %rax
je 0x7358
andl $0x0, 0x1a8(%rbx,%r13,4)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x71d3
movq %rbx, %rdi
movl %ebp, %esi
xorl %edx, %edx
callq 0x7420
movq 0x1b0(%rbx), %r12
testq %r12, %r12
je 0x7306
testq %r14, %r14
je 0x7200
cmpq $0x0, 0x10(%r14)
je 0x7200
addq $0x8, %r14
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x4100
testb $0x1, %bpl
je 0x7271
leaq 0x54(%rsp), %rax
movl %r15d, 0x10(%rax)
orl $-0x1, (%rax)
movq 0x30(%rsp), %rsi
leaq 0x20(%rsp), %rcx
movq %rcx, 0x10(%rsp)
movq %rax, 0x8(%rsp)
andq $0x0, (%rsp)
leaq 0x2986(%rip), %r8       # 0x9bb8
pushq $0x2
popq %rdx
leaq 0x24(%rsp), %r9
xorl %edi, %edi
xorl %ecx, %ecx
callq 0x41b0
movq %rax, 0x8(%r12)
testq %rax, %rax
jne 0x72ac
leaq 0x296b(%rip), %rsi      # 0x9bbf
jmp 0x7374
leaq 0x180(%rbx), %rdi
leaq 0x288b(%rip), %rsi      # 0x9af2
callq 0x43e0
jmp 0x73a6
movq 0x30(%rsp), %rsi
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, (%rsp)
leaq 0x297b(%rip), %r8       # 0x9c09
pushq $0x1
popq %rdx
leaq 0x24(%rsp), %r9
xorl %edi, %edi
xorl %ecx, %ecx
callq 0x41b0
movq %rax, (%r12)
testq %rax, %rax
je 0x736d
movl 0x1b8(%rbx), %eax
cmpl $-0x4b, %eax
je 0x72c2
cmpl %ebp, %eax
je 0x7380
pushq $0x2
popq %rbp
movl %ebp, 0x1b8(%rbx)
cmpb $0x0, 0x288(%rbx)
jne 0x734a
leaq 0x258(%rbx), %rcx
movq %rbx, 0x258(%rbx)
movb $0x1, 0x288(%rbx)
leaq 0x10(%r12), %rdi
leaq 0x3e4(%rip), %rdx       # 0x76d6
xorl %esi, %esi
callq 0x43c0
testl %eax, %eax
je 0x734a
leaq 0x2959(%rip), %rsi      # 0x9c5d
jmp 0x7374
pushq $0x50
popq %rdi
callq 0x41d0
movb $0x0, 0x48(%rax)
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq %rax, 0x1b0(%rbx)
addq $0x18, %rax
movq %rax, %rdi
xorl %esi, %esi
callq 0x4230
testl %eax, %eax
je 0x73f9
leaq 0x180(%rbx), %rdi
leaq 0x2835(%rip), %rsi      # 0x9b78
callq 0x43e0
jmp 0x73a6
andl $0x0, 0x1bc(%rbx)
movb $0x1, %bl
jmp 0x73ea
leaq 0x180(%rbx), %rdi
leaq 0x27ce(%rip), %rsi      # 0x9b34
callq 0x43e0
jmp 0x73a6
leaq 0x289e(%rip), %rsi      # 0x9c12
leaq 0x180(%rbx), %rdi
callq 0x43e0
cmpb $0x1, 0x288(%rbx)
jne 0x73a6
leaq 0x18(%r12), %rdi
callq 0x43f0
pushq $0x50
popq %rsi
movq %r12, %rdi
callq 0x41e0
andq $0x0, 0x1b0(%rbx)
xorl %r14d, %r14d
cmpq $0x2, %r14
je 0x73cf
movq 0x1c0(%rbx,%r14,8), %rdi
testq %rdi, %rdi
je 0x73ca
callq 0x4220
andq $0x0, 0x1c0(%rbx,%r14,8)
incq %r14
jmp 0x73a9
movq 0x1d0(%rbx), %rdi
testq %rdi, %rdi
je 0x73e8
callq 0x4220
andq $0x0, 0x1d0(%rbx)
xorl %ebx, %ebx
leaq 0x30(%rsp), %rdi
callq 0x40c0
jmp 0x6fa3
movq 0x1b0(%rbx), %r12
jmp 0x71e3
jmp 0x740b
jmp 0x740b
jmp 0x740b
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x40c0
movq %rbx, %rdi
callq 0x4390