+class RaopLogLevel:
+ EMERG = 0
+ ALERT = 1
+ CRIT = 2
+ ERR = 3
+ WARNING = 4
+ NOTICE = 5
+ INFO = 6
+ DEBUG = 7
+
+raop_log_callback_prototype = CFUNCTYPE(None, c_void_p, c_int, c_char_p)
+
+audio_init_prototype = CFUNCTYPE(py_object, c_void_p, c_int, c_int, c_int)
+audio_process_prototype = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_int)
+audio_destroy_prototype = CFUNCTYPE(None, c_void_p, c_void_p)
+
+audio_flush_prototype = CFUNCTYPE(None, c_void_p, c_void_p)
+audio_set_volume_prototype = CFUNCTYPE(None, c_void_p, c_void_p, c_float)
+audio_set_metadata_prototype = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_int)
+audio_set_coverart_prototype = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_int)
+
+class RaopNativeCallbacks(Structure):
+ _fields_ = [("cls", py_object),
+ ("audio_init", audio_init_prototype),
+ ("audio_process", audio_process_prototype),
+ ("audio_destroy", audio_destroy_prototype),
+ ("audio_flush", audio_flush_prototype),
+ ("audio_set_volume", audio_set_volume_prototype),
+ ("audio_set_metadata", audio_set_metadata_prototype),
+ ("audio_set_coverart", audio_set_coverart_prototype)]
+
+def InitShairplay(libshairplay):
+ # Initialize dnssd related functions
+ libshairplay.dnssd_init.restype = c_void_p
+ libshairplay.dnssd_init.argtypes = [POINTER(c_int)]
+ libshairplay.dnssd_register_raop.restype = c_int
+ libshairplay.dnssd_register_raop.argtypes = [c_void_p, c_char_p, c_ushort, POINTER(c_char), c_int, c_int]
+ libshairplay.dnssd_register_airplay.restype = c_int
+ libshairplay.dnssd_register_airplay.argtypes = [c_void_p, c_char_p, c_ushort, POINTER(c_char), c_int]
+ libshairplay.dnssd_unregister_raop.restype = None
+ libshairplay.dnssd_unregister_raop.argtypes = [c_void_p]
+ libshairplay.dnssd_unregister_airplay.restype = None
+ libshairplay.dnssd_unregister_airplay.argtypes = [c_void_p]
+ libshairplay.dnssd_destroy.restype = None
+ libshairplay.dnssd_destroy.argtypes = [c_void_p]
+
+ # Initialize raop related functions
+ libshairplay.raop_init.restype = c_void_p
+ libshairplay.raop_init.argtypes = [c_int, POINTER(RaopNativeCallbacks), c_char_p, POINTER(c_int)]
+ libshairplay.raop_set_log_level.restype = None
+ libshairplay.raop_set_log_level.argtypes = [c_void_p, c_int]
+ libshairplay.raop_set_log_callback.restype = None
+ libshairplay.raop_set_log_callback.argtypes = [c_void_p, raop_log_callback_prototype, c_void_p]
+ libshairplay.raop_is_running.restype = c_int
+ libshairplay.raop_is_running.argtypes = [c_void_p]
+ libshairplay.raop_start.restype = c_int
+ libshairplay.raop_start.argtypes = [c_void_p, POINTER(c_ushort), POINTER(c_char), c_int, c_char_p]
+ libshairplay.raop_stop.restype = None
+ libshairplay.raop_stop.argtypes = [c_void_p]
+ libshairplay.raop_destroy.restype = None
+ libshairplay.raop_destroy.argtypes = [c_void_p]
+
+def LoadShairplay(path):
+ if sys.maxsize < 2**32:
+ libname = "shairplay32"
+ else:
+ libname = "shairplay64"
+
+ if platform.system() == "Windows":
+ libname = libname + ".dll"
+ elif platform.system() == "Darwin":
+ libname = "lib" + libname + ".dylib"
+ else:
+ libname = "lib" + libname + ".so"
+
+ try:
+ fullpath = os.path.join(path, libname)
+ libshairplay = cdll.LoadLibrary(fullpath)
+ except:
+ raise RuntimeError("Couldn't load shairplay library " + libname)
+
+ InitShairplay(libshairplay)
+ return libshairplay
+