Do not crash to assertion failure on unknown audio codec
[deb_shairplay.git] / src / lib / logger.c
CommitLineData
23e7e3ae
JVH
1/**
2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 */
14
2340bcd3
JVH
15#include <stdlib.h>
16#include <stdio.h>
17#include <stdarg.h>
18#include <assert.h>
19
20#include "logger.h"
979533c3 21#include "compat.h"
2340bcd3 22
fda63ad4
JVH
23struct logger_s {
24 mutex_handle_t lvl_mutex;
25 mutex_handle_t cb_mutex;
26
27 int level;
2975b4b8 28 void *cls;
fda63ad4
JVH
29 logger_callback_t callback;
30};
31
32logger_t *
33logger_init()
2340bcd3 34{
fda63ad4 35 logger_t *logger = calloc(1, sizeof(logger_t));
2340bcd3
JVH
36 assert(logger);
37
fda63ad4
JVH
38 MUTEX_CREATE(logger->lvl_mutex);
39 MUTEX_CREATE(logger->cb_mutex);
40
02fe4db1 41 logger->level = LOGGER_WARNING;
2340bcd3 42 logger->callback = NULL;
fda63ad4
JVH
43 return logger;
44}
45
46void
47logger_destroy(logger_t *logger)
48{
49 MUTEX_DESTROY(logger->lvl_mutex);
50 MUTEX_DESTROY(logger->cb_mutex);
51 free(logger);
2340bcd3
JVH
52}
53
54void
55logger_set_level(logger_t *logger, int level)
56{
57 assert(logger);
58
fda63ad4 59 MUTEX_LOCK(logger->lvl_mutex);
2340bcd3 60 logger->level = level;
fda63ad4 61 MUTEX_UNLOCK(logger->lvl_mutex);
2340bcd3
JVH
62}
63
64void
2975b4b8 65logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls)
2340bcd3
JVH
66{
67 assert(logger);
68
fda63ad4 69 MUTEX_LOCK(logger->cb_mutex);
2975b4b8 70 logger->cls = cls;
2340bcd3 71 logger->callback = callback;
fda63ad4 72 MUTEX_UNLOCK(logger->cb_mutex);
2340bcd3
JVH
73}
74
75static char *
76logger_utf8_to_local(const char *str)
77{
78 char *ret = NULL;
79
80/* FIXME: This is only implemented on Windows for now */
81#if defined(_WIN32) || defined(_WIN64)
82 int wclen, mblen;
83 WCHAR *wcstr;
84 BOOL failed;
85
86 wclen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
87 wcstr = malloc(sizeof(WCHAR) * wclen);
88 MultiByteToWideChar(CP_UTF8, 0, str, -1, wcstr, wclen);
89
90 mblen = WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, NULL, 0, NULL, &failed);
91 if (failed) {
92 /* Invalid characters in input, conversion failed */
93 free(wcstr);
94 return NULL;
95 }
96
97 ret = malloc(sizeof(CHAR) * mblen);
98 WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, ret, mblen, NULL, NULL);
99 free(wcstr);
100#endif
101
102 return ret;
103}
104
105void
106logger_log(logger_t *logger, int level, const char *fmt, ...)
107{
108 char buffer[4096];
109 va_list ap;
110
fda63ad4
JVH
111 MUTEX_LOCK(logger->lvl_mutex);
112 if (level > logger->level) {
113 MUTEX_UNLOCK(logger->lvl_mutex);
2340bcd3 114 return;
fda63ad4
JVH
115 }
116 MUTEX_UNLOCK(logger->lvl_mutex);
2340bcd3
JVH
117
118 buffer[sizeof(buffer)-1] = '\0';
119 va_start(ap, fmt);
120 vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
121 va_end(ap);
122
fda63ad4 123 MUTEX_LOCK(logger->cb_mutex);
2340bcd3 124 if (logger->callback) {
2975b4b8 125 logger->callback(logger->cls, level, buffer);
fda63ad4 126 MUTEX_UNLOCK(logger->cb_mutex);
2340bcd3 127 } else {
fda63ad4
JVH
128 char *local;
129 MUTEX_UNLOCK(logger->cb_mutex);
130 local = logger_utf8_to_local(buffer);
2340bcd3 131 if (local) {
46212791 132 fprintf(stderr, "%s\n", local);
2340bcd3
JVH
133 free(local);
134 } else {
46212791 135 fprintf(stderr, "%s\n", buffer);
2340bcd3
JVH
136 }
137 }
138}
139