@@ -7,6 +7,7 @@ class Instance:
7
7
- a list of strings as first parameters
8
8
- the parameters given as the constructor parameters (must be strings)
9
9
"""
10
+
10
11
def __new__ (cls , * args ):
11
12
if len (args ) == 1 :
12
13
# Only 1 arg. It is either a C pointer, or an arg string,
@@ -142,6 +143,52 @@ def video_filter_list_get(self):
142
143
"""
143
144
return module_description_list (libvlc_video_filter_list_get (self ))
144
145
146
+ def set_logger (self , logger , max_log_message_size = 4096 ):
147
+ """Links a logging.Logger object to the libVLC Instance
148
+
149
+ Along with the log level and message, each libVLC log will also include
150
+ The following extra info:
151
+ - vlc_module: the name of the VLC module (str).
152
+ - file: the VLC source filename (str).
153
+ - line: the VLC source file line number (int).
154
+ These variables can be used in the logger formatter.
155
+
156
+ @param logger: a logging.Logger object
157
+ @param max_log_message_size: defines the maximum size that will be
158
+ copied from VLC log messages. If you experience truncated log
159
+ messages, raise this number (default 4096).
160
+ """
161
+ # libVLC provides the log message through a printf format + va_list.
162
+ # Unfortunately, there is no simple way to use a
163
+ # printf format + va_list in Python outside of the use of a C format
164
+ # function.
165
+ # As there is no guarantee to have access to a C `vasprintf`, we use
166
+ # `vsnprintf` with a log message max size.
167
+ libc = find_libc ()
168
+ self ._vsnprintf = libc .vsnprintf
169
+ self ._max_log_message_size = max_log_message_size
170
+ self ._logger = logger
171
+ # The log_handler is meant to be the "real" callback for libvlc_log_set().
172
+ @CallbackDecorators .LogCb
173
+ def log_handler (instance , log_level , ctx , fmt , va_list ):
174
+ bufferString = ctypes .create_string_buffer (self ._max_log_message_size )
175
+ self ._vsnprintf (bufferString , self ._max_log_message_size , fmt ,
176
+ ctypes .cast (va_list , ctypes .c_void_p ))
177
+ msg = bufferString .value .decode ('utf-8' )
178
+ module , file , line = libvlc_log_get_context (ctx )
179
+ module = module .decode ('utf-8' )
180
+ file = file .decode ('utf-8' )
181
+ self ._logger .log (loglevel_to_logging (LogLevel (log_level )),
182
+ msg , extra = {"vlc_module" : module , "file" : file , "line" : line })
183
+ # We need to keep a reference to the log_handler function that persists
184
+ # after the end of the set_logger.
185
+ # If we do not do that, there is a (high) chance the python garbage
186
+ # collector will destroy the callback function and produce segfault in
187
+ # libVLC.
188
+ # To avoid that, link the log_handler lifetime to the Instance's one.
189
+ self ._log_handler = log_handler
190
+ self .log_set (self ._log_handler , None )
191
+
145
192
class Media :
146
193
"""Create a new Media instance.
147
194
0 commit comments