// File: /workspace/github_cpp_makefile_star2_O1/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 0x7659
movq %rdi, %rbx
leal -0x3(%rcx), %eax
cmpl $-0x3, %eax
ja 0x7650
movq 0x188(%rbx), %rdx
addq $0x180, %rbx            # imm = 0x180
leaq 0x243c(%rip), %rcx      # 0x9a77
xorl %r14d, %r14d
movl $0x3c, %r8d
movq %rbx, %rdi
xorl %esi, %esi
callq 0x4310
jmp 0x765c
movb %cl, 0x2c(%rsp)
testl %r8d, %r8d
je 0x766e
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 0xa0(%rsp), %rax
movl $0x1f40, %esi           # imm = 0x1F40
leaq 0x1e1a(%rip), %rdx      # 0x94a4
cmpl %r9d, %esi
je 0x76b9
movl (%rdx), %esi
addq $0x4, %rdx
testl %esi, %esi
jne 0x768a
movq 0x188(%rbx), %rdx
addq $0x180, %rbx            # imm = 0x180
leaq 0x2406(%rip), %rcx      # 0x9ab4
xorl %r14d, %r14d
movl $0x35, %r8d
jmp 0x7644
movl %r9d, 0x1e0(%rbx)
movl %r9d, 0x28(%rsp)
movl $0x2, %edx
leaq 0x1dff(%rip), %rsi      # 0x94d0
cmpq %rax, %rdx
je 0x76ee
movq (%rsi), %rdx
addq $0x10, %rsi
testq %rdx, %rdx
jne 0x76d1
movl $0x5, %esi
movl $0x10, %edx
jmp 0x76f4
movl -0x8(%rsi), %esi
movq %rdx, %rax
movq %rax, 0x218(%rbx)
movl %ebp, %r13d
movq %rdx, 0x220(%rbx,%r13,8)
movl %esi, 0x24(%rsp)
testq %r14, %r14
je 0x7715
testb $0x1, (%r14)
jne 0x7719
movb $0x1, %al
jmp 0x771b
xorl %eax, %eax
movb %al, 0x1da(%rbx)
movb $0x1, 0x1db(%rbx,%r13)
movl $0x1, %r15d
movl %r15d, 0x1e8(%rbx)
xorl %r12d, %r12d
movb %r12b, 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 0x237c(%rip), %rsi      # 0x9aea
leaq 0x237c(%rip), %rdx      # 0x9af1
leaq 0x30(%rsp), %rdi
callq 0x8252
movb %r12b, 0x1d8(%rbx,%r13)
movq 0x218(%rbx), %rax
xorl %ecx, %ecx
cmpq 0x220(%rbx,%r13,8), %rax
setne %cl
setne 0x1d8(%rbx,%r13)
movl 0x1ec(%rbx,%r13,4), %r12d
cmpl 0x1f4(%rbx,%r13,4), %r12d
cmovbl %r15d, %ecx
movb %cl, 0x1d8(%rbx,%r13)
movq 0xa8(%rsp), %rax
movl (%rax), %r15d
movq 0x218(%rbx), %rsi
movq %rbx, %rdi
callq 0x5800
imull %r12d, %r15d
imull %eax, %r15d
movl $0x1, %esi
movq %r15, %rdi
callq 0x4120
movq %rax, 0x1c0(%rbx,%r13,8)
testq %rax, %rax
je 0x78c9
movq 0xa8(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x1e4(%rbx)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x78ec
movl 0x1f4(%rbx,%r13,4), %r15d
movq 0x220(%rbx,%r13,8), %rsi
movq %rbx, %rdi
callq 0x5800
movl %eax, %r12d
imull %r15d, %r12d
cmpl $0x1, %ebp
jne 0x7877
cmpl $0x0, 0x1b8(%rbx)
jne 0x7877
cmpq $0x0, 0x1d0(%rbx)
je 0x7877
movl 0x1f4(%rbx), %r15d
movq 0x220(%rbx), %rsi
movq %rbx, %rdi
callq 0x5800
imull %r15d, %eax
movb $0x1, %cl
cmpl %eax, %r12d
jbe 0x78e1
movq 0xa8(%rsp), %rax
movl (%rax), %r15d
imulq %r12, %r15
movq 0x1d0(%rbx), %rdi
testq %rdi, %rdi
je 0x7897
callq 0x4230
movl $0x1, %esi
movq %r15, %rdi
callq 0x4120
movq %rax, 0x1d0(%rbx)
movb $0x1, %cl
testq %rax, %rax
jne 0x78e4
leaq 0x180(%rbx), %rdi
leaq 0x2274(%rip), %rsi      # 0x9b34
callq 0x4280
xorl %ecx, %ecx
jmp 0x78e4
leaq 0x180(%rbx), %rdi
leaq 0x221b(%rip), %rsi      # 0x9af2
callq 0x4280
jmp 0x7a8f
movq %r12, %r15
testb %cl, %cl
je 0x7a8f
movl $0x0, 0x1a8(%rbx,%r13,4)
cmpb $0x1, 0x1d8(%rbx,%r13)
jne 0x790f
movq %rbx, %rdi
movl %ebp, %esi
xorl %edx, %edx
callq 0x7b84
cmpq $0x0, 0x1b0(%rbx)
je 0x7a3f
movq 0x1b0(%rbx), %r12
testq %r14, %r14
je 0x7941
cmpq $0x0, 0x10(%r14)
je 0x7941
addq $0x8, %r14
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x4100
testb $0x1, %bpl
je 0x79a2
leaq 0x54(%rsp), %rax
movl %r15d, 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 0x223f(%rip), %r8       # 0x9bb8
leaq 0x24(%rsp), %r9
xorl %edi, %edi
movl $0x2, %edx
xorl %ecx, %ecx
callq 0x41b0
movq %rax, 0x8(%r12)
testq %rax, %rax
jne 0x79df
leaq 0x2222(%rip), %rsi      # 0x9bbf
jmp 0x7aad
movq 0x30(%rsp), %rsi
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
xorps %xmm0, %xmm0
movups %xmm0, (%rsp)
leaq 0x224a(%rip), %r8       # 0x9c09
leaq 0x24(%rsp), %r9
xorl %edi, %edi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x41b0
movq %rax, (%r12)
testq %rax, %rax
je 0x7aa6
movl 0x1b8(%rbx), %eax
cmpl $-0x4b, %eax
je 0x79f7
cmpl %ebp, %eax
movl $0x2, %ebp
je 0x7ab9
movl %ebp, 0x1b8(%rbx)
cmpb $0x0, 0x288(%rbx)
jne 0x7a94
leaq 0x258(%rbx), %rcx
movq %rbx, 0x258(%rbx)
movb $0x1, 0x288(%rbx)
leaq 0x10(%r12), %rdi
leaq 0x53d(%rip), %rdx       # 0x7f68
xorl %esi, %esi
callq 0x43e0
testl %eax, %eax
je 0x7a94
leaq 0x2220(%rip), %rsi      # 0x9c5d
jmp 0x7aad
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 0x791d
movl %eax, %r12d
leaq 0x180(%rbx), %rdi
leaq 0x20f7(%rip), %rsi      # 0x9b78
callq 0x4280
testl %r12d, %r12d
je 0x791d
xorl %r12d, %r12d
jmp 0x7ab9
movl $0x0, 0x1bc(%rbx)
movb $0x1, %r14b
jmp 0x7b32
leaq 0x2165(%rip), %rsi      # 0x9c12
leaq 0x180(%rbx), %rdi
callq 0x4280
testq %r12, %r12
je 0x7ae9
cmpb $0x1, 0x288(%rbx)
jne 0x7ae9
leaq 0x18(%r12), %rdi
callq 0x4400
movl $0x50, %esi
movq %r12, %rdi
callq 0x41f0
movq $0x0, 0x1b0(%rbx)
xorl %r14d, %r14d
movq 0x1c0(%rbx,%r14,8), %rdi
testq %rdi, %rdi
je 0x7b0a
callq 0x4230
movq $0x0, 0x1c0(%rbx,%r14,8)
incq %r14
cmpq $0x1, %r14
je 0x7aec
movq 0x1d0(%rbx), %rdi
testq %rdi, %rdi
je 0x7b2f
callq 0x4230
movq $0x0, 0x1d0(%rbx)
xorl %r14d, %r14d
leaq 0x40(%rsp), %rax
movq 0x30(%rsp), %rdi
cmpq %rax, %rdi
je 0x765c
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x41f0
jmp 0x765c
jmp 0x7b5d
jmp 0x7b5d
jmp 0x7b5d
movq %rax, %rbx
movq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rax
cmpq %rax, %rdi
je 0x7b7c
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x41f0
movq %rbx, %rdi
callq 0x43b0