// File: Themaister[P]umusd/alsa.cpp
// Function: ALSA::init(unsigned int, unsigned int, FF::MediaInfo::Format, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
void ALSA::init(unsigned channels, unsigned rate,
      FF::MediaInfo::Format fmt,
      const std::string &dev)
{
   stop();

   try
   {
      TRY(snd_pcm_open(&pcm, dev.c_str(), SND_PCM_STREAM_PLAYBACK, 0),
            "Failed to open device.\n");

      snd_pcm_hw_params_t *params;
      snd_pcm_hw_params_alloca(&params);

      TRY(snd_pcm_hw_params_any(pcm, params),
            "Failed to set initial params.\n");

      TRY(snd_pcm_hw_params_set_access(pcm, params,
               SND_PCM_ACCESS_RW_INTERLEAVED),
            "Failed to set RW access.\n");

      snd_pcm_format_t format;
      switch (fmt)
      {
         case FF::MediaInfo::Format::S16:
            format = SND_PCM_FORMAT_S16;
            break;
         case FF::MediaInfo::Format::S32:
            format = SND_PCM_FORMAT_S32;
            break;
         case FF::MediaInfo::Format::Float:
            format = SND_PCM_FORMAT_FLOAT;
            break;
         default:
            format = SND_PCM_FORMAT_UNKNOWN;
            break;
      }

      TRY(snd_pcm_hw_params_set_format(pcm, params,
               format),
            "Failed to set sample format.\n");

      TRY(snd_pcm_hw_params_set_channels(pcm, params,
               channels),
            "Failed to set number of channels.\n");

      TRY(snd_pcm_hw_params_set_rate(pcm, params, rate, 0),
            "Failed to set sampling rate.\n");

      unsigned usec = 500000;
      unsigned periods = 4;
      TRY(snd_pcm_hw_params_set_buffer_time_near(pcm, params,
               &usec, nullptr),
            "Failed to set buffer time.\n");

      TRY(snd_pcm_hw_params_set_periods_near(pcm, params,
               &periods, nullptr),
            "Failed to set periods.\n");

      TRY(snd_pcm_hw_params(pcm, params),
            "Failed to install params.\n");

      fds.resize(snd_pcm_poll_descriptors_count(pcm));
      snd_pcm_poll_descriptors(pcm, fds.data(), fds.size());
   }
   catch(...)
   {
      stop();
      throw;
   }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl %ecx, -0x14(%rbp)
movq %r8, -0x20(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x58(%rbp)
movq (%rdi), %rax
movq 0x40(%rax), %rax
callq *%rax
movq -0x58(%rbp), %rax
addq $0x30, %rax
movq %rax, -0x50(%rbp)
movq -0x20(%rbp), %rdi
callq 0x5460
movq -0x50(%rbp), %rdi
movq %rax, %rsi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x52e0
movl %eax, -0x48(%rbp)
jmp 0x5c47
movl -0x48(%rbp), %eax
cmpl $0x0, %eax
jge 0x5cb8
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x60(%rbp)
leaq 0x203a2(%rip), %rsi     # 0x2600c
callq 0x5140
jmp 0x5c71
movq -0x60(%rbp), %rdi
movq 0x35314(%rip), %rsi     # 0x3af90
movq 0x3535d(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6199
movq -0x60(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
jmp 0x5cba
callq 0x54e0
movq %rax, -0x68(%rbp)
jmp 0x5cc5
movq -0x68(%rbp), %rcx
addq $0xf, %rcx
andq $-0x10, %rcx
movq %rsp, %rax
subq %rcx, %rax
movq %rax, %rsp
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x78(%rbp)
callq 0x54e0
movq %rax, -0x70(%rbp)
jmp 0x5cf1
movq -0x70(%rbp), %rdx
movq -0x78(%rbp), %rdi
xorl %esi, %esi
callq 0x5170
jmp 0x5d02
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
callq 0x51f0
movl %eax, -0x7c(%rbp)
jmp 0x5d18
movl -0x7c(%rbp), %eax
cmpl $0x0, %eax
jge 0x5d81
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x88(%rbp)
leaq 0x202e6(%rip), %rsi     # 0x26024
callq 0x5140
jmp 0x5d45
movq -0x88(%rbp), %rdi
movq 0x3523d(%rip), %rsi     # 0x3af90
movq 0x35286(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0x88(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
movl $0x3, %edx
callq 0x53c0
movl %eax, -0x8c(%rbp)
jmp 0x5d9f
movl -0x8c(%rbp), %eax
cmpl $0x0, %eax
jge 0x5e0b
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x98(%rbp)
leaq 0x2027b(%rip), %rsi     # 0x26043
callq 0x5140
jmp 0x5dcf
movq -0x98(%rbp), %rdi
movq 0x351b3(%rip), %rsi     # 0x3af90
movq 0x351fc(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0x98(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movl -0x14(%rbp), %eax
movl %eax, -0x9c(%rbp)
subl $0x1, %eax
je 0x5e35
jmp 0x5e1b
movl -0x9c(%rbp), %eax
subl $0x2, %eax
je 0x5e3e
jmp 0x5e28
movl -0x9c(%rbp), %eax
subl $0x3, %eax
je 0x5e47
jmp 0x5e50
movl $0x2, -0x3c(%rbp)
jmp 0x5e57
movl $0xa, -0x3c(%rbp)
jmp 0x5e57
movl $0xe, -0x3c(%rbp)
jmp 0x5e57
movl $0xffffffff, -0x3c(%rbp) # imm = 0xFFFFFFFF
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
movl -0x3c(%rbp), %edx
callq 0x56c0
movl %eax, -0xa0(%rbp)
jmp 0x5e73
movl -0xa0(%rbp), %eax
cmpl $0x0, %eax
jge 0x5edf
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa8(%rbp)
leaq 0x201c1(%rip), %rsi     # 0x2605d
callq 0x5140
jmp 0x5ea3
movq -0xa8(%rbp), %rdi
movq 0x350df(%rip), %rsi     # 0x3af90
movq 0x35128(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xa8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
movl -0xc(%rbp), %edx
callq 0x5130
movl %eax, -0xac(%rbp)
jmp 0x5efb
movl -0xac(%rbp), %eax
cmpl $0x0, %eax
jge 0x5f67
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb8(%rbp)
leaq 0x20157(%rip), %rsi     # 0x2607b
callq 0x5140
jmp 0x5f2b
movq -0xb8(%rbp), %rdi
movq 0x35057(%rip), %rsi     # 0x3af90
movq 0x350a0(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xb8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
movl -0x10(%rbp), %edx
xorl %ecx, %ecx
callq 0x5280
movl %eax, -0xbc(%rbp)
jmp 0x5f85
movl -0xbc(%rbp), %eax
cmpl $0x0, %eax
jge 0x5ff1
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc8(%rbp)
leaq 0x200f0(%rip), %rsi     # 0x2609e
callq 0x5140
jmp 0x5fb5
movq -0xc8(%rbp), %rdi
movq 0x34fcd(%rip), %rsi     # 0x3af90
movq 0x35016(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movl $0x7a120, -0x40(%rbp)   # imm = 0x7A120
movl $0x4, -0x44(%rbp)
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x40(%rbp), %rdx
callq 0x5270
movl %eax, -0xcc(%rbp)
jmp 0x6020
movl -0xcc(%rbp), %eax
cmpl $0x0, %eax
jge 0x608c
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd8(%rbp)
leaq 0x20073(%rip), %rsi     # 0x260bc
callq 0x5140
jmp 0x6050
movq -0xd8(%rbp), %rdi
movq 0x34f32(%rip), %rsi     # 0x3af90
movq 0x34f7b(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x44(%rbp), %rdx
callq 0x57b0
movl %eax, -0xdc(%rbp)
jmp 0x60ad
movl -0xdc(%rbp), %eax
cmpl $0x0, %eax
jge 0x6119
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
leaq 0x20002(%rip), %rsi     # 0x260d8
callq 0x5140
jmp 0x60dd
movq -0xe8(%rbp), %rdi
movq 0x34ea5(%rip), %rsi     # 0x3af90
movq 0x34eee(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
jmp 0x6199
movq -0x58(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x38(%rbp), %rsi
callq 0x55e0
movl %eax, -0xec(%rbp)
jmp 0x6132
movl -0xec(%rbp), %eax
cmpl $0x0, %eax
jge 0x61bb
movl $0x10, %edi
callq 0x5540
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xf8(%rbp)
leaq 0x1ff95(%rip), %rsi     # 0x260f0
callq 0x5140
jmp 0x6162
movq -0xf8(%rbp), %rdi
movq 0x34e20(%rip), %rsi     # 0x3af90
movq 0x34e69(%rip), %rdx     # 0x3afe0
callq 0x5260
jmp 0x626b
movq -0xf8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x56d0
movq -0x28(%rbp), %rdi
callq 0x5080
movq -0x58(%rbp), %rdi
movq (%rdi), %rax
movq 0x40(%rax), %rax
callq *%rax
jmp 0x61b1
callq 0x5690
jmp 0x626b
movq -0x58(%rbp), %rax
movq %rax, %rcx
addq $0x38, %rcx
movq %rcx, -0x108(%rbp)
movq 0x30(%rax), %rdi
callq 0x5310
movl %eax, -0xfc(%rbp)
jmp 0x61de
movq -0x108(%rbp), %rdi
movl -0xfc(%rbp), %eax
movslq %eax, %rsi
callq 0x6880
jmp 0x61f5
movq -0x58(%rbp), %rdi
movq 0x30(%rdi), %rax
movq %rax, -0x118(%rbp)
addq $0x38, %rdi
movq %rdi, -0x120(%rbp)
callq 0x6910
movq -0x120(%rbp), %rdi
movq %rax, -0x110(%rbp)
callq 0x6930
movq -0x118(%rbp), %rdi
movq -0x110(%rbp), %rsi
movl %eax, %edx
callq 0x5210
jmp 0x623e
jmp 0x6255
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x5660
jmp 0x6253
jmp 0x625a
movq %rbp, %rsp
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x52a0
movq %rax, %rdi
callq 0x6700
nopl (%rax,%rax)