// File: fulhax[P]ncpamixer/src/pa.cpp
// Function: Pa::subscribe_cb(pa_context*, pa_subscription_event_type, unsigned int, void*)
void Pa::subscribe_cb(pa_context *ctx, pa_subscription_event_type_t t,
                      uint32_t index, void *instance)
{

    int type = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK);
    Pa *pa = reinterpret_cast<Pa *>(instance);
    // https://freedesktop.org/software/pulseaudio/doxygen/def_8h.html#a6bedfa147a9565383f1f44642cfef6a3

    switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
        case PA_SUBSCRIPTION_EVENT_SINK: {
            if (type == PA_SUBSCRIPTION_EVENT_REMOVE) {
                pa->remove_paobject(&pa->PA_SINKS, index);
            } else if (type == PA_SUBSCRIPTION_EVENT_NEW ||
                       type == PA_SUBSCRIPTION_EVENT_CHANGE) {

                pa_operation *o = pa_context_get_sink_info_by_index(
                                      ctx,
                                      index,
                                      &Pa::ctx_sinklist_cb,
                                      instance
                                  );
                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;
        }

        case PA_SUBSCRIPTION_EVENT_SINK_INPUT: {

            if (type == PA_SUBSCRIPTION_EVENT_REMOVE) {
                pa->remove_paobject(&pa->PA_INPUTS, index);
            } else if (type == PA_SUBSCRIPTION_EVENT_NEW ||
                       type == PA_SUBSCRIPTION_EVENT_CHANGE) {

                pa_operation *o = pa_context_get_sink_input_info(
                                      ctx,
                                      index,
                                      &Pa::ctx_inputlist_cb,
                                      instance
                                  );
                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;
        }

        case PA_SUBSCRIPTION_EVENT_SOURCE: {
            if (type == PA_SUBSCRIPTION_EVENT_REMOVE) {
                pa->remove_paobject(&pa->PA_SOURCES, index);
            } else if (type == PA_SUBSCRIPTION_EVENT_NEW ||
                       type == PA_SUBSCRIPTION_EVENT_CHANGE) {

                pa_operation *o;

                if (!(o = pa_context_get_source_info_by_index(ctx, index,
                          &Pa::ctx_sourcelist_cb, instance))) {
                    return;
                }

                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;
        }

        case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
            if (type == PA_SUBSCRIPTION_EVENT_REMOVE) {
                pa->remove_paobject(&pa->PA_SOURCE_OUTPUTS, index);
            } else if (type == PA_SUBSCRIPTION_EVENT_NEW ||
                       type == PA_SUBSCRIPTION_EVENT_CHANGE) {
                pa_operation *o = pa_context_get_source_output_info(ctx, index,
                                  &Pa::ctx_sourceoutputlist_cb, instance);

                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;

        case PA_SUBSCRIPTION_EVENT_CARD:
            if (type == PA_SUBSCRIPTION_EVENT_REMOVE) {
                pa->remove_paobject(&pa->PA_CARDS, index);
            } else if (type == PA_SUBSCRIPTION_EVENT_NEW ||
                       type == PA_SUBSCRIPTION_EVENT_CHANGE) {
                pa_operation *o = pa_context_get_card_info_by_index(ctx, index,
                                  &Pa::ctx_cardlist_cb, instance);

                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;

        case PA_SUBSCRIPTION_EVENT_SERVER: {
                pa_operation *o = pa_context_get_server_info(ctx,
                                  &Pa::ctx_serverinfo_cb, instance);

                pa->wait_on_pa_operation(o);
                pa_operation_unref(o);
            }

            break;

        case PA_SUBSCRIPTION_EVENT_MODULE:
        case PA_SUBSCRIPTION_EVENT_CLIENT:
        case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE:
        default:
            break;

    }

}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movl %esi, 0x5c(%rsp)
movl %edx, 0x58(%rsp)
movq %rcx, 0x50(%rsp)
movl 0x5c(%rsp), %eax
andl $0x30, %eax
movl %eax, 0x4c(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x40(%rsp)
movl 0x5c(%rsp), %eax
andl $0xf, %eax
movl %eax, %ecx
movq %rcx, 0x8(%rsp)
subl $0x9, %eax
ja 0xb35e
movq 0x8(%rsp), %rax
leaq 0x1517a(%rip), %rcx     # 0x20268
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x20, 0x4c(%rsp)
jne 0xb117
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rsi
addq $0x38, %rsi
movl 0x58(%rsp), %edx
callq 0xb7d0
jmp 0xb15f
cmpl $0x0, 0x4c(%rsp)
je 0xb125
cmpl $0x10, 0x4c(%rsp)
jne 0xb15d
movq 0x60(%rsp), %rdi
movl 0x58(%rsp), %esi
movq 0x50(%rsp), %rcx
leaq 0x596(%rip), %rdx       # 0xb6d0
callq 0x7160
movq %rax, 0x38(%rsp)
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
callq 0xb650
movq 0x38(%rsp), %rdi
callq 0x77a0
jmp 0xb15f
jmp 0xb360
cmpl $0x20, 0x4c(%rsp)
jne 0xb184
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rsi
addq $0x8, %rsi
movl 0x58(%rsp), %edx
callq 0xb7d0
jmp 0xb1cc
cmpl $0x0, 0x4c(%rsp)
je 0xb192
cmpl $0x10, 0x4c(%rsp)
jne 0xb1ca
movq 0x60(%rsp), %rdi
movl 0x58(%rsp), %esi
movq 0x50(%rsp), %rcx
leaq 0x569(%rip), %rdx       # 0xb710
callq 0x7bf0
movq %rax, 0x30(%rsp)
movq 0x40(%rsp), %rdi
movq 0x30(%rsp), %rsi
callq 0xb650
movq 0x30(%rsp), %rdi
callq 0x77a0
jmp 0xb1cc
jmp 0xb360
cmpl $0x20, 0x4c(%rsp)
jne 0xb1f1
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rsi
addq $0x68, %rsi
movl 0x58(%rsp), %edx
callq 0xb7d0
jmp 0xb244
cmpl $0x0, 0x4c(%rsp)
je 0xb1ff
cmpl $0x10, 0x4c(%rsp)
jne 0xb242
movq 0x60(%rsp), %rdi
movl 0x58(%rsp), %esi
movq 0x50(%rsp), %rcx
leaq 0x47c(%rip), %rdx       # 0xb690
callq 0x75e0
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
jne 0xb229
jmp 0xb360
movq 0x40(%rsp), %rdi
movq 0x28(%rsp), %rsi
callq 0xb650
movq 0x28(%rsp), %rdi
callq 0x77a0
jmp 0xb244
jmp 0xb360
cmpl $0x20, 0x4c(%rsp)
jne 0xb26c
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rsi
addq $0x98, %rsi
movl 0x58(%rsp), %edx
callq 0xb7d0
jmp 0xb2b4
cmpl $0x0, 0x4c(%rsp)
je 0xb27a
cmpl $0x10, 0x4c(%rsp)
jne 0xb2b2
movq 0x60(%rsp), %rdi
movl 0x58(%rsp), %esi
movq 0x50(%rsp), %rcx
leaq 0x4c1(%rip), %rdx       # 0xb750
callq 0x7ca0
movq %rax, 0x20(%rsp)
movq 0x40(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0xb650
movq 0x20(%rsp), %rdi
callq 0x77a0
jmp 0xb2b4
jmp 0xb360
cmpl $0x20, 0x4c(%rsp)
jne 0xb2dc
movq 0x40(%rsp), %rdi
movq 0x40(%rsp), %rsi
addq $0xc8, %rsi
movl 0x58(%rsp), %edx
callq 0xb7d0
jmp 0xb324
cmpl $0x0, 0x4c(%rsp)
je 0xb2ea
cmpl $0x10, 0x4c(%rsp)
jne 0xb322
movq 0x60(%rsp), %rdi
movl 0x58(%rsp), %esi
movq 0x50(%rsp), %rcx
leaq 0x311(%rip), %rdx       # 0xb610
callq 0x7c30
movq %rax, 0x18(%rsp)
movq 0x40(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0xb650
movq 0x18(%rsp), %rdi
callq 0x77a0
jmp 0xb324
jmp 0xb360
movq 0x60(%rsp), %rdi
movq 0x50(%rsp), %rdx
leaq 0x459(%rip), %rsi       # 0xb790
callq 0x7680
movq %rax, 0x10(%rsp)
movq 0x40(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0xb650
movq 0x10(%rsp), %rdi
callq 0x77a0
jmp 0xb360
jmp 0xb35e
jmp 0xb360
addq $0x68, %rsp
retq
nopw %cs:(%rax,%rax)