Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  messages.c   Sprache: C

 

/*****************************************************************************
 * messages.c: messages interface
 * This library provides an interface to the message queue to be used by other
 * modules, especially intf modules. See vlc_config.h for output configuration.
 *****************************************************************************
 * Copyright (C) 1998-2005 VLC authors and VideoLAN
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdlib.h>
#include <stdarg.h>                                       /* va_list for BSD */
#include <unistd.h>
#include <assert.h>

#include <vlc_common.h>
#include <vlc_threads.h>
#include <vlc_interface.h>
#include <vlc_charset.h>
#include <vlc_modules.h>
#include "rcu.h"
#include "../libvlc.h"

#ifndef CONFIGURE_LINE
// generated C file
extern const char CONFIGURE_LINE[];
#endif

#ifdef _WIN32
static const char msg_type[4][9] = { "", " error", " warning", " debug" };

static void Win32DebugOutputMsg (int type, const vlc_log_t *p_item,
                                 const char *format, va_list dol)
{
    char *msg = NULL;
    int msg_len = vasprintf(&msg, format, dol);

    if (unlikely(msg_len == -1))
        return;

    const char *ending = msg_len > 1 && msg[msg_len-1] == '\n' ? "" : "\n";

    char* psz_msg = NULL;
    if (asprintf(&psz_msg, "%s %s%s: %s%s", p_item->psz_module,
                p_item->psz_object_type, msg_type[type], msg, ending) > 0) {
        wchar_t* wmsg = ToWide(psz_msg);
        if (likely(wmsg != NULL))
        {
            OutputDebugStringW(wmsg);
            free(wmsg);
        }
        free(psz_msg);
    }
    free(msg);
}
#endif

static void vlc_LogSpam(vlc_object_t *obj)
{
    /* Announce who we are */
    msg_Dbg(obj, "VLC media player - %s", VERSION_MESSAGE);
    msg_Dbg(obj, "%s", COPYRIGHT_MESSAGE);
    msg_Dbg(obj, "revision %s", psz_vlc_changeset);
    msg_Dbg(obj, "configured with %s", CONFIGURE_LINE);
}

static void vlc_vaLogCallback(vlc_logger_t *logger, int type,
                              const vlc_log_t *item, const char *format,
                              va_list ap)
{
    if (logger != NULL) {
#ifdef _WIN32
        va_list dol;

        va_copy (dol, ap);
        Win32DebugOutputMsg (type, item, format, dol);
        va_end (dol);
#endif

        int canc = vlc_savecancel();

        logger->ops->log(logger, type, item, format, ap);
        vlc_restorecancel(canc);
    }
}

static void vlc_LogCallback(vlc_logger_t *logger, int type,
                            const vlc_log_t *item, const char *format, ...)
{
    va_list ap;

    va_start(ap, format);
    vlc_vaLogCallback(logger, type, item, format, ap);
    va_end(ap);
}

void vlc_vaLog(struct vlc_logger *const *loggerp, int type,
               const char *typename, const char *module,
               const char *file, unsigned line, const char *func,
               const char *format, va_list args)
{
    struct vlc_logger *logger = *loggerp;
    if (logger == NULL)
        // nothing to do
        return;

    /* Get basename from the module filename */
    const char *p = strrchr(module, '/');
    if (p != NULL)
        module = p + 1;
    p = strchr(module, '.');

    size_t modlen = (p != NULL) ? (p - module) : 0;
    char modulebuf[modlen + 1];
    if (p != NULL)
    {
        memcpy(modulebuf, module, modlen);
        modulebuf[modlen] = '\0';
        module = modulebuf;
    }

    /* Fill message information fields */
    vlc_log_t msg;

    msg.i_object_id = (uintptr_t)(void *)loggerp;
    msg.psz_object_type = typename;
    msg.psz_module = module;
    msg.psz_header = NULL;
    msg.file = file;
    msg.line = line;
    msg.func = func;
    msg.tid = vlc_thread_id();

    /* Pass message to the callback */
    vlc_vaLogCallback(logger, type, &msg, format, args);
}

void vlc_Log(struct vlc_logger *const *logger, int type,
             const char *typename, const char *module,
             const char *file, unsigned line, const char *func,
             const char *format, ... )
{
    va_list ap;

    va_start(ap, format);
    vlc_vaLog(logger, type, typename, module, file, line, func, format, ap);
    va_end(ap);
}

/**
 * Early (latched) message log.
 *
 * A message log that stores messages in memory until another log is available.
 */

typedef struct vlc_log_early_t
{
    struct vlc_log_early_t *next;
    int type;
    vlc_log_t meta;
    char *msg;
} vlc_log_early_t;

typedef struct vlc_logger_early {
    vlc_mutex_t lock;
    vlc_log_early_t *head;
    vlc_log_early_t **tailp;
    vlc_logger_t *sink;
    struct vlc_logger logger;
} vlc_logger_early_t;

static void vlc_vaLogEarly(void *d, int type, const vlc_log_t *item,
                           const char *format, va_list ap)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_early *early =
        container_of(logger, struct vlc_logger_early, logger);

    vlc_log_early_t *log = malloc(sizeof (*log));
    if (unlikely(log == NULL))
        return;

    log->next = NULL;
    log->type = type;
    log->meta.i_object_id = item->i_object_id;
    /* NOTE: Object types MUST be static constant - no need to copy them. */
    log->meta.psz_object_type = item->psz_object_type;
    log->meta.psz_module = item->psz_module; /* Ditto. */
    log->meta.psz_header = item->psz_header ? strdup(item->psz_header) : NULL;
    log->meta.file = item->file;
    log->meta.line = item->line;
    log->meta.func = item->func;

    if (vasprintf(&log->msg, format, ap) == -1)
        log->msg = NULL;

    vlc_mutex_lock(&early->lock);
    assert(early->tailp != NULL);
    assert(*(early->tailp) == NULL);
    *(early->tailp) = log;
    early->tailp = &log->next;
    vlc_mutex_unlock(&early->lock);
}

static void vlc_LogEarlyClose(void *d)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_early *early =
        container_of(logger, struct vlc_logger_early, logger);
    vlc_logger_t *sink = early->sink;

    /* Drain early log messages */
    for (vlc_log_early_t *log = early->head, *next; log != NULL; log = next)
    {
        vlc_LogCallback(sink, log->type, &log->meta, "%s",
                        (log->msg != NULL) ? log->msg : "message lost");
        free(log->msg);
        free((char*)log->meta.psz_header); // local copy
        next = log->next;
        free(log);
    }

    free(early);
}

static const struct vlc_logger_operations early_ops = {
    vlc_vaLogEarly,
    vlc_LogEarlyClose,
};

static struct vlc_logger *vlc_LogEarlyOpen(struct vlc_logger *logger)
{
    vlc_logger_early_t *early = malloc(sizeof (*early));
    if (unlikely(early == NULL))
        return NULL;

    early->logger.ops = &early_ops;
    vlc_mutex_init(&early->lock);
    early->head = NULL;
    early->tailp = &early->head;
    early->sink = logger;
    return &early->logger;
}

static void vlc_vaLogDiscard(void *d, int type, const vlc_log_t *item,
                             const char *format, va_list ap)
{
    (void) d; (void) type; (void) item; (void) format; (void) ap;
}

static void vlc_LogDiscardClose(void *d)
{
    (void) d;
}

static const struct vlc_logger_operations discard_ops = {
    vlc_vaLogDiscard,
    vlc_LogDiscardClose,
};

static struct vlc_logger discard_log = { &discard_ops };

/**
 * Switchable message log.
 *
 * A message log that can be redirected live.
 */

struct vlc_logger_switch {
    struct vlc_logger *_Atomic backend;
    struct vlc_logger frontend;
};

static void vlc_vaLogSwitch(void *d, int type, const vlc_log_t *item,
                            const char *format, va_list ap)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_switch *logswitch =
        container_of(logger, struct vlc_logger_switch, frontend);
    struct vlc_logger *backend;

    vlc_rcu_read_lock();
    backend = atomic_load_explicit(&logswitch->backend, memory_order_acquire);
    backend->ops->log(backend, type, item, format, ap);
    vlc_rcu_read_unlock();
}

static void vlc_LogSwitch(vlc_logger_t *logger, vlc_logger_t *new_logger);

static void vlc_LogSwitchClose(void *d)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_switch *logswitch =
        container_of(logger, struct vlc_logger_switch, frontend);

    /* Discard any further messages. */
    vlc_LogSwitch(logger, &discard_log);
    free(logswitch);
}

static const struct vlc_logger_operations switch_ops = {
    vlc_vaLogSwitch,
    vlc_LogSwitchClose,
};

static void vlc_LogSwitch(vlc_logger_t *logger, vlc_logger_t *new_logger)
{
    struct vlc_logger_switch *logswitch =
        container_of(logger, struct vlc_logger_switch, frontend);
    struct vlc_logger *old_logger;

    assert(logger->ops == &switch_ops);

    if (new_logger == NULL)
        new_logger = &discard_log;

    old_logger = atomic_exchange_explicit(&logswitch->backend, new_logger,
                                          memory_order_acq_rel);
    vlc_rcu_synchronize();
    old_logger->ops->destroy(old_logger);
}

static struct vlc_logger *vlc_LogSwitchCreate(void)
{
    struct vlc_logger_switch *logswitch = malloc(sizeof (*logswitch));
    if (unlikely(logswitch == NULL))
        return NULL;

    logswitch->frontend.ops = &switch_ops;
    atomic_init(&logswitch->backend, &discard_log);
    return &logswitch->frontend;
}

/**
 * Module-based message log.
 */

struct vlc_logger_module {
    struct vlc_object_t obj;
    struct vlc_logger frontend;
    const struct vlc_logger_operations *ops;
    void *opaque;
};

static int vlc_logger_load(void *func, bool forced, va_list ap)
{
    const struct vlc_logger_operations *(*activate)(vlc_object_t *,
                                                    void **) = func;
    struct vlc_logger_module *module = va_arg(ap, struct vlc_logger_module *);

    (void) forced;
    module->ops = activate(VLC_OBJECT(module), &module->opaque);
    return (module->ops != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
}

static void vlc_vaLogModule(void *d, int type, const vlc_log_t *item,
                            const char *format, va_list ap)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_module *module =
        container_of(logger, struct vlc_logger_module, frontend);

    module->ops->log(module->opaque, type, item, format, ap);
}

static void vlc_LogModuleClose(void *d)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_module *module =
        container_of(logger, struct vlc_logger_module, frontend);

    if (module->ops->destroy != NULL)
        module->ops->destroy(module->opaque);

    vlc_object_delete(VLC_OBJECT(module));
}

static const struct vlc_logger_operations module_ops = {
    vlc_vaLogModule,
    vlc_LogModuleClose,
};

static struct vlc_logger *vlc_LogModuleCreate(vlc_object_t *parent)
{
    struct vlc_logger_module *module;

    module = vlc_custom_create(parent, sizeof (*module), "logger");
    if (unlikely(module == NULL))
        return NULL;

    /* TODO: module configuration item */
    if (vlc_module_load(vlc_object_logger(module), "logger", NULL, false,
                        vlc_logger_load, module) == NULL) {
        vlc_object_delete(VLC_OBJECT(module));
        return NULL;
    }

    module->frontend.ops = &module_ops;
    return &module->frontend;
}

/**
 * Initializes the messages logging subsystem and drain the early messages to
 * the configured log.
 */

void vlc_LogInit(libvlc_int_t *vlc)
{
    struct vlc_logger *logger = vlc_LogModuleCreate(VLC_OBJECT(vlc));
    if (logger == NULL)
        logger = &discard_log;

    vlc_LogSwitch(vlc->obj.logger, logger);
}

/**
 * Performs preinitialization of the messages logging subsystem.
 *
 * Early log messages will be stored in memory until the subsystem is fully
 * initialized with vlc_LogInit(). This enables logging before the
 * configuration and modules bank are ready.
 *
 * \return 0 on success, -1 on error.
 */

int vlc_LogPreinit(libvlc_int_t *vlc)
{
    vlc_logger_t *logger = vlc_LogSwitchCreate();
    if (unlikely(logger == NULL))
        return -1;
    vlc->obj.logger = logger;

    struct vlc_logger *early = vlc_LogEarlyOpen(logger);
    if (early != NULL) {
        vlc_LogSwitch(logger, early);
        vlc_LogSpam(VLC_OBJECT(vlc));
    }
    return 0;
}

/**
 * Message log with "header".
 */

struct vlc_logger_header {
    struct vlc_logger logger;
    struct vlc_logger *parent;
    char header[];
};

static void vlc_vaLogHeader(void *d, int type, const vlc_log_t *item,
                            const char *format, va_list ap)
{
    struct vlc_logger *logger = d;
    struct vlc_logger_header *header =
        container_of(logger, struct vlc_logger_header, logger);
    struct vlc_logger *parent = header->parent;
    vlc_log_t hitem = *item;

    hitem.psz_header = header->header;
    parent->ops->log(parent, type, &hitem, format, ap);
}

static const struct vlc_logger_operations header_ops = {
    vlc_vaLogHeader,
    free,
};

struct vlc_logger *vlc_LogHeaderCreate(struct vlc_logger *parent,
                                       const char *str)
{
    if (parent == NULL)
        return NULL;

    size_t len = strlen(str) + 1;
    struct vlc_logger_header *header = malloc(sizeof (*header) + len);
    if (unlikely(header == NULL))
        return NULL;

    header->logger.ops = &header_ops;
    header->parent = parent;
    memcpy(header->header, str, len);
    return &header->logger;
}

/**
 * External custom log callback
 */

struct vlc_logger_external {
    struct vlc_logger logger;
    const struct vlc_logger_operations *ops;
    void *opaque;
};

static void vlc_vaLogExternal(void *d, int type, const vlc_log_t *item,
                              const char *format, va_list ap)
{
    struct vlc_logger_external *ext = d;

    ext->ops->log(ext->opaque, type, item, format, ap);
}

static void vlc_LogExternalClose(void *d)
{
    struct vlc_logger_external *ext = d;

    if (ext->ops->destroy != NULL)
        ext->ops->destroy(ext->opaque);
    free(ext);
}

static const struct vlc_logger_operations external_ops = {
    vlc_vaLogExternal,
    vlc_LogExternalClose,
};

static struct vlc_logger *
vlc_LogExternalCreate(const struct vlc_logger_operations *ops, void *opaque)
{
    struct vlc_logger_external *ext = malloc(sizeof (*ext));
    if (unlikely(ext == NULL))
        return NULL;

    ext->logger.ops = &external_ops;
    ext->ops = ops;
    ext->opaque = opaque;
    return &ext->logger;
}

/**
 * Sets the message logging callback.
 *
 * \param vlc the libvlc private instance to replace the logger for
 * \param ops message callback, or NULL to clear
 * \param opaque data pointer for the message callback
 */

void vlc_LogSet(libvlc_int_t *vlc, const struct vlc_logger_operations *ops,
                void *opaque)
{
    struct vlc_logger *logger;

    if (ops != NULL)
        logger = vlc_LogExternalCreate(ops, opaque);
    else
        logger = NULL;

    if (logger == NULL)
        logger = &discard_log;

    vlc_LogSwitch(vlc->obj.logger, logger);
    vlc_LogSpam(VLC_OBJECT(vlc));
}

void vlc_LogDestroy(vlc_logger_t *logger)
{
    logger->ops->destroy(logger);
}

Messung
CHZG
849610093

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104842
#Domains=499164