<commit_before>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster 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.

    Campcaster 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 Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

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

#define DEBUG_PREFIX "GstreamerPlayer"
#include "LiveSupport/Core/Debug.h"

#include "LiveSupport/Core/TimeConversion.h"
#include "LiveSupport/GstreamerElements/autoplug.h"
#include "GstreamerPlayer.h"

using namespace boost::posix_time;
using namespace LiveSupport::Core;
using namespace LiveSupport::PlaylistExecutor;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/**
 *  The name of the config element for this class
 */
const std::string GstreamerPlayer::configElementNameStr = "gstreamerPlayer";

/**
 *  The name of the audio device attribute.
 */
static const std::string    audioDeviceName = "audioDevice";

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Configure the Audio Player.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: configure(const xmlpp::Element   &  element)
                                                throw (std::invalid_argument,
                                                       std::logic_error)
{
    DEBUG_FUNC_INFO

    if (element.get_name() != configElementNameStr) {
        std::string eMsg = "Bad configuration element ";
        eMsg += element.get_name();
        throw std::invalid_argument(eMsg);
    }

    const xmlpp::Attribute    * attribute = 0;

    if ((attribute = element.get_attribute(audioDeviceName))) {
        audioDevice = attribute->get_value();
    }
}

/*------------------------------------------------------------------------------
 *  Initialize the Audio Player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: initialize(void)                 throw (std::exception)
{
    DEBUG_FUNC_INFO

    if (initialized) {
        return;
    }

    // initialize the gstreamer library
    if (!gst_init_check(0, 0)) {
        throw std::runtime_error("couldn't initialize the gstreamer library");
    }

    // create the pipeline container (threaded)
    pipeline   = gst_thread_new("audio-player");

    filesrc         = 0;
    decoder         = 0;
    audioconvert    = 0;
    audioscale      = 0;

    g_signal_connect(pipeline, "error", G_CALLBACK(errorHandler), this);

    // TODO: read the caps from the config file
    sinkCaps = gst_caps_new_simple("audio/x-raw-int",
                                   "width", G_TYPE_INT, 16,
                                   "depth", G_TYPE_INT, 16,
                                   "endiannes", G_TYPE_INT, G_BYTE_ORDER,
                                   "channels", G_TYPE_INT, 2,
                                   "rate", G_TYPE_INT, 44100,
                                   NULL);

    setAudioDevice(audioDevice);

    // set up other variables
    initialized = true;
}

/*------------------------------------------------------------------------------
 *  Handler for gstreamer errors.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: errorHandler(GstElement   * pipeline,
                                GstElement   * source,
                                GError       * error,
                                gchar        * debug,
                                gpointer       self)
                                                                throw ()
{
    // TODO: handle error
    std::cerr << "gstreamer error: " << error->message << std::endl;
}

/*------------------------------------------------------------------------------
 *  De-initialize the Gstreamer Player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: deInitialize(void)                       throw ()
{
    DEBUG_FUNC_INFO

    if (initialized) {
        gst_element_set_state(pipeline, GST_STATE_NULL);
        gst_bin_sync_children_state(GST_BIN(pipeline));

        if (!gst_element_get_parent(audiosink)) {
            // delete manually, if audiosink wasn't added to the pipeline
            // for some reason
            gst_object_unref(GST_OBJECT(audiosink));
        }
        gst_object_unref(GST_OBJECT(pipeline));
        gst_caps_free(sinkCaps);

        audiosink   = 0;
        initialized = false;
    }
}

/*------------------------------------------------------------------------------
 *  Attach an event listener.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: attachListener(AudioPlayerEventListener*     eventListener)
                                                                    throw ()
{
    listeners.push_back(eventListener);
}

/*------------------------------------------------------------------------------
 *  Detach an event listener.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: detachListener(AudioPlayerEventListener*     eventListener)
                                                throw (std::invalid_argument)
{
    ListenerVector::iterator    it  = listeners.begin();
    ListenerVector::iterator    end = listeners.end();

    while (it != end) {
        if (*it == eventListener) {
            listeners.erase(it);
            return;
        }
        ++it;
    }

    throw std::invalid_argument("supplied event listener not found");
}

/*------------------------------------------------------------------------------
 *  Send the onStop event to all attached listeners.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: fireOnStopEvent(void)                        throw ()
{
    ListenerVector::iterator    it  = listeners.begin();
    ListenerVector::iterator    end = listeners.end();

    while (it != end) {
        (*it)->onStop();
        ++it;
    }
}

/*------------------------------------------------------------------------------
 *  An EOS event handler, that will put the pipeline to EOS as well.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: eosEventHandler(GstElement    * element,
                                   gpointer        self)
                                                                throw ()
{
    GstreamerPlayer   * player = (GstreamerPlayer*) self;

    gst_element_set_eos(player->pipeline);
    player->fireOnStopEvent();
}

/*------------------------------------------------------------------------------
 *  Specify which file to play
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: open(const std::string   fileUrl)
                                                throw (std::invalid_argument,
                                                       std::runtime_error)
{
    // GStreamer pipeline overview:
    // filesrc -> decoder -> audioconvert -> audioscale -> audiosink

    DEBUG_BLOCK

    std::string     filePath;
    GstElement    * pipe;
    GstElement    * fakesink;
    gint64          position;

    if (isOpen()) {
        close();
    }

    if (fileUrl.find("file://") == 0) {
        filePath = fileUrl.substr(7, fileUrl.size());
    }
    else if (fileUrl.find("file:") == 0) {
        filePath = fileUrl.substr(5, fileUrl.size());
    }
    else {
        throw std::invalid_argument("badly formed URL or unsupported protocol");
    }

    filesrc    = gst_element_factory_make("filesrc", "file-source");
    gst_element_set(filesrc, "location", filePath.c_str(), NULL);

    decoder = ls_gst_autoplug_plug_source(filesrc, "decoder", sinkCaps);

    if (!decoder) {
        throw std::invalid_argument(std::string("can't open URL ") + fileUrl);
    }

    // connect the decoder unto a fakesink, and iterate on it until the
    // first bytes come out. this is to make sure that _really_ all
    // initialiation is done at opening
    pipe     = gst_pipeline_new("pipe");
    fakesink = gst_element_factory_make("fakesink", "fakesink");
    gst_object_ref(GST_OBJECT(filesrc));
    gst_object_ref(GST_OBJECT(decoder));
    gst_element_link_many(decoder, fakesink, NULL);
    gst_bin_add_many(GST_BIN(pipe), filesrc, decoder, fakesink, NULL);

    gst_element_set_state(pipe, GST_STATE_PLAYING);

    position = 0LL;
    while (position == 0LL && gst_bin_iterate(GST_BIN(pipe))) {
        GstFormat   format = GST_FORMAT_DEFAULT;
        gst_element_query(fakesink, GST_QUERY_POSITION, &format, &position);
    }

    gst_element_set_state(pipe, GST_STATE_PAUSED);
    gst_bin_remove_many(GST_BIN(pipe), filesrc, decoder, NULL);
    gst_element_unlink(decoder, fakesink);
    gst_object_unref(GST_OBJECT(pipe));

    // converts between different audio formats (e.g. bitrate)
    audioconvert    = gst_element_factory_make("audioconvert", NULL);

    // scale the sampling rate, if necessary
    audioscale      = gst_element_factory_make("audioscale", NULL);

    gst_bin_add_many(GST_BIN(pipeline), filesrc,
                                        decoder,
                                        audioconvert,
                                        audioscale,
                                        NULL);
    gst_element_link_many(decoder,
                          audioconvert,
                          audioscale,
                          audiosink,
                          NULL);

    // connect the eos signal handler
    g_signal_connect(decoder, "eos", G_CALLBACK(eosEventHandler), this);

    if (gst_element_set_state(pipeline,GST_STATE_PAUSED) == GST_STATE_FAILURE) {
        close();
        // the error is most probably caused by not being able to open
        // the audio device (as it might be blocked by an other process
        throw std::runtime_error("can't open audio device " + audioDevice);
    }
    gst_bin_sync_children_state(GST_BIN(pipeline));
}

/*------------------------------------------------------------------------------
 *  Tell if we've been opened.
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: isOpen(void)                                 throw ()
{
    return decoder != 0;
}

/*------------------------------------------------------------------------------
 *  Get the length of the current audio clip.
 *----------------------------------------------------------------------------*/
Ptr<time_duration>::Ref
GstreamerPlayer :: getPlaylength(void)              throw (std::logic_error)
{
    Ptr<time_duration>::Ref   length;
    gint64                    ns;
    GstFormat                 format = GST_FORMAT_TIME;

    if (!isOpen()) {
        throw std::logic_error("player not open");
    }

    if (decoder
     && gst_element_query(decoder, GST_QUERY_TOTAL, &format, &ns)
     && format == GST_FORMAT_TIME) {

        // use microsec, as nanosec() is not found by the compiler (?)
        length.reset(new time_duration(microsec(ns / 1000LL)));
    } else {
        length.reset(new time_duration(microsec(0LL)));
    }

    return length;
}

/*------------------------------------------------------------------------------
 *  Get the current position of the current audio clip.
 *----------------------------------------------------------------------------*/
Ptr<time_duration>::Ref
GstreamerPlayer :: getPosition(void)                throw (std::logic_error)
{
    Ptr<time_duration>::Ref   length;
    gint64                    ns;

    if (!isOpen()) {
        throw std::logic_error("player not open");
    }

    ns = ls_gst_autoplug_get_position(decoder);

    // this is necessary for boost version < 1.33.0
    gint64      us      = ns / 1000LL;
    long        s       = us / 1000000LL;
    long        frac_s  = us % 1000000LL;
    length.reset(new time_duration(seconds(s) + microseconds(frac_s)));

    // if we can be sure that boost >= 1.33.0, then we can write this instead:
    // length.reset(new time_duration(microseconds(ns / 1000LL)));

    return length;
}

/*------------------------------------------------------------------------------
 *  Start playing
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: start(void)                      throw (std::logic_error)
{
    DEBUG_BLOCK

    if (!isOpen()) {
        throw std::logic_error("GstreamerPlayer not opened yet");
    }

    if (!isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_PLAYING);
    }
}

/*------------------------------------------------------------------------------
 *  Pause the player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: pause(void)                      throw (std::logic_error)
{
    if (isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_PAUSED);
    }
}

/*------------------------------------------------------------------------------
 *  Tell if we're playing
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: isPlaying(void)                  throw ()
{
    return gst_element_get_state(pipeline) == GST_STATE_PLAYING;
}

/*------------------------------------------------------------------------------
 *  Stop playing
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: stop(void)                       throw (std::logic_error)
{
    if (!isOpen()) {
        throw std::logic_error("GstreamerPlayer not opened yet");
    }

    if (isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_READY);
    }
}

/*------------------------------------------------------------------------------
 *  Close the currently opened audio file.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: close(void)                       throw (std::logic_error)
{
    DEBUG_FUNC_INFO

    if (isPlaying()) {
        stop();
    }

    gst_element_set_state(pipeline, GST_STATE_NULL);

    // Unlink elements:
    if (filesrc && decoder) {
        gst_element_unlink(filesrc, decoder);
    }
    if (decoder && audioconvert) {
        gst_element_unlink(decoder, audioconvert);
    }
    if (audioconvert && audioscale ) {
        gst_element_unlink(audioconvert, audioscale);
    }
    if (audioscale && audiosink) {
        gst_element_unlink(audioscale, audiosink);
    }

    // Remove elements from pipeline:
    if (audioscale) {
        gst_bin_remove(GST_BIN(pipeline), audioscale);
    }
    if (audioconvert) {
        gst_bin_remove(GST_BIN(pipeline), audioconvert);
    }
    if (decoder) {
        gst_bin_remove(GST_BIN(pipeline), decoder);
    }
    if (filesrc) {
        gst_bin_remove(GST_BIN(pipeline), filesrc);
    }

    filesrc         = 0;
    decoder         = 0;
    audioconvert    = 0;
    audioscale      = 0;
}

/*------------------------------------------------------------------------------
 *  Get the volume of the player. *Unimplemented*: Feature is currently not used.
 *----------------------------------------------------------------------------*/
unsigned int
GstreamerPlayer :: getVolume(void)                                  throw ()
{
    return 0;
}

/*------------------------------------------------------------------------------
 *  Set the volume of the player. *Unimplemented*: Feature is currently not used.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: setVolume(unsigned int   volume)                 throw ()
{}

/*------------------------------------------------------------------------------
 *  Set the audio device.
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: setAudioDevice(const std::string &deviceName)
                                                                throw ()
{
    DEBUG_BLOCK

    if (deviceName.size() == 0) {
        return false;
    }

    const bool oss = deviceName.find("/dev") == 0;

    if (audiosink) {
        debug() << "Destroying old sink." << endl;
        if (audioscale) {
            gst_element_unlink(audioscale, audiosink);
        }
        gst_bin_remove(GST_BIN(pipeline), audiosink);
        audiosink = 0;
    }

    if (!audiosink) {
        audiosink = (oss ? gst_element_factory_make("osssink", "osssink")
                         : gst_element_factory_make("alsasink", "alsasink"));
    }
    if (!audiosink) {
        return false;
    }

    // it's the same property, "device" for both alsasink and osssink
    gst_element_set(audiosink, "device", deviceName.c_str(), NULL);

    if (audioscale) {
        gst_element_link_filtered(audioscale, audiosink, sinkCaps);
    }
    gst_bin_add(GST_BIN(pipeline), audiosink);
    gst_bin_sync_children_state(GST_BIN(pipeline));

    return true;
}

<commit_msg>Output the current file URL to debug.<commit_after>/*------------------------------------------------------------------------------

    Copyright (c) 2004 Media Development Loan Fund

    This file is part of the Campcaster project.
    http://campcaster.campware.org/
    To report bugs, send an e-mail to bugs@campware.org

    Campcaster 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.

    Campcaster 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 Campcaster; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Author   : $Author$
    Version  : $Revision$
    Location : $URL$

------------------------------------------------------------------------------*/

/* ============================================================ include files */

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

#define DEBUG_PREFIX "GstreamerPlayer"
#include "LiveSupport/Core/Debug.h"

#include "LiveSupport/Core/TimeConversion.h"
#include "LiveSupport/GstreamerElements/autoplug.h"
#include "GstreamerPlayer.h"

using namespace boost::posix_time;
using namespace LiveSupport::Core;
using namespace LiveSupport::PlaylistExecutor;

/* ===================================================  local data structures */

/* ================================================  local constants & macros */

/**
 *  The name of the config element for this class
 */
const std::string GstreamerPlayer::configElementNameStr = "gstreamerPlayer";

/**
 *  The name of the audio device attribute.
 */
static const std::string    audioDeviceName = "audioDevice";

/* ===============================================  local function prototypes */

/* =============================================================  module code */

/*------------------------------------------------------------------------------
 *  Configure the Audio Player.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: configure(const xmlpp::Element   &  element)
                                                throw (std::invalid_argument,
                                                       std::logic_error)
{
    DEBUG_FUNC_INFO

    if (element.get_name() != configElementNameStr) {
        std::string eMsg = "Bad configuration element ";
        eMsg += element.get_name();
        throw std::invalid_argument(eMsg);
    }

    const xmlpp::Attribute    * attribute = 0;

    if ((attribute = element.get_attribute(audioDeviceName))) {
        audioDevice = attribute->get_value();
    }
}

/*------------------------------------------------------------------------------
 *  Initialize the Audio Player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: initialize(void)                 throw (std::exception)
{
    DEBUG_FUNC_INFO

    if (initialized) {
        return;
    }

    // initialize the gstreamer library
    if (!gst_init_check(0, 0)) {
        throw std::runtime_error("couldn't initialize the gstreamer library");
    }

    // create the pipeline container (threaded)
    pipeline   = gst_thread_new("audio-player");

    filesrc         = 0;
    decoder         = 0;
    audioconvert    = 0;
    audioscale      = 0;

    g_signal_connect(pipeline, "error", G_CALLBACK(errorHandler), this);

    // TODO: read the caps from the config file
    sinkCaps = gst_caps_new_simple("audio/x-raw-int",
                                   "width", G_TYPE_INT, 16,
                                   "depth", G_TYPE_INT, 16,
                                   "endiannes", G_TYPE_INT, G_BYTE_ORDER,
                                   "channels", G_TYPE_INT, 2,
                                   "rate", G_TYPE_INT, 44100,
                                   NULL);

    setAudioDevice(audioDevice);

    // set up other variables
    initialized = true;
}

/*------------------------------------------------------------------------------
 *  Handler for gstreamer errors.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: errorHandler(GstElement   * pipeline,
                                GstElement   * source,
                                GError       * error,
                                gchar        * debug,
                                gpointer       self)
                                                                throw ()
{
    // TODO: handle error
    std::cerr << "gstreamer error: " << error->message << std::endl;
}

/*------------------------------------------------------------------------------
 *  De-initialize the Gstreamer Player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: deInitialize(void)                       throw ()
{
    DEBUG_FUNC_INFO

    if (initialized) {
        gst_element_set_state(pipeline, GST_STATE_NULL);
        gst_bin_sync_children_state(GST_BIN(pipeline));

        if (!gst_element_get_parent(audiosink)) {
            // delete manually, if audiosink wasn't added to the pipeline
            // for some reason
            gst_object_unref(GST_OBJECT(audiosink));
        }
        gst_object_unref(GST_OBJECT(pipeline));
        gst_caps_free(sinkCaps);

        audiosink   = 0;
        initialized = false;
    }
}

/*------------------------------------------------------------------------------
 *  Attach an event listener.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: attachListener(AudioPlayerEventListener*     eventListener)
                                                                    throw ()
{
    listeners.push_back(eventListener);
}

/*------------------------------------------------------------------------------
 *  Detach an event listener.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: detachListener(AudioPlayerEventListener*     eventListener)
                                                throw (std::invalid_argument)
{
    ListenerVector::iterator    it  = listeners.begin();
    ListenerVector::iterator    end = listeners.end();

    while (it != end) {
        if (*it == eventListener) {
            listeners.erase(it);
            return;
        }
        ++it;
    }

    throw std::invalid_argument("supplied event listener not found");
}

/*------------------------------------------------------------------------------
 *  Send the onStop event to all attached listeners.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: fireOnStopEvent(void)                        throw ()
{
    ListenerVector::iterator    it  = listeners.begin();
    ListenerVector::iterator    end = listeners.end();

    while (it != end) {
        (*it)->onStop();
        ++it;
    }
}

/*------------------------------------------------------------------------------
 *  An EOS event handler, that will put the pipeline to EOS as well.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: eosEventHandler(GstElement    * element,
                                   gpointer        self)
                                                                throw ()
{
    GstreamerPlayer   * player = (GstreamerPlayer*) self;

    gst_element_set_eos(player->pipeline);
    player->fireOnStopEvent();
}

/*------------------------------------------------------------------------------
 *  Specify which file to play
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: open(const std::string   fileUrl)
                                                throw (std::invalid_argument,
                                                       std::runtime_error)
{
    // GStreamer pipeline overview:
    // filesrc -> decoder -> audioconvert -> audioscale -> audiosink

    DEBUG_BLOCK

    std::string     filePath;
    GstElement    * pipe;
    GstElement    * fakesink;
    gint64          position;

    if (isOpen()) {
        close();
    }

    debug() << "Opening URL: " << fileUrl << endl;

    if (fileUrl.find("file://") == 0) {
        filePath = fileUrl.substr(7, fileUrl.size());
    }
    else if (fileUrl.find("file:") == 0) {
        filePath = fileUrl.substr(5, fileUrl.size());
    }
    else {
        throw std::invalid_argument("badly formed URL or unsupported protocol");
    }

    filesrc    = gst_element_factory_make("filesrc", "file-source");
    gst_element_set(filesrc, "location", filePath.c_str(), NULL);

    decoder = ls_gst_autoplug_plug_source(filesrc, "decoder", sinkCaps);

    if (!decoder) {
        throw std::invalid_argument(std::string("can't open URL ") + fileUrl);
    }

    // connect the decoder unto a fakesink, and iterate on it until the
    // first bytes come out. this is to make sure that _really_ all
    // initialiation is done at opening
    pipe     = gst_pipeline_new("pipe");
    fakesink = gst_element_factory_make("fakesink", "fakesink");
    gst_object_ref(GST_OBJECT(filesrc));
    gst_object_ref(GST_OBJECT(decoder));
    gst_element_link_many(decoder, fakesink, NULL);
    gst_bin_add_many(GST_BIN(pipe), filesrc, decoder, fakesink, NULL);

    gst_element_set_state(pipe, GST_STATE_PLAYING);

    position = 0LL;
    while (position == 0LL && gst_bin_iterate(GST_BIN(pipe))) {
        GstFormat   format = GST_FORMAT_DEFAULT;
        gst_element_query(fakesink, GST_QUERY_POSITION, &format, &position);
    }

    gst_element_set_state(pipe, GST_STATE_PAUSED);
    gst_bin_remove_many(GST_BIN(pipe), filesrc, decoder, NULL);
    gst_element_unlink(decoder, fakesink);
    gst_object_unref(GST_OBJECT(pipe));

    // converts between different audio formats (e.g. bitrate)
    audioconvert    = gst_element_factory_make("audioconvert", NULL);

    // scale the sampling rate, if necessary
    audioscale      = gst_element_factory_make("audioscale", NULL);

    gst_bin_add_many(GST_BIN(pipeline), filesrc,
                                        decoder,
                                        audioconvert,
                                        audioscale,
                                        NULL);
    gst_element_link_many(decoder,
                          audioconvert,
                          audioscale,
                          audiosink,
                          NULL);

    // connect the eos signal handler
    g_signal_connect(decoder, "eos", G_CALLBACK(eosEventHandler), this);

    if (gst_element_set_state(pipeline,GST_STATE_PAUSED) == GST_STATE_FAILURE) {
        close();
        // the error is most probably caused by not being able to open
        // the audio device (as it might be blocked by an other process
        throw std::runtime_error("can't open audio device " + audioDevice);
    }
    gst_bin_sync_children_state(GST_BIN(pipeline));
}

/*------------------------------------------------------------------------------
 *  Tell if we've been opened.
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: isOpen(void)                                 throw ()
{
    return decoder != 0;
}

/*------------------------------------------------------------------------------
 *  Get the length of the current audio clip.
 *----------------------------------------------------------------------------*/
Ptr<time_duration>::Ref
GstreamerPlayer :: getPlaylength(void)              throw (std::logic_error)
{
    Ptr<time_duration>::Ref   length;
    gint64                    ns;
    GstFormat                 format = GST_FORMAT_TIME;

    if (!isOpen()) {
        throw std::logic_error("player not open");
    }

    if (decoder
     && gst_element_query(decoder, GST_QUERY_TOTAL, &format, &ns)
     && format == GST_FORMAT_TIME) {

        // use microsec, as nanosec() is not found by the compiler (?)
        length.reset(new time_duration(microsec(ns / 1000LL)));
    } else {
        length.reset(new time_duration(microsec(0LL)));
    }

    return length;
}

/*------------------------------------------------------------------------------
 *  Get the current position of the current audio clip.
 *----------------------------------------------------------------------------*/
Ptr<time_duration>::Ref
GstreamerPlayer :: getPosition(void)                throw (std::logic_error)
{
    Ptr<time_duration>::Ref   length;
    gint64                    ns;

    if (!isOpen()) {
        throw std::logic_error("player not open");
    }

    ns = ls_gst_autoplug_get_position(decoder);

    // this is necessary for boost version < 1.33.0
    gint64      us      = ns / 1000LL;
    long        s       = us / 1000000LL;
    long        frac_s  = us % 1000000LL;
    length.reset(new time_duration(seconds(s) + microseconds(frac_s)));

    // if we can be sure that boost >= 1.33.0, then we can write this instead:
    // length.reset(new time_duration(microseconds(ns / 1000LL)));

    return length;
}

/*------------------------------------------------------------------------------
 *  Start playing
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: start(void)                      throw (std::logic_error)
{
    DEBUG_BLOCK

    if (!isOpen()) {
        throw std::logic_error("GstreamerPlayer not opened yet");
    }

    if (!isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_PLAYING);
    }
}

/*------------------------------------------------------------------------------
 *  Pause the player
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: pause(void)                      throw (std::logic_error)
{
    if (isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_PAUSED);
    }
}

/*------------------------------------------------------------------------------
 *  Tell if we're playing
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: isPlaying(void)                  throw ()
{
    return gst_element_get_state(pipeline) == GST_STATE_PLAYING;
}

/*------------------------------------------------------------------------------
 *  Stop playing
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: stop(void)                       throw (std::logic_error)
{
    if (!isOpen()) {
        throw std::logic_error("GstreamerPlayer not opened yet");
    }

    if (isPlaying()) {
        gst_element_set_state(pipeline, GST_STATE_READY);
    }
}

/*------------------------------------------------------------------------------
 *  Close the currently opened audio file.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: close(void)                       throw (std::logic_error)
{
    DEBUG_FUNC_INFO

    if (isPlaying()) {
        stop();
    }

    gst_element_set_state(pipeline, GST_STATE_NULL);

    // Unlink elements:
    if (filesrc && decoder) {
        gst_element_unlink(filesrc, decoder);
    }
    if (decoder && audioconvert) {
        gst_element_unlink(decoder, audioconvert);
    }
    if (audioconvert && audioscale ) {
        gst_element_unlink(audioconvert, audioscale);
    }
    if (audioscale && audiosink) {
        gst_element_unlink(audioscale, audiosink);
    }

    // Remove elements from pipeline:
    if (audioscale) {
        gst_bin_remove(GST_BIN(pipeline), audioscale);
    }
    if (audioconvert) {
        gst_bin_remove(GST_BIN(pipeline), audioconvert);
    }
    if (decoder) {
        gst_bin_remove(GST_BIN(pipeline), decoder);
    }
    if (filesrc) {
        gst_bin_remove(GST_BIN(pipeline), filesrc);
    }

    filesrc         = 0;
    decoder         = 0;
    audioconvert    = 0;
    audioscale      = 0;
}

/*------------------------------------------------------------------------------
 *  Get the volume of the player. *Unimplemented*: Feature is currently not used.
 *----------------------------------------------------------------------------*/
unsigned int
GstreamerPlayer :: getVolume(void)                                  throw ()
{
    return 0;
}

/*------------------------------------------------------------------------------
 *  Set the volume of the player. *Unimplemented*: Feature is currently not used.
 *----------------------------------------------------------------------------*/
void
GstreamerPlayer :: setVolume(unsigned int   volume)                 throw ()
{}

/*------------------------------------------------------------------------------
 *  Set the audio device.
 *----------------------------------------------------------------------------*/
bool
GstreamerPlayer :: setAudioDevice(const std::string &deviceName)
                                                                throw ()
{
    DEBUG_BLOCK

    if (deviceName.size() == 0) {
        return false;
    }

    const bool oss = deviceName.find("/dev") == 0;

    if (audiosink) {
        debug() << "Destroying old sink." << endl;
        if (audioscale) {
            gst_element_unlink(audioscale, audiosink);
        }
        gst_bin_remove(GST_BIN(pipeline), audiosink);
        audiosink = 0;
    }

    if (!audiosink) {
        audiosink = (oss ? gst_element_factory_make("osssink", "osssink")
                         : gst_element_factory_make("alsasink", "alsasink"));
    }
    if (!audiosink) {
        return false;
    }

    // it's the same property, "device" for both alsasink and osssink
    gst_element_set(audiosink, "device", deviceName.c_str(), NULL);

    if (audioscale) {
        gst_element_link_filtered(audioscale, audiosink, sinkCaps);
    }
    gst_bin_add(GST_BIN(pipeline), audiosink);
    gst_bin_sync_children_state(GST_BIN(pipeline));

    return true;
}

<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2011 Jose Fonseca
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

#include "glimports.hpp"
#include "glws.hpp"

namespace glws {

class WglDrawable : public Drawable
{
public:
    DWORD dwExStyle;
    DWORD dwStyle;
    HWND hWnd;
    HDC hDC;
    PIXELFORMATDESCRIPTOR pfd;
    int iPixelFormat;

    WglDrawable(const Visual *vis) :
        Drawable(vis)
    {
        static bool first = TRUE;
        RECT rect;

        if (first) {
            WNDCLASS wc;
            memset(&wc, 0, sizeof wc);
            wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
            wc.hCursor = LoadCursor(NULL, IDC_ARROW);
            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
            wc.lpfnWndProc = DefWindowProc;
            wc.lpszClassName = "glretrace";
            wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
            RegisterClass(&wc);
            first = FALSE;
        }

        dwExStyle = 0;
        dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;

        int x = 0, y = 0, width = 256, height = 256;

        rect.left = x;
        rect.top = y;
        rect.right = rect.left + width;
        rect.bottom = rect.top + height;

        AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);

        hWnd = CreateWindowEx(dwExStyle,
                              "glretrace", /* wc.lpszClassName */
                              NULL,
                              dwStyle,
                              CW_USEDEFAULT, /* x */
                              CW_USEDEFAULT, /* y */
                              rect.right - rect.left, /* width */
                              rect.bottom - rect.top, /* height */
                              NULL,
                              NULL,
                              NULL,
                              NULL);
        hDC = GetDC(hWnd);

        memset(&pfd, 0, sizeof pfd);
        pfd.cColorBits = 3;
        pfd.cRedBits = 1;
        pfd.cGreenBits = 1;
        pfd.cBlueBits = 1;
        pfd.cDepthBits = 1;
        pfd.cStencilBits = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
        pfd.iLayerType = PFD_MAIN_PLANE;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.nSize = sizeof(pfd);
        pfd.nVersion = 1;

        if (visual->doubleBuffer) {
           pfd.dwFlags |= PFD_DOUBLEBUFFER;
        }

        iPixelFormat = ChoosePixelFormat(hDC, &pfd);

        SetPixelFormat(hDC, iPixelFormat, &pfd);
    }

    ~WglDrawable() {
        ReleaseDC(hWnd, hDC);
        DestroyWindow(hWnd);
    }

    void
    resize(unsigned w, unsigned h) {
        Drawable::resize(w, h);
        RECT rClient, rWindow;
        GetClientRect(hWnd, &rClient);
        GetWindowRect(hWnd, &rWindow);
        w += (rWindow.right  - rWindow.left) - rClient.right;
        h += (rWindow.bottom - rWindow.top)  - rClient.bottom;
        MoveWindow(hWnd, rWindow.left, rWindow.top, w, h, TRUE);
    }

    void swapBuffers(void) {
        SwapBuffers(hDC);
    }
};

class WglContext : public Context
{
public:
    HGLRC hglrc;

    WglContext(const Visual *vis) :
        Context(vis),
        hglrc(0)
    {}

    ~WglContext() {
        if (hglrc) {
            wglDeleteContext(hglrc);
        }
    }
};

class WglWindowSystem : public WindowSystem
{
public:
    Visual *
    createVisual(bool doubleBuffer) {
        Visual *visual = new Visual();

        visual->doubleBuffer = doubleBuffer;

        return visual;
    }

    Drawable *
    createDrawable(const Visual *visual)
    {
        return new WglDrawable(visual);
    }

    Context *
    createContext(const Visual *visual)
    {
        return new WglContext(visual);
    }

    bool
    makeCurrent(Drawable *drawable, Context *context)
    {
        if (!drawable || !context) {
            return wglMakeCurrent(NULL, NULL);
        } else {
            WglDrawable *wglDrawable = dynamic_cast<WglDrawable *>(drawable);
            WglContext *wglContext = dynamic_cast<WglContext *>(context);

            if (!wglContext->hglrc) {
                wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
                if (!wglContext->hglrc) {
                    return false;
                }
            }

            return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
        }
    }

    bool
    processEvents(void) {
        // TODO
        return true;
    }
};

WindowSystem *createNativeWindowSystem(void) {
    return new WglWindowSystem();
}

} /* namespace glretrace */
<commit_msg>Allow to resize the window to be larger than the desktop.<commit_after>/**************************************************************************
 *
 * Copyright 2011 Jose Fonseca
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 **************************************************************************/

#include "glimports.hpp"
#include "glws.hpp"

namespace glws {

static LRESULT CALLBACK
WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    MINMAXINFO *pMMI;
    switch (uMsg) {
    case WM_GETMINMAXINFO:
        // Allow to create a window bigger than the desktop
        pMMI = (MINMAXINFO *)lParam;
        pMMI->ptMaxSize.x = 60000;
        pMMI->ptMaxSize.y = 60000;
        pMMI->ptMaxTrackSize.x = 60000;
        pMMI->ptMaxTrackSize.y = 60000;
        break;
    default:
        break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

class WglDrawable : public Drawable
{
public:
    DWORD dwExStyle;
    DWORD dwStyle;
    HWND hWnd;
    HDC hDC;
    PIXELFORMATDESCRIPTOR pfd;
    int iPixelFormat;

    WglDrawable(const Visual *vis) :
        Drawable(vis)
    {
        static bool first = TRUE;
        RECT rect;

        if (first) {
            WNDCLASS wc;
            memset(&wc, 0, sizeof wc);
            wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
            wc.hCursor = LoadCursor(NULL, IDC_ARROW);
            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
            wc.lpfnWndProc = WndProc;
            wc.lpszClassName = "glretrace";
            wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
            RegisterClass(&wc);
            first = FALSE;
        }

        dwExStyle = 0;
        dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;

        int x = 0, y = 0, width = 256, height = 256;

        rect.left = x;
        rect.top = y;
        rect.right = rect.left + width;
        rect.bottom = rect.top + height;

        AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);

        hWnd = CreateWindowEx(dwExStyle,
                              "glretrace", /* wc.lpszClassName */
                              NULL,
                              dwStyle,
                              0, /* x */
                              0, /* y */
                              rect.right - rect.left, /* width */
                              rect.bottom - rect.top, /* height */
                              NULL,
                              NULL,
                              NULL,
                              NULL);
        hDC = GetDC(hWnd);

        memset(&pfd, 0, sizeof pfd);
        pfd.cColorBits = 3;
        pfd.cRedBits = 1;
        pfd.cGreenBits = 1;
        pfd.cBlueBits = 1;
        pfd.cDepthBits = 1;
        pfd.cStencilBits = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
        pfd.iLayerType = PFD_MAIN_PLANE;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.nSize = sizeof(pfd);
        pfd.nVersion = 1;

        if (visual->doubleBuffer) {
           pfd.dwFlags |= PFD_DOUBLEBUFFER;
        }

        iPixelFormat = ChoosePixelFormat(hDC, &pfd);

        SetPixelFormat(hDC, iPixelFormat, &pfd);
    }

    ~WglDrawable() {
        ReleaseDC(hWnd, hDC);
        DestroyWindow(hWnd);
    }

    void
    resize(unsigned w, unsigned h) {
        Drawable::resize(w, h);
        RECT rClient, rWindow;
        GetClientRect(hWnd, &rClient);
        GetWindowRect(hWnd, &rWindow);
        w += (rWindow.right  - rWindow.left) - rClient.right;
        h += (rWindow.bottom - rWindow.top)  - rClient.bottom;
        SetWindowPos(hWnd, NULL, rWindow.left, rWindow.top, w, h, SWP_NOMOVE);
    }

    void swapBuffers(void) {
        SwapBuffers(hDC);
    }
};

class WglContext : public Context
{
public:
    HGLRC hglrc;

    WglContext(const Visual *vis) :
        Context(vis),
        hglrc(0)
    {}

    ~WglContext() {
        if (hglrc) {
            wglDeleteContext(hglrc);
        }
    }
};

class WglWindowSystem : public WindowSystem
{
public:
    Visual *
    createVisual(bool doubleBuffer) {
        Visual *visual = new Visual();

        visual->doubleBuffer = doubleBuffer;

        return visual;
    }

    Drawable *
    createDrawable(const Visual *visual)
    {
        return new WglDrawable(visual);
    }

    Context *
    createContext(const Visual *visual)
    {
        return new WglContext(visual);
    }

    bool
    makeCurrent(Drawable *drawable, Context *context)
    {
        if (!drawable || !context) {
            return wglMakeCurrent(NULL, NULL);
        } else {
            WglDrawable *wglDrawable = dynamic_cast<WglDrawable *>(drawable);
            WglContext *wglContext = dynamic_cast<WglContext *>(context);

            if (!wglContext->hglrc) {
                wglContext->hglrc = wglCreateContext(wglDrawable->hDC);
                if (!wglContext->hglrc) {
                    return false;
                }
            }

            return wglMakeCurrent(wglDrawable->hDC, wglContext->hglrc);
        }
    }

    bool
    processEvents(void) {
        // TODO
        return true;
    }
};

WindowSystem *createNativeWindowSystem(void) {
    return new WglWindowSystem();
}

} /* namespace glretrace */
<|endoftext|>


<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"
#include "SkBlurMaskFilter.h"

namespace skiagm {

class BlursGM : public GM {
public:
    BlursGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    virtual SkString onShortName() {
        return SkString("blurs");
    }

    virtual SkISize onISize() {
        return make_isize(700, 500);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkBlurMaskFilter::BlurStyle NONE = SkBlurMaskFilter::BlurStyle(-999);
        static const struct {
            SkBlurMaskFilter::BlurStyle fStyle;
            int                         fCx, fCy;
        } gRecs[] = {
            { NONE,                                 0,  0 },
            { SkBlurMaskFilter::kInner_BlurStyle,  -1,  0 },
            { SkBlurMaskFilter::kNormal_BlurStyle,  0,  1 },
            { SkBlurMaskFilter::kSolid_BlurStyle,   0, -1 },
            { SkBlurMaskFilter::kOuter_BlurStyle,   1,  0 },
        };

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(25));
        canvas->translate(SkIntToScalar(-40), SkIntToScalar(0));

        SkBlurMaskFilter::BlurFlags flags = SkBlurMaskFilter::kNone_BlurFlag;
        for (int j = 0; j < 2; j++) {
            canvas->save();
            paint.setColor(SK_ColorBLUE);
            for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
                if (gRecs[i].fStyle != NONE) {
                    SkMaskFilter* mf = SkBlurMaskFilter::Create(
                            SkIntToScalar(20), gRecs[i].fStyle, flags
                    );
                    paint.setMaskFilter(mf)->unref();
                } else {
                    paint.setMaskFilter(NULL);
                }
                canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100)
                                   , SkIntToScalar(200 + gRecs[i].fCy*100)
                                   , SkIntToScalar(50)
                                   , paint);
            }
            // draw text
            {
                SkMaskFilter* mf = SkBlurMaskFilter::Create(
                        SkIntToScalar(4)
                        , SkBlurMaskFilter::kNormal_BlurStyle
                        , flags
                );
                paint.setMaskFilter(mf)->unref();
                SkScalar x = SkIntToScalar(70);
                SkScalar y = SkIntToScalar(400);
                paint.setColor(SK_ColorBLACK);
                canvas->drawText("Hamburgefons Style", 18, x, y, paint);
                canvas->drawText("Hamburgefons Style", 18
                                 , x, y + SkIntToScalar(50), paint);
                paint.setMaskFilter(NULL);
                paint.setColor(SK_ColorWHITE);
                x -= SkIntToScalar(2);
                y -= SkIntToScalar(2);
                canvas->drawText("Hamburgefons Style", 18, x, y, paint);
            }
            canvas->restore();
            flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
            canvas->translate(SkIntToScalar(350), SkIntToScalar(0));
        }
    }

private:
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new BlursGM; }
static GMRegistry reg(MyFactory);

}

<commit_msg>Turn off the blurs GM for Pipe playback.<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "gm.h"
#include "SkBlurMaskFilter.h"

namespace skiagm {

class BlursGM : public GM {
public:
    BlursGM() {
        this->setBGColor(0xFFDDDDDD);
    }

protected:
    virtual uint32_t onGetFlags() const SK_OVERRIDE {
        return this->INHERITED::onGetFlags() | GM::kSkipPipe_Flag;
    }

    virtual SkString onShortName() {
        return SkString("blurs");
    }

    virtual SkISize onISize() {
        return make_isize(700, 500);
    }

    virtual void onDraw(SkCanvas* canvas) {
        SkBlurMaskFilter::BlurStyle NONE = SkBlurMaskFilter::BlurStyle(-999);
        static const struct {
            SkBlurMaskFilter::BlurStyle fStyle;
            int                         fCx, fCy;
        } gRecs[] = {
            { NONE,                                 0,  0 },
            { SkBlurMaskFilter::kInner_BlurStyle,  -1,  0 },
            { SkBlurMaskFilter::kNormal_BlurStyle,  0,  1 },
            { SkBlurMaskFilter::kSolid_BlurStyle,   0, -1 },
            { SkBlurMaskFilter::kOuter_BlurStyle,   1,  0 },
        };

        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(25));
        canvas->translate(SkIntToScalar(-40), SkIntToScalar(0));

        SkBlurMaskFilter::BlurFlags flags = SkBlurMaskFilter::kNone_BlurFlag;
        for (int j = 0; j < 2; j++) {
            canvas->save();
            paint.setColor(SK_ColorBLUE);
            for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
                if (gRecs[i].fStyle != NONE) {
                    SkMaskFilter* mf = SkBlurMaskFilter::Create(
                            SkIntToScalar(20), gRecs[i].fStyle, flags
                    );
                    paint.setMaskFilter(mf)->unref();
                } else {
                    paint.setMaskFilter(NULL);
                }
                canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100)
                                   , SkIntToScalar(200 + gRecs[i].fCy*100)
                                   , SkIntToScalar(50)
                                   , paint);
            }
            // draw text
            {
                SkMaskFilter* mf = SkBlurMaskFilter::Create(
                        SkIntToScalar(4)
                        , SkBlurMaskFilter::kNormal_BlurStyle
                        , flags
                );
                paint.setMaskFilter(mf)->unref();
                SkScalar x = SkIntToScalar(70);
                SkScalar y = SkIntToScalar(400);
                paint.setColor(SK_ColorBLACK);
                canvas->drawText("Hamburgefons Style", 18, x, y, paint);
                canvas->drawText("Hamburgefons Style", 18
                                 , x, y + SkIntToScalar(50), paint);
                paint.setMaskFilter(NULL);
                paint.setColor(SK_ColorWHITE);
                x -= SkIntToScalar(2);
                y -= SkIntToScalar(2);
                canvas->drawText("Hamburgefons Style", 18, x, y, paint);
            }
            canvas->restore();
            flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
            canvas->translate(SkIntToScalar(350), SkIntToScalar(0));
        }
    }

private:
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static GM* MyFactory(void*) { return new BlursGM; }
static GMRegistry reg(MyFactory);

}

<|endoftext|>


<commit_before>/************************************************************************/
/* XGPacket                                                             */
/*                                                                      */
/* XGrid Packet                                                         */
/*                                                                      */
/* XGPacket.cpp                                                         */
/*                                                                      */
/* Alex Forencich <alex@alexforencich.com>                              */
/*                                                                      */
/* Copyright (c) 2011 Alex Forencich                                    */
/*                                                                      */
/* Permission is hereby granted, free of charge, to any person          */
/* obtaining a copy of this software and associated documentation       */
/* files(the "Software"), to deal in the Software without restriction,  */
/* including without limitation the rights to use, copy, modify, merge, */
/* publish, distribute, sublicense, and/or sell copies of the Software, */
/* and to permit persons to whom the Software is furnished to do so,    */
/* subject to the following conditions:                                 */
/*                                                                      */
/* The above copyright notice and this permission notice shall be       */
/* included in all copies or substantial portions of the Software.      */
/*                                                                      */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
/* MEXGHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                            */
/*                                                                      */
/************************************************************************/

#include "XGPacket.h"

#include <sstream>
#include <iomanip>

XGPacket::XGPacket()
{
        zero();
}

XGPacket::~XGPacket()
{
        // nothing
}

void XGPacket::zero()
{
        source_id = 0;
        type = 0;
        seq = 0;
        flags = 0;
        radius = 0;
        data.clear();
}

uint16_t XGPacket::get_length()
{
        return data.size()+sizeof(xgrid_header_t);
}

std::vector<uint8_t> XGPacket::get_raw_packet()
{
        std::vector<uint8_t> dataout;

        dataout.push_back(XGRID_IDENTIFIER);
        dataout.push_back(payload.size());
        dataout.push_back(payload.size() >> 8);

        dataout.insert(dataout.end(), payload.begin(), payload.end());

        return dataout;
}

bool XGPacket::read_packet(std::vector<char> bytes, size_t &bytes_read)
{
        return read_packet((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(std::vector<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(std::deque<char> bytes, size_t &bytes_read)
{
        return read_packet((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(std::deque<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(uint8_t *bytes, size_t count, size_t &bytes_read)
{
        size_t n = 0;
        uint16_t size;
        uint8_t *ptr = bytes;
        uint8_t b;

        if (count == 0)
                return false;

        // find packet start byte
        while ((*(ptr++) != XGRID_IDENTIFIER) & (n++ < count)) { }

        // start of packet offset
        // to discard junk ahead of incomplete packet
        // (assuming packet is currently truncated)
        bytes_read = n-1;

        // return if out of buffer
        if (n > count)
                return false;

        // return if not enough bytes left
        if (count - n < sizeof(xgrid_header_t) + 2)
                return false;

        // get packet size
        size = (uint16_t)*(ptr++);
        size |= (uint16_t)*(ptr++) << 8;
        n += 2;

        // return if we don't have the whole packet
        if (count - n < size)
                return false;

        payload.clear();

        // read payload
        for (int i = 0; i < size; i++)
        {
                b = *(ptr++);
                payload.push_back(b);
                n++;
        }

        bytes_read = n;

        return true;
}

bool XGPacket::read_packet_bare(std::vector<char> bytes, size_t &bytes_read)
{
        return read_packet_bare((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::vector<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet_bare(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::deque<char> bytes, size_t &bytes_read)
{
        return read_packet_bare((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::deque<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet_bare(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(uint8_t *bytes, size_t count, size_t &bytes_read)
{
        size_t n = 0;
        uint8_t *ptr = bytes;
        uint8_t b;

        if (count < sizeof(xgrid_header_t))
                return false;

        payload.clear();

        // read payload
        for (int i = 0; i < count; i++)
        {
                b = *(ptr++);
                payload.push_back(b);
        }

        bytes_read = count;

        return true;
}

bool XGPacket::build_packet()
{
        payload.clear();
        payload.push_back(source_id);
        payload.push_back(source_id << 8);
        payload.push_back(type);
        payload.push_back(seq);
        payload.push_back(flags);
        payload.push_back(radius);

        for (int i = 0; i < data.size(); i++)
        {
                payload.push_back(data[i]);
        }

        return true;
}

bool XGPacket::decode_packet()
{
        if (payload.size() < sizeof(xgrid_header_t))
                return false;

        source_id = read_payload_uint16(0);
        type = payload[2];
        seq = payload[3];
        flags = payload[4];
        radius = payload[5];

        data.clear();
        for (int i = sizeof(xgrid_header_t); i < payload.size(); i++)
        {
                data.push_back(payload[i]);
        }

        return true;
}

std::string XGPacket::get_desc()
{
        std::stringstream desc;

        desc << "XGrid Packet" << std::endl;
        desc << "  Length: " << std::dec << get_length() << std::endl;
        desc << "  Source ID: 0x" << std::setfill('0') << std::setw(4) << std::hex << (int)source_id << std::endl;
        desc << "  Type: 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)type << std::endl;
        desc << "  Seq: " << std::dec << (int)seq << std::endl;
        desc << "  Flags: 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)flags << std::endl;
        desc << "  Radius: " << std::dec << (int)radius << std::endl;

        desc << "  Data (hex):";
        for (int i = 0; i < data.size(); i++)
        {
                if (i > 0 && i % 16 == 0)
                        desc << std::endl << "             ";
                desc << " " << std::setfill('0') << std::setw(2) << std::hex << (int)data[i];
        }
        desc << std::endl;

        return desc.str();
}

std::string XGPacket::get_hex_packet()
{
        std::vector<uint8_t> pkt = get_raw_packet();
        std::stringstream out;

        for (int i = 0; i < pkt.size(); i++)
        {
                if (i > 0)
                        out << " ";
                out << std::setfill('0') << std::setw(2) << std::hex << (int)pkt[i];
        }

        return out.str();
}

// read and write payload data
uint8_t XGPacket::read_payload_uint8(int offset)
{
        if (offset < 0)
                return 0;
        return payload[offset];
}

uint16_t XGPacket::read_payload_uint16(int offset)
{
        if (offset < 0)
                return 0;
        uint16_t value;
        value  = (uint16_t)payload[offset];
        value |= (uint16_t)payload[offset+1] << 8;
        return value;
}

uint32_t XGPacket::read_payload_uint32(int offset)
{
        if (offset < 0)
                return 0;
        uint32_t value;
        value  = (uint32_t)payload[offset];
        value |= (uint32_t)payload[offset+1] << 8;
        value |= (uint32_t)payload[offset+2] << 16;
        value |= (uint32_t)payload[offset+3] << 24;
        return value;
}

uint64_t XGPacket::read_payload_uint64(int offset)
{
        if (offset < 0)
                return 0;
        uint64_t value;
        value  = (uint64_t)payload[offset];
        value |= (uint64_t)payload[offset+1] << 8;
        value |= (uint64_t)payload[offset+2] << 16;
        value |= (uint64_t)payload[offset+3] << 24;
        value |= (uint64_t)payload[offset+4] << 32;
        value |= (uint64_t)payload[offset+5] << 40;
        value |= (uint64_t)payload[offset+6] << 48;
        value |= (uint64_t)payload[offset+7] << 56;
        return value;
}

void XGPacket::write_payload_uint8(int offset, uint8_t value)
{
        if (offset < 0)
                return;
        payload[offset] = value;
}

void XGPacket::write_payload_uint16(int offset, uint16_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
}

void XGPacket::write_payload_uint32(int offset, uint32_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
        payload[offset+2] = value >> 16;
        payload[offset+3] = value >> 24;
}

void XGPacket::write_payload_uint64(int offset, uint64_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
        payload[offset+2] = value >> 16;
        payload[offset+3] = value >> 24;
        payload[offset+4] = value >> 32;
        payload[offset+5] = value >> 40;
        payload[offset+6] = value >> 48;
        payload[offset+7] = value >> 56;
}

<commit_msg>Fixed deque cast issue<commit_after>/************************************************************************/
/* XGPacket                                                             */
/*                                                                      */
/* XGrid Packet                                                         */
/*                                                                      */
/* XGPacket.cpp                                                         */
/*                                                                      */
/* Alex Forencich <alex@alexforencich.com>                              */
/*                                                                      */
/* Copyright (c) 2011 Alex Forencich                                    */
/*                                                                      */
/* Permission is hereby granted, free of charge, to any person          */
/* obtaining a copy of this software and associated documentation       */
/* files(the "Software"), to deal in the Software without restriction,  */
/* including without limitation the rights to use, copy, modify, merge, */
/* publish, distribute, sublicense, and/or sell copies of the Software, */
/* and to permit persons to whom the Software is furnished to do so,    */
/* subject to the following conditions:                                 */
/*                                                                      */
/* The above copyright notice and this permission notice shall be       */
/* included in all copies or substantial portions of the Software.      */
/*                                                                      */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,      */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF   */
/* MEXGHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                */
/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS  */
/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN   */
/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN    */
/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                            */
/*                                                                      */
/************************************************************************/

#include "XGPacket.h"

#include <sstream>
#include <iomanip>

XGPacket::XGPacket()
{
        zero();
}

XGPacket::~XGPacket()
{
        // nothing
}

void XGPacket::zero()
{
        source_id = 0;
        type = 0;
        seq = 0;
        flags = 0;
        radius = 0;
        data.clear();
}

uint16_t XGPacket::get_length()
{
        return data.size()+sizeof(xgrid_header_t);
}

std::vector<uint8_t> XGPacket::get_raw_packet()
{
        std::vector<uint8_t> dataout;

        dataout.push_back(XGRID_IDENTIFIER);
        dataout.push_back(payload.size());
        dataout.push_back(payload.size() >> 8);

        dataout.insert(dataout.end(), payload.begin(), payload.end());

        return dataout;
}

bool XGPacket::read_packet(std::vector<char> bytes, size_t &bytes_read)
{
        return read_packet((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(std::vector<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet(std::deque<char> bytes, size_t &bytes_read)
{
        std::vector<char> v(bytes.begin(), bytes.end());
        return read_packet(v, bytes_read);
}

bool XGPacket::read_packet(std::deque<uint8_t> bytes, size_t &bytes_read)
{
        std::vector<uint8_t> v(bytes.begin(), bytes.end());
        return read_packet(v, bytes_read);
}

bool XGPacket::read_packet(uint8_t *bytes, size_t count, size_t &bytes_read)
{
        size_t n = 0;
        uint16_t size;
        uint8_t *ptr = bytes;
        uint8_t b;

        if (count == 0)
                return false;

        // find packet start byte
        while ((*(ptr++) != XGRID_IDENTIFIER) & (n++ < count)) { }

        // start of packet offset
        // to discard junk ahead of incomplete packet
        // (assuming packet is currently truncated)
        bytes_read = n-1;

        // return if out of buffer
        if (n > count)
                return false;

        // return if not enough bytes left
        if (count - n < sizeof(xgrid_header_t) + 2)
                return false;

        // get packet size
        size = (uint16_t)*(ptr++);
        size |= (uint16_t)*(ptr++) << 8;
        n += 2;

        // return if we don't have the whole packet
        if (count - n < size)
                return false;

        payload.clear();

        // read payload
        for (int i = 0; i < size; i++)
        {
                b = *(ptr++);
                payload.push_back(b);
                n++;
        }

        bytes_read = n;

        return true;
}

bool XGPacket::read_packet_bare(std::vector<char> bytes, size_t &bytes_read)
{
        return read_packet_bare((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::vector<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet_bare(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::deque<char> bytes, size_t &bytes_read)
{
        return read_packet_bare((uint8_t *)&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(std::deque<uint8_t> bytes, size_t &bytes_read)
{
        return read_packet_bare(&bytes[0], bytes.size(), bytes_read);
}

bool XGPacket::read_packet_bare(uint8_t *bytes, size_t count, size_t &bytes_read)
{
        size_t n = 0;
        uint8_t *ptr = bytes;
        uint8_t b;

        if (count < sizeof(xgrid_header_t))
                return false;

        payload.clear();

        // read payload
        for (int i = 0; i < count; i++)
        {
                b = *(ptr++);
                payload.push_back(b);
        }

        bytes_read = count;

        return true;
}

bool XGPacket::build_packet()
{
        payload.clear();
        payload.push_back(source_id);
        payload.push_back(source_id << 8);
        payload.push_back(type);
        payload.push_back(seq);
        payload.push_back(flags);
        payload.push_back(radius);

        for (int i = 0; i < data.size(); i++)
        {
                payload.push_back(data[i]);
        }

        return true;
}

bool XGPacket::decode_packet()
{
        if (payload.size() < sizeof(xgrid_header_t))
                return false;

        source_id = read_payload_uint16(0);
        type = payload[2];
        seq = payload[3];
        flags = payload[4];
        radius = payload[5];

        data.clear();
        for (int i = sizeof(xgrid_header_t); i < payload.size(); i++)
        {
                data.push_back(payload[i]);
        }

        return true;
}

std::string XGPacket::get_desc()
{
        std::stringstream desc;

        desc << "XGrid Packet" << std::endl;
        desc << "  Length: " << std::dec << get_length() << std::endl;
        desc << "  Source ID: 0x" << std::setfill('0') << std::setw(4) << std::hex << (int)source_id << std::endl;
        desc << "  Type: 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)type << std::endl;
        desc << "  Seq: " << std::dec << (int)seq << std::endl;
        desc << "  Flags: 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)flags << std::endl;
        desc << "  Radius: " << std::dec << (int)radius << std::endl;

        desc << "  Data (hex):";
        for (int i = 0; i < data.size(); i++)
        {
                if (i > 0 && i % 16 == 0)
                        desc << std::endl << "             ";
                desc << " " << std::setfill('0') << std::setw(2) << std::hex << (int)data[i];
        }
        desc << std::endl;

        return desc.str();
}

std::string XGPacket::get_hex_packet()
{
        std::vector<uint8_t> pkt = get_raw_packet();
        std::stringstream out;

        for (int i = 0; i < pkt.size(); i++)
        {
                if (i > 0)
                        out << " ";
                out << std::setfill('0') << std::setw(2) << std::hex << (int)pkt[i];
        }

        return out.str();
}

// read and write payload data
uint8_t XGPacket::read_payload_uint8(int offset)
{
        if (offset < 0)
                return 0;
        return payload[offset];
}

uint16_t XGPacket::read_payload_uint16(int offset)
{
        if (offset < 0)
                return 0;
        uint16_t value;
        value  = (uint16_t)payload[offset];
        value |= (uint16_t)payload[offset+1] << 8;
        return value;
}

uint32_t XGPacket::read_payload_uint32(int offset)
{
        if (offset < 0)
                return 0;
        uint32_t value;
        value  = (uint32_t)payload[offset];
        value |= (uint32_t)payload[offset+1] << 8;
        value |= (uint32_t)payload[offset+2] << 16;
        value |= (uint32_t)payload[offset+3] << 24;
        return value;
}

uint64_t XGPacket::read_payload_uint64(int offset)
{
        if (offset < 0)
                return 0;
        uint64_t value;
        value  = (uint64_t)payload[offset];
        value |= (uint64_t)payload[offset+1] << 8;
        value |= (uint64_t)payload[offset+2] << 16;
        value |= (uint64_t)payload[offset+3] << 24;
        value |= (uint64_t)payload[offset+4] << 32;
        value |= (uint64_t)payload[offset+5] << 40;
        value |= (uint64_t)payload[offset+6] << 48;
        value |= (uint64_t)payload[offset+7] << 56;
        return value;
}

void XGPacket::write_payload_uint8(int offset, uint8_t value)
{
        if (offset < 0)
                return;
        payload[offset] = value;
}

void XGPacket::write_payload_uint16(int offset, uint16_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
}

void XGPacket::write_payload_uint32(int offset, uint32_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
        payload[offset+2] = value >> 16;
        payload[offset+3] = value >> 24;
}

void XGPacket::write_payload_uint64(int offset, uint64_t value)
{
        if (offset < 0)
                return;
        payload[offset]   = value;
        payload[offset+1] = value >> 8;
        payload[offset+2] = value >> 16;
        payload[offset+3] = value >> 24;
        payload[offset+4] = value >> 32;
        payload[offset+5] = value >> 40;
        payload[offset+6] = value >> 48;
        payload[offset+7] = value >> 56;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tp_Wizard_TitlesAndObjects.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-25 08:38:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "tp_Wizard_TitlesAndObjects.hxx"
#include "tp_Wizard_TitlesAndObjects.hrc"
#include "Strings.hrc"
#include "res_Titles.hxx"
#include "res_LegendPosition.hxx"
#include "ResId.hxx"
#include "HelpIds.hrc"
#include "macros.hxx"
#include "ChartModelHelper.hxx"
#include "AxisHelper.hxx"
#include "LegendHelper.hxx"
#include "NoWarningThisInCTOR.hxx"
#include "ControllerLockGuard.hxx"

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

TitlesAndObjectsTabPage::TitlesAndObjectsTabPage( svt::OWizardMachine* pParent
        , const uno::Reference< XChartDocument >& xChartModel
        , const uno::Reference< uno::XComponentContext >& xContext )
        : OWizardPage( pParent, SchResId(TP_WIZARD_TITLEANDOBJECTS) )
        , m_aFT_TitleDescription( this, SchResId( FT_TITLEDESCRIPTION ) )
        , m_aFL_Vertical( this, SchResId( FL_VERTICAL ) )
        , m_apTitleResources( new TitleResources(this) )
        , m_apLegendPositionResources( new LegendPositionResources(this,xContext) )
        , m_aFL_Grids( this, SchResId( FL_GRIDS ) )
        , m_aCB_Grid_X( this, SchResId( CB_X_SECONDARY ) )
        , m_aCB_Grid_Y( this, SchResId( CB_Y_SECONDARY ) )
        , m_aCB_Grid_Z( this, SchResId( CB_Z_SECONDARY ) )
        , m_xChartModel( xChartModel )
        , m_xCC( xContext )
        , m_bCommitToModel( true )
        , m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY ) )
{
    FreeResource();

    this->SetText( String( SchResId( STR_PAGE_CHART_ELEMENTS ) ) );

    Font aFont( m_aFT_TitleDescription.GetControlFont() );
    aFont.SetWeight( WEIGHT_BOLD );
    m_aFT_TitleDescription.SetControlFont( aFont );

    m_aCB_Grid_X.SetHelpId( HID_SCH_CB_XGRID );
    m_aCB_Grid_Y.SetHelpId( HID_SCH_CB_YGRID );
    m_aCB_Grid_Z.SetHelpId( HID_SCH_CB_ZGRID );

    m_apTitleResources->SetUpdateDataHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_apLegendPositionResources->SetChangeHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));

    m_aCB_Grid_X.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_aCB_Grid_Y.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_aCB_Grid_Z.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
}

TitlesAndObjectsTabPage::~TitlesAndObjectsTabPage()
{
}

void TitlesAndObjectsTabPage::initializePage()
{
    m_bCommitToModel = false;

    //init titles
    {
        TitleDialogData aTitleInput;
        aTitleInput.readFromModel( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY) );
        m_apTitleResources->writeToResources( aTitleInput );
    }

    //init legend
    {
        m_apLegendPositionResources->writeToResources( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY) );
    }

    //init grid checkboxes
    {
        uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( m_xChartModel );
        uno::Sequence< sal_Bool > aPossibilityList;
        uno::Sequence< sal_Bool > aExistenceList;
        AxisHelper::getAxisOrGridPossibilities( aPossibilityList, xDiagram, sal_False );
        AxisHelper::getAxisOrGridExcistence( aExistenceList, xDiagram, sal_False );
        m_aCB_Grid_X.Enable( aPossibilityList[0] );
        m_aCB_Grid_Y.Enable( aPossibilityList[1] );
        m_aCB_Grid_Z.Enable( aPossibilityList[2] );
        m_aCB_Grid_X.Check( aExistenceList[0] );
        m_aCB_Grid_Y.Check( aExistenceList[1] );
        m_aCB_Grid_Z.Check( aExistenceList[2] );
    }

    m_bCommitToModel = true;
}

sal_Bool TitlesAndObjectsTabPage::commitPage( COMMIT_REASON /*eReason*/ )
{
    if( m_apTitleResources->IsModified() ) //titles may have changed in the meanwhile
        commitToModel();
    return sal_True;//return false if this page should not be left
}

void TitlesAndObjectsTabPage::commitToModel()
{
    bool bChanged = false;

    m_aTimerTriggeredControllerLock.startTimer();
    uno::Reference< frame::XModel >  xModel( m_xChartModel, uno::UNO_QUERY);

    ControllerLockGuard aLockedControllers( xModel );

    //commit title changes to model
    {
        TitleDialogData aTitleOutput;
        m_apTitleResources->readFromResources( aTitleOutput );
        bChanged = bChanged || aTitleOutput.writeDifferenceToModel( xModel, m_xCC );
        m_apTitleResources->ClearModifyFlag();
    }

    //commit legend changes to model
    {
        bChanged = true;
        m_apLegendPositionResources->writeToModel( xModel );
    }

    //commit grid changes to model
    {
        uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel );
        uno::Sequence< sal_Bool > aOldExistenceList;
        AxisHelper::getAxisOrGridExcistence( aOldExistenceList, xDiagram, sal_False );
        uno::Sequence< sal_Bool > aNewExistenceList(aOldExistenceList);
        aNewExistenceList[0]=m_aCB_Grid_X.IsChecked();
        aNewExistenceList[1]=m_aCB_Grid_Y.IsChecked();
        aNewExistenceList[2]=m_aCB_Grid_Z.IsChecked();
        AxisHelper::changeVisibilityOfGrids( xDiagram
                , aOldExistenceList, aNewExistenceList, m_xCC );
    }
}

IMPL_LINK( TitlesAndObjectsTabPage, ChangeHdl, void *, EMPTYARG )
{
    if( m_bCommitToModel )
        commitToModel();
    return 0;
}

sal_Bool TitlesAndObjectsTabPage::determineNextButtonState()
{
    return sal_False;
}

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>INTEGRATION: CWS chart19 (1.3.44); FILE MERGED 2007/11/20 17:12:15 iha 1.3.44.1: #1163# title for secondary axes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tp_Wizard_TitlesAndObjects.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2008-02-18 15:52:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "tp_Wizard_TitlesAndObjects.hxx"
#include "tp_Wizard_TitlesAndObjects.hrc"
#include "Strings.hrc"
#include "res_Titles.hxx"
#include "res_LegendPosition.hxx"
#include "ResId.hxx"
#include "HelpIds.hrc"
#include "macros.hxx"
#include "ChartModelHelper.hxx"
#include "AxisHelper.hxx"
#include "LegendHelper.hxx"
#include "NoWarningThisInCTOR.hxx"
#include "ControllerLockGuard.hxx"

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;
using namespace ::com::sun::star::chart2;

TitlesAndObjectsTabPage::TitlesAndObjectsTabPage( svt::OWizardMachine* pParent
        , const uno::Reference< XChartDocument >& xChartModel
        , const uno::Reference< uno::XComponentContext >& xContext )
        : OWizardPage( pParent, SchResId(TP_WIZARD_TITLEANDOBJECTS) )
        , m_aFT_TitleDescription( this, SchResId( FT_TITLEDESCRIPTION ) )
        , m_aFL_Vertical( this, SchResId( FL_VERTICAL ) )
        , m_apTitleResources( new TitleResources(this,false) )
        , m_apLegendPositionResources( new LegendPositionResources(this,xContext) )
        , m_aFL_Grids( this, SchResId( FL_GRIDS ) )
        , m_aCB_Grid_X( this, SchResId( CB_X_SECONDARY ) )
        , m_aCB_Grid_Y( this, SchResId( CB_Y_SECONDARY ) )
        , m_aCB_Grid_Z( this, SchResId( CB_Z_SECONDARY ) )
        , m_xChartModel( xChartModel )
        , m_xCC( xContext )
        , m_bCommitToModel( true )
        , m_aTimerTriggeredControllerLock( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY ) )
{
    FreeResource();

    this->SetText( String( SchResId( STR_PAGE_CHART_ELEMENTS ) ) );

    Font aFont( m_aFT_TitleDescription.GetControlFont() );
    aFont.SetWeight( WEIGHT_BOLD );
    m_aFT_TitleDescription.SetControlFont( aFont );

    m_aCB_Grid_X.SetHelpId( HID_SCH_CB_XGRID );
    m_aCB_Grid_Y.SetHelpId( HID_SCH_CB_YGRID );
    m_aCB_Grid_Z.SetHelpId( HID_SCH_CB_ZGRID );

    m_apTitleResources->SetUpdateDataHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_apLegendPositionResources->SetChangeHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));

    m_aCB_Grid_X.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_aCB_Grid_Y.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
    m_aCB_Grid_Z.SetToggleHdl( LINK( this, TitlesAndObjectsTabPage, ChangeHdl ));
}

TitlesAndObjectsTabPage::~TitlesAndObjectsTabPage()
{
}

void TitlesAndObjectsTabPage::initializePage()
{
    m_bCommitToModel = false;

    //init titles
    {
        TitleDialogData aTitleInput;
        aTitleInput.readFromModel( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY) );
        m_apTitleResources->writeToResources( aTitleInput );
    }

    //init legend
    {
        m_apLegendPositionResources->writeToResources( uno::Reference< frame::XModel >( m_xChartModel, uno::UNO_QUERY) );
    }

    //init grid checkboxes
    {
        uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( m_xChartModel );
        uno::Sequence< sal_Bool > aPossibilityList;
        uno::Sequence< sal_Bool > aExistenceList;
        AxisHelper::getAxisOrGridPossibilities( aPossibilityList, xDiagram, sal_False );
        AxisHelper::getAxisOrGridExcistence( aExistenceList, xDiagram, sal_False );
        m_aCB_Grid_X.Enable( aPossibilityList[0] );
        m_aCB_Grid_Y.Enable( aPossibilityList[1] );
        m_aCB_Grid_Z.Enable( aPossibilityList[2] );
        m_aCB_Grid_X.Check( aExistenceList[0] );
        m_aCB_Grid_Y.Check( aExistenceList[1] );
        m_aCB_Grid_Z.Check( aExistenceList[2] );
    }

    m_bCommitToModel = true;
}

sal_Bool TitlesAndObjectsTabPage::commitPage( COMMIT_REASON /*eReason*/ )
{
    if( m_apTitleResources->IsModified() ) //titles may have changed in the meanwhile
        commitToModel();
    return sal_True;//return false if this page should not be left
}

void TitlesAndObjectsTabPage::commitToModel()
{
    bool bChanged = false;

    m_aTimerTriggeredControllerLock.startTimer();
    uno::Reference< frame::XModel >  xModel( m_xChartModel, uno::UNO_QUERY);

    ControllerLockGuard aLockedControllers( xModel );

    //commit title changes to model
    {
        TitleDialogData aTitleOutput;
        m_apTitleResources->readFromResources( aTitleOutput );
        bChanged = bChanged || aTitleOutput.writeDifferenceToModel( xModel, m_xCC );
        m_apTitleResources->ClearModifyFlag();
    }

    //commit legend changes to model
    {
        bChanged = true;
        m_apLegendPositionResources->writeToModel( xModel );
    }

    //commit grid changes to model
    {
        uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( xModel );
        uno::Sequence< sal_Bool > aOldExistenceList;
        AxisHelper::getAxisOrGridExcistence( aOldExistenceList, xDiagram, sal_False );
        uno::Sequence< sal_Bool > aNewExistenceList(aOldExistenceList);
        aNewExistenceList[0]=m_aCB_Grid_X.IsChecked();
        aNewExistenceList[1]=m_aCB_Grid_Y.IsChecked();
        aNewExistenceList[2]=m_aCB_Grid_Z.IsChecked();
        AxisHelper::changeVisibilityOfGrids( xDiagram
                , aOldExistenceList, aNewExistenceList, m_xCC );
    }
}

IMPL_LINK( TitlesAndObjectsTabPage, ChangeHdl, void *, EMPTYARG )
{
    if( m_bCommitToModel )
        commitToModel();
    return 0;
}

sal_Bool TitlesAndObjectsTabPage::determineNextButtonState()
{
    return sal_False;
}

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/stringprintf.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_webstore_private_api.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/ui_test_utils.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"
#include "net/base/mock_host_resolver.h"

// A base class for tests below.
class ExtensionWebstorePrivateApiTest : public ExtensionApiTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kAppsGalleryURL,
        "http://www.example.com");
  }

  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    // Start up the test server and get us ready for calling the install
    // API functions.
    host_resolver()->AddRule("www.example.com", "127.0.0.1");
    ASSERT_TRUE(test_server()->Start());
    BeginInstallWithManifestFunction::SetIgnoreUserGestureForTests(true);
    BeginInstallWithManifestFunction::SetAutoConfirmForTests(true);
    ExtensionInstallUI::DisableFailureUIForTests();
  }

 protected:
  // Returns a test server URL, but with host 'www.example.com' so it matches
  // the web store app's extent that we set up via command line flags.
  GURL GetTestServerURL(const std::string& path) {
    GURL url = test_server()->GetURL(
        std::string("files/extensions/api_test/webstore_private/") + path);

    // Replace the host with 'www.example.com' so it matches the web store
    // app's extent.
    GURL::Replacements replace_host;
    std::string host_str("www.example.com");
    replace_host.SetHostStr(host_str);

    return url.ReplaceComponents(replace_host);
  }

  // Navigates to |page| and runs the Extension API test there.
  bool RunInstallTest(const std::string& page) {
    GURL crx_url = GetTestServerURL("extension.crx");
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryUpdateURL, crx_url.spec());

    GURL page_url = GetTestServerURL(page);
    return RunPageTest(page_url.spec());
  }

  ExtensionService* service() {
    return browser()->profile()->GetExtensionService();
  }
};

// Test cases where the user accepts the install confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallAccepted) {
  ASSERT_TRUE(RunInstallTest("accepted.html"));
}

// Now test the case where the user cancels the confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallCancelled) {
  BeginInstallWithManifestFunction::SetAutoConfirmForTests(false);
  ASSERT_TRUE(RunInstallTest("cancelled.html"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallNoGesture) {
  BeginInstallFunction::SetIgnoreUserGestureForTests(false);
  ASSERT_TRUE(RunInstallTest("no_user_gesture.html"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest1) {
  ui_test_utils::WindowedNotificationObserver observer(
      NotificationType::EXTENSION_INSTALL_ERROR,
      NotificationService::AllSources());
  ASSERT_TRUE(RunInstallTest("incorrect_manifest1.html"));
  observer.Wait();
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest2) {
  ui_test_utils::WindowedNotificationObserver observer(
      NotificationType::EXTENSION_INSTALL_ERROR,
      NotificationService::AllSources());
  ASSERT_TRUE(RunInstallTest("incorrect_manifest2.html"));
  observer.Wait();
}
<commit_msg>Mark ExtensionWebstorePrivateApiTest.InstallAccepted as FLAKY.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/stringprintf.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_install_ui.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_webstore_private_api.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/ui_test_utils.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/notification_service.h"
#include "net/base/mock_host_resolver.h"

// A base class for tests below.
class ExtensionWebstorePrivateApiTest : public ExtensionApiTest {
 public:
  void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionApiTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kAppsGalleryURL,
        "http://www.example.com");
  }

  void SetUpInProcessBrowserTestFixture() OVERRIDE {
    // Start up the test server and get us ready for calling the install
    // API functions.
    host_resolver()->AddRule("www.example.com", "127.0.0.1");
    ASSERT_TRUE(test_server()->Start());
    BeginInstallWithManifestFunction::SetIgnoreUserGestureForTests(true);
    BeginInstallWithManifestFunction::SetAutoConfirmForTests(true);
    ExtensionInstallUI::DisableFailureUIForTests();
  }

 protected:
  // Returns a test server URL, but with host 'www.example.com' so it matches
  // the web store app's extent that we set up via command line flags.
  GURL GetTestServerURL(const std::string& path) {
    GURL url = test_server()->GetURL(
        std::string("files/extensions/api_test/webstore_private/") + path);

    // Replace the host with 'www.example.com' so it matches the web store
    // app's extent.
    GURL::Replacements replace_host;
    std::string host_str("www.example.com");
    replace_host.SetHostStr(host_str);

    return url.ReplaceComponents(replace_host);
  }

  // Navigates to |page| and runs the Extension API test there.
  bool RunInstallTest(const std::string& page) {
    GURL crx_url = GetTestServerURL("extension.crx");
    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        switches::kAppsGalleryUpdateURL, crx_url.spec());

    GURL page_url = GetTestServerURL(page);
    return RunPageTest(page_url.spec());
  }

  ExtensionService* service() {
    return browser()->profile()->GetExtensionService();
  }
};

// TODO(asargent) - flaky; see crbug.com/80606.
// Test cases where the user accepts the install confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, FLAKY_InstallAccepted) {
  ASSERT_TRUE(RunInstallTest("accepted.html"));
}

// Now test the case where the user cancels the confirmation dialog.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallCancelled) {
  BeginInstallWithManifestFunction::SetAutoConfirmForTests(false);
  ASSERT_TRUE(RunInstallTest("cancelled.html"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, InstallNoGesture) {
  BeginInstallFunction::SetIgnoreUserGestureForTests(false);
  ASSERT_TRUE(RunInstallTest("no_user_gesture.html"));
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest1) {
  ui_test_utils::WindowedNotificationObserver observer(
      NotificationType::EXTENSION_INSTALL_ERROR,
      NotificationService::AllSources());
  ASSERT_TRUE(RunInstallTest("incorrect_manifest1.html"));
  observer.Wait();
}

IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
                       IncorrectManifest2) {
  ui_test_utils::WindowedNotificationObserver observer(
      NotificationType::EXTENSION_INSTALL_ERROR,
      NotificationService::AllSources());
  ASSERT_TRUE(RunInstallTest("incorrect_manifest2.html"));
  observer.Wait();
}
<|endoftext|>