1

PulseAudio API を利用する Python アプリを作成しています。この実装では、Python で記述され、PulseAudio の C コードによって呼び出されるコールバックを多用しています。

ほとんどの情報は、C で次のように定義されている特定の構造体 (たとえばpa_sink_info、 ) によってコールバックに渡されます。

typedef struct pa_sink_info {
  const char *name;                  
  uint32_t index;                    
  const char *description;           
  pa_sample_spec sample_spec;        
  pa_channel_map channel_map;        
  uint32_t owner_module;             
  pa_cvolume volume;                 
  int mute;                          
  uint32_t monitor_source;           
  const char *monitor_source_name;   
  pa_usec_t latency;                 
  const char *driver;                
  pa_sink_flags_t flags;             
  pa_proplist *proplist;             
  pa_usec_t configured_latency;      
  pa_volume_t base_volume;           
  pa_sink_state_t state;             
  uint32_t n_volume_steps;           
  uint32_t card;                     
  uint32_t n_ports;                  
  pa_sink_port_info** ports;         
  pa_sink_port_info* active_port;    
  uint8_t n_formats;                 
  pa_format_info **formats;          
} pa_sink_info;

この構造から、スカラー値を取得するのは非常に簡単です。例:

self.some_proc(
  struct.contents.index,
  struct.contents.name,
  struct.contents.description)

しかし、 Python では次のように記述されているportsとを扱うのが困難です。active_port

('n_ports', uint32_t),
('ports', POINTER(POINTER(pa_sink_port_info))),
('active_port', POINTER(pa_sink_port_info)),

ここでn_portsは、 の要素数を指定しますports。これは、 型の構造体へのポインターの配列へのポインターpa_sink_port_infoです。実際、これらを Python 型に変換する方法もまったくわかりません。

portsを含むPython辞書に変換する最も効率的な方法は何pa_sink_port_infoですか?

4

1 に答える 1

0

この問題を解決するには、Python のctypes リファレンスを注意深く読む必要がありました。型変換の実装のメカニズムctypesが明確になると、目的の値に到達することはそれほど難しくありません。

ポインターに関する主な考え方は、そのcontents属性を使用して、ポインターが指すデータを取得することです。知っておくと便利なもう 1 つのことは、ポインターが配列のようにインデックス付けできることです (インタープリターによって検証されないため、実際に配列であることを確認するのはユーザー自身の責任です)。

この特定の PulseAudio の例では、ports構造体メンバー (ポインターの配列へのポインター) を次のように処理できます。

port_list = []
if struct.contents.ports:
  i = 0
  while True:
    port_ptr = struct.contents.ports[i]
    # NULL pointer terminates the array
    if port_ptr:
      port_struct = port_ptr.contents
      port_list.append(port_struct.name)
      i += 1
    else:
      break
于 2013-12-30T17:03:24.227 に答える