Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  extension_thread.c   Sprache: C

 

/*****************************************************************************
 * extension_thread.c: Extensions Manager, Threads manager (no Lua here)
 *****************************************************************************
 * Copyright (C) 2009-2010 VideoLAN and authors
 *
 * Authors: Jean-Philippe André < jpeg # videolan.org >
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU 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.
 *****************************************************************************/


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

#include "vlc.h"
#include "extension.h"
#include "assert.h"

#include <vlc_common.h>
#include <vlc_messages.h>
#include <vlc_player.h>

struct thread_sys_t
{
    extensions_manager_t *p_mgr;
    extension_t *p_ext;
};

/** Thread Run */
static void* Run( void *data );
static void FreeCommands( struct command_t *command );

/**
 * Player listeners
 */


static void
OnCurrentMediaChanged(vlc_player_t *player,
                      input_item_t *new_media,
                      void *opaque)
{
    (void)player;
    extension_t *ext = opaque;
    struct lua_extension *sys = ext->p_sys;

    vlc_mutex_lock(&sys->running_lock);
    // Change input
    input_item_t *old = sys->p_item;
    if (old)
        input_item_Release(old);

    if (new_media)
        input_item_Hold(new_media);
    sys->p_item = new_media;

    // Tell the script the input changed
    if (sys->i_capabilities & EXT_INPUT_LISTENER)
        PushCommandUnique(ext, CMD_SET_INPUT);
    vlc_mutex_unlock(&sys->running_lock);
}

/**
 * Activate an extension
 * @param p_ext Extension to activate
 * @return The usual VLC return codes
 **/

int Activate(extension_t *p_ext)
{
    assert( p_ext != NULL );

    struct lua_extension *sys = p_ext->p_sys;
    assert(sys != NULL);
    extensions_manager_t *mgr = sys->p_mgr;

    vlc_mutex_lock(&sys->command_lock);
    if (sys->b_activating)
    {
        vlc_mutex_unlock(&sys->command_lock);
        return VLC_SUCCESS;
    }
    if (!sys->b_activated)
    {
        /* Prepare first command */
        assert(sys->command == NULL);
        sys->command = calloc(1, sizeof(*sys->command));
        if (!sys->command)
        {
            vlc_mutex_unlock(&sys->command_lock);
            return VLC_ENOMEM;
        }
        sys->command->i_command = CMD_ACTIVATE; /* No params */
        if (sys->b_thread_running)
        {
            vlc_debug(p_ext->logger, "Reactivating extension %s", p_ext->psz_title);
            vlc_cond_signal(&sys->wait);
        }
        sys->b_activating = true;
    }
    vlc_mutex_unlock(&sys->command_lock);

    if (!sys->b_thread_running)
    {
        vlc_debug(p_ext->logger, "Activating extension '%s'", p_ext->psz_title);
        sys->b_exiting = false;
        if (vlc_clone(&sys->thread, Run, p_ext) != VLC_SUCCESS)
        {
            sys->b_exiting = true;
            return VLC_ENOMEM;
        }
        sys->b_thread_running = true;
    }

    /* Setup the listeners on the player object. */
    static const struct vlc_player_cbs player_cbs =
    {
        .on_current_media_changed = OnCurrentMediaChanged,
    };

    vlc_player_Lock(mgr->player);
    sys->player_listener =
        vlc_player_AddListener(mgr->player, &player_cbs, p_ext);
    vlc_player_Unlock(mgr->player);

    if (sys->player_listener == NULL)
        goto error_listener;

    return VLC_SUCCESS;
error_listener:
    vlc_mutex_lock(&sys->command_lock);
    sys->b_exiting = true;
    vlc_cond_signal(&sys->wait);
    vlc_mutex_unlock(&sys->command_lock);
    vlc_join(sys->thread, NULL);
    return VLC_ENOMEM;
}

static void FreeCommands( struct command_t *command )
{
    while (command) {
        struct command_t *next = command->next;
        switch( command->i_command )
        {
            case CMD_ACTIVATE:
            case CMD_DEACTIVATE:
            case CMD_CLICK:
                /* No extra memory to free */
                break;
            case CMD_TRIGGERMENU:
            case CMD_PLAYING_CHANGED:
                free( command->data[0] ); // free allocated data
                break;
            default:
                break;
        }
        free(command);
        command = next;
    }
}

bool QueueDeactivateCommand( extension_t *p_ext )
{
    struct lua_extension *sys = p_ext->p_sys;
    vlc_mutex_assert(&sys->command_lock);

    struct command_t *cmd = calloc( 1, sizeof( struct command_t ) );
    if( unlikely( cmd == NULL ) )
        return false;
    /* Free the list of commands */
    if (sys->command != NULL)
        FreeCommands(sys->command->next);

    /* Push command */

    cmd->i_command = CMD_DEACTIVATE;
    if (sys->command)
        sys->command->next = cmd;
    else
        sys->command = cmd;

    sys->b_deactivating = true;
    sys->b_activating = false;
    vlc_cond_signal(&sys->wait);

    vlc_player_Lock(sys->p_mgr->player);
    vlc_player_RemoveListener(sys->p_mgr->player, sys->player_listener);
    vlc_player_Unlock(sys->p_mgr->player);

    return true;
}

/** Deactivate this extension: pushes immediate command and drops queued */
int Deactivate( extensions_manager_t *p_mgr, extension_t *p_ext )
{
    struct lua_extension *sys = p_ext->p_sys;

    vlc_mutex_lock(&sys->command_lock);
    if (!sys->b_activated && !sys->b_activating)
    {
        vlc_mutex_unlock(&sys->command_lock);
        return VLC_SUCCESS;
    }

    if (sys->b_exiting)
    {
        vlc_mutex_unlock(&sys->command_lock);
        return VLC_EGENERIC;
    }

    if (sys->p_progress_id != NULL)
    {
        // Extension is stuck, kill it now
        vlc_dialog_release(p_mgr, sys->p_progress_id);
        sys->p_progress_id = NULL;
        KillExtension(p_ext);
        vlc_mutex_unlock(&sys->command_lock);
        return VLC_SUCCESS;
    }

    bool b_success = QueueDeactivateCommand( p_ext );
    vlc_mutex_unlock(&sys->command_lock);

    return b_success ? VLC_SUCCESS : VLC_ENOMEM;
}

/* MUST be called with command_lock held */
void KillExtension(extension_t *p_ext)
{
    struct lua_extension *sys = p_ext->p_sys;
    vlc_debug(p_ext->logger, "Killing extension now");
    vlclua_fd_interrupt(&sys->dtable);
    sys->b_activated = false;
    sys->b_exiting = true;
    vlc_cond_signal(&sys->wait);
}

/** Push a UI command */
int PushCommand__( extension_t *p_ext,  bool b_unique, command_type_e i_command,
                   va_list args )
{
    struct lua_extension *sys = p_ext->p_sys;
    /* Create command */
    struct command_t *cmd = calloc( 1, sizeof( struct command_t ) );
    if( unlikely( cmd == NULL ) )
        return VLC_ENOMEM;
    cmd->i_command = i_command;
    switch( i_command )
    {
        case CMD_CLICK:
            cmd->data[0] = va_arg( args, void* );
            break;
        case CMD_TRIGGERMENU:
            {
                int *pi = malloc( sizeof( int ) );
                if( !pi )
                {
                    free( cmd );
                    return VLC_ENOMEM;
                }
                *pi = va_arg( args, int );
                cmd->data[0] = pi;
            }
            break;
        case CMD_PLAYING_CHANGED:
            {
                int *pi = malloc( sizeof( int ) );
                if( !pi )
                {
                    free( cmd );
                    return VLC_ENOMEM;
                }
                *pi = va_arg( args, int );
                cmd->data[0] = pi;
            }
            break;
        case CMD_CLOSE:
        case CMD_SET_INPUT:
        case CMD_UPDATE_META:
            // Nothing to do here
            break;
        default:
            msg_Dbg(sys->p_mgr, "Unknown command send to extension: %d",
                    i_command);
            break;
    }

    vlc_mutex_lock(&sys->command_lock);

    /* Push command to the end of the queue */
    struct command_t *last = sys->command;
    if( !last )
    {
        sys->command = cmd;
    }
    else
    {
        bool b_skip = false;
        while( last->next != NULL )
        {
            if( b_unique && last->i_command == i_command )
            {
                // Do not push this 'unique' command a second time
                b_skip = !memcmp( last->data, cmd->data, sizeof( cmd->data ) );
                break;
            }
            else
            {
                last = last->next;
            }
        }
        if( !b_skip )
        {
            last->next = cmd;
        }
        else
        {
            FreeCommands( cmd );
        }
    }

    vlc_cond_signal(&sys->wait);
    vlc_mutex_unlock(&sys->command_lock);
    return VLC_SUCCESS;
}

/* Thread loop */
static void* Run( void *data )
{
    extension_t *p_ext = data;
    struct lua_extension *sys = p_ext->p_sys;
    extensions_manager_t *p_mgr = sys->p_mgr;

    vlc_thread_set_name("vlc-lua-ext");

    vlc_mutex_lock(&sys->command_lock);

    while (!sys->b_exiting || (sys->command && sys->command->i_command == CMD_DEACTIVATE))
    {
        struct command_t *cmd = sys->command;

        /* Pop command in front */
        if( cmd == NULL )
        {
            vlc_cond_wait(&sys->wait, &sys->command_lock);
            continue;
        }
        sys->command = cmd->next;
        cmd->next = NULL; /* unlink command (for FreeCommands()) */
        // Create watch timer
        vlc_timer_schedule(sys->timer, false, WATCH_TIMER_PERIOD,
                           VLC_TIMER_FIRE_ONCE);
        vlc_mutex_unlock(&sys->command_lock);

        /* Run command */
        vlc_mutex_lock(&sys->running_lock);
        switch( cmd->i_command )
        {
            case CMD_ACTIVATE:
            {
                if( lua_ExecuteFunction( p_mgr, p_ext, "activate", LUA_END ) < 0 )
                {
                    msg_Err( p_mgr, "Could not activate extension!" );
                    vlc_mutex_lock(&sys->command_lock);
                    QueueDeactivateCommand( p_ext );
                    vlc_mutex_unlock(&sys->command_lock);
                    break;
                }
                vlc_mutex_lock(&sys->command_lock);
                sys->b_activated = true;
                sys->b_activating = false;
                vlc_mutex_unlock(&sys->command_lock);
                break;
            }

            case CMD_DEACTIVATE:
            {
                vlc_debug(p_ext->logger, "Deactivating '%s'", p_ext->psz_title);
                if( lua_ExtensionDeactivate( p_mgr, p_ext ) < 0 )
                {
                    vlc_warning(p_ext->logger, "Extension '%s' did not deactivate properly",
                                p_ext->psz_title);
                }
                vlc_mutex_lock(&sys->command_lock);
                sys->b_activated = false;
                sys->b_deactivating = false;
                vlc_mutex_unlock(&sys->command_lock);
                break;
            }

            case CMD_CLOSE:
            {
                lua_ExecuteFunction( p_mgr, p_ext, "close", LUA_END );
                break;
            }

            case CMD_CLICK:
            {
                extension_widget_t *p_widget = cmd->data[0];
                assert( p_widget );
                vlc_debug(p_ext->logger, "Clicking '%s': '%s'",
                         p_ext->psz_name, p_widget->psz_text);
                if( lua_ExtensionWidgetClick( p_mgr, p_ext, p_widget ) < 0 )
                    vlc_debug(p_ext->logger, "Could not translate click");
                break;
            }

            case CMD_TRIGGERMENU:
            {
                int *pi_id = cmd->data[0];
                assert( pi_id );
                vlc_debug(p_ext->logger, "Trigger menu %d of '%s'",
                          *pi_id, p_ext->psz_name);
                lua_ExtensionTriggerMenu( p_mgr, p_ext, *pi_id );
                break;
            }

            case CMD_SET_INPUT:
            {
                lua_ExecuteFunction( p_mgr, p_ext, "input_changed", LUA_END );
                break;
            }

            case CMD_UPDATE_META:
            {
                lua_ExecuteFunction( p_mgr, p_ext, "meta_changed", LUA_END );
                break;
            }

            case CMD_PLAYING_CHANGED:
            {
                lua_ExecuteFunction( p_mgr, p_ext, "playing_changed",
                        LUA_NUM, *((int *)cmd->data[0]), LUA_END );
                break;
            }

            default:
            {
                msg_Dbg( p_mgr, "Unknown command in extension command queue: %d",
                         cmd->i_command );
                break;
            }
        }
        vlc_mutex_unlock(&sys->running_lock);

        FreeCommands( cmd );

        vlc_mutex_lock(&sys->command_lock);
        // Reset watch timer and timestamp
        if (sys->p_progress_id != NULL)
        {
            vlc_dialog_release(p_mgr, sys->p_progress_id);
            sys->p_progress_id = NULL;
        }
        vlc_timer_disarm(sys->timer);
    }

    vlc_mutex_unlock(&sys->command_lock);
    msg_Dbg( p_mgr, "Extension thread end: '%s'", p_ext->psz_title );

    // Note: At this point, the extension should be deactivated
    return NULL;
}

Messung
CHZG
849410092

¤ Dauer der Verarbeitung: 0.6 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=499162