MythTV  master
libdiscid.py
Go to the documentation of this file.
1 # Copyright (C) 2013 Johannes Dewender
2 #
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Lesser General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
16 # Please submit bug reports to GitHub:
17 # https://github.com/JonnyJD/python-discid/issues
18 """libdiscid dynamic loading code and constants
19 
20 The code that works with Disc objects is in disc.py
21 """
22 
23 import os
24 import sys
25 import ctypes
26 from ctypes import c_void_p, c_char_p
27 from ctypes.util import find_library
28 
29 from discid.util import _encode, _decode
30 
31 _LIB_BASE_NAME = "discid"
32 _LIB_MAJOR_VERSION = 0
33 
34 
35 def _find_library(name, version=0):
36  """Find a library by base-name and major version
37  """
38  windows_names = ["%s.dll" % name, "lib%s.dll" % name,
39  "lib%s-%d.dll" % (name, version)]
40 
41  lib_file = None
42 
43  # force prefer current folder
44  # for linux/UNIX-like and Windows
45  if sys.platform in ["darwin", "cygwin"]:
46  # these will already work fine with find_library
47  pass
48  elif sys.platform == "win32":
49  for lib_name in windows_names:
50  if os.path.isfile(lib_name):
51  lib_file = lib_name
52  break
53  else:
54  # that would be linux/UNIX-like
55  # these need to prepend ./
56  lib_name = "./lib%s.so.%d" % (name, version)
57  if os.path.isfile(lib_name):
58  lib_file = lib_name
59 
60  # doesn't work on Windows
61  # Darwin gives a full path when found system-wide
62  # Linux and Cygwin give base filename when found
63  # Darwin and Cygwin will find and prefer in current folder
64  if lib_file is None:
65  lib_file = find_library(name)
66 
67  # Windows needs complete filenames
68  # and gives a full path when found system-wide
69  # also searches in current folder, but system-wide preferred
70  if lib_file is None and sys.platform == "win32":
71  for lib_name in windows_names:
72  if lib_file is None:
73  lib_file = find_library(lib_name)
74 
75  if lib_file is None:
76  # this won't help anymore,
77  # but gives a nice platform dependent file in the error message
78  if sys.platform == "win32":
79  lib_file = "%s.dll" % name
80  elif sys.platform == "darwin":
81  lib_file = "lib%s.%d.dylib" % (name, version)
82  elif sys.platform == "cygwin":
83  lib_file = "cyg%s-%d.dll" % (name, version)
84  else:
85  lib_file = "lib%s.so.%d" % (name, version)
86 
87  return lib_file
88 
89 def _open_library(lib_name):
90  """Open a library by name or location
91  """
92  try:
93  return ctypes.cdll.LoadLibrary(lib_name)
94  except OSError as exc:
95  if lib_name not in str(exc):
96  # replace uninformative Error on Windows
97  raise OSError("could not find libdiscid: %s" % lib_name)
98  else:
99  raise
100 
101 _LIB_NAME = _find_library(_LIB_BASE_NAME, _LIB_MAJOR_VERSION)
102 _LIB = _open_library(_LIB_NAME)
103 
104 
105 
106 try:
107  _LIB.discid_get_version_string.argtypes = ()
108  _LIB.discid_get_version_string.restype = c_char_p
109 except AttributeError:
110  pass
112  """Get the version string of libdiscid
113  """
114  try:
115  version_string = _LIB.discid_get_version_string()
116  except AttributeError:
117  return "libdiscid < 0.4.0"
118  else:
119  return _decode(version_string)
120 
121 _LIB.discid_get_default_device.argtypes = ()
122 _LIB.discid_get_default_device.restype = c_char_p
124  """The default device to use for :func:`read` on this platform
125  given as a :obj:`unicode` or :obj:`str <python:str>` object.
126  """
127  device = _LIB.discid_get_default_device()
128  return _decode(device)
129 
130 try:
131  _LIB.discid_get_feature_list.argtypes = (c_void_p, )
132  _LIB.discid_get_feature_list.restype = None
133 except AttributeError:
134  _features_available = False
135 else:
136  _features_available = True
138  """Get the supported features for the platform.
139  """
140  features = []
141  if _features_available:
142  c_features = (c_char_p * 32)()
143  _LIB.discid_get_feature_list(c_features)
144  for feature in c_features:
145  if feature:
146  features.append(_decode(feature))
147  else:
148  # libdiscid <= 0.4.0
149  features = ["read"] # no generic platform yet
150  try:
151  # test for ISRC/MCN API (introduced 0.3.0)
152  _LIB.discid_get_mcn
153  except AttributeError:
154  pass
155  else:
156  # ISRC/MCN API found -> libdiscid = 0.3.x
157  if (sys.platform.startswith("linux") and
158  not os.path.isfile("/usr/lib/libdiscid.so.0.3.0")
159  and not os.path.isfile("/usr/lib64/libdiscid.so.0.3.0")):
160  features += ["mcn", "isrc"]
161  elif sys.platform in ["darwin", "win32"]:
162  features += ["mcn", "isrc"]
163 
164  return features
165 
166 LIBDISCID_VERSION_STRING = _get_version_string()
167 
168 FEATURES = _get_features()
169 
170 
171 # vim:set shiftwidth=4 smarttab expandtab:
discid.libdiscid._find_library
def _find_library(name, version=0)
Definition: libdiscid.py:35
discid.util
Definition: discid/util.py:1
discid.util._decode
def _decode(byte_string)
Definition: discid/util.py:36
discid.libdiscid._get_features
def _get_features()
Definition: libdiscid.py:137
discid.libdiscid.get_default_device
def get_default_device()
Definition: libdiscid.py:123
discid.libdiscid._open_library
def _open_library(lib_name)
Definition: libdiscid.py:89
discid.libdiscid._get_version_string
def _get_version_string()
Definition: libdiscid.py:111