<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ChangeRequestQueueProcessor.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-03 15:44:28 $
 *
 *  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
 *
 ************************************************************************/

#ifndef SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX
#define SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX

#include "ChangeRequestQueue.hxx"

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#include <rtl/ref.hxx>

#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCHANGEREQUEST_HPP_
#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_CONFIGURATIONCHANGEEVENT_HPP_
#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
#endif

#include <cppuhelper/interfacecontainer.hxx>
#include <tools/link.hxx>

#include <boost/shared_ptr.hpp>

namespace sd { namespace framework {

class ConfigurationController;
class ConfigurationUpdater;

/** The ChangeRequestQueueProcessor ownes the ChangeRequestQueue and
    processes the configuration change requests.

    When after processing one entry the queue is empty then the
    XConfigurationController::update() method is called so that the changes
    made to the local XConfiguration reference are reflected by the UI.

    Queue entries are processed asynchronously by calling PostUserEvent().
*/
class ChangeRequestQueueProcessor
{
public:
    /** The queue processor is created with a reference to an
        ConfigurationController so that its UpdateConfiguration() method can
        be called when the queue becomes empty.
    */
    ChangeRequestQueueProcessor (
        const ::rtl::Reference<ConfigurationController>& rxController,
        const ::boost::shared_ptr<ConfigurationUpdater>& rpUpdater);
    ~ChangeRequestQueueProcessor (void);

    /** Sets the configuration who will be changed by subsequent change
        requests.  This method should be called only by the configuration
        controller who owns the configuration.
    */
    void SetConfiguration (
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration);

    /** The given request is appended to the end of the queue and will
        eventually be processed when all other entries in front of it have
        been processed.
    */
    void AddRequest (const ::com::sun::star::uno::Reference<
        ::com::sun::star::drawing::framework::XConfigurationChangeRequest>& rxRequest);

    /** Returns </TRUE> when the queue is empty.
    */
    bool IsEmpty (void) const;

private:
    mutable ::osl::Mutex maMutex;

    ChangeRequestQueue maQueue;

    /** The id returned by the last PostUserEvent() call.  This id is stored
        so that a pending user event can be removed whent he queue processor
        is destroyed.
    */
    sal_uInt32 mnUserEventId;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::drawing::framework::XConfiguration> mxConfiguration;

    ::rtl::Reference<ConfigurationController> mpConfigurationController;

    ::boost::shared_ptr<ConfigurationUpdater> mpConfigurationUpdater;

    /** Initiate the processing of the entries in the queue.  The actual
        processing starts asynchronously.
    */
    void StartProcessing (void);

    /** Callback function for the PostUserEvent() call.
    */
    DECL_LINK(ProcessOneEvent,void*);
};

} } // end of namespace sd::framework

#endif
<commit_msg>INTEGRATION: CWS hr45_SRC680 (1.2.114); FILE MERGED 2007/08/22 14:09:59 hr 1.2.114.1: #i80944#: ChangeRequestQueueProcessor: member mnUserEventId is a pointer in camouflage, change from type sal_uInt32 to sal_uIntPtr for the benefit of LP64 platforms<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ChangeRequestQueueProcessor.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2007-08-28 11:15:47 $
 *
 *  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
 *
 ************************************************************************/

#ifndef SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX
#define SD_FRAMEWORK_CHANGE_REQUEST_QUEUE_PROCESSOR_HXX

#include "ChangeRequestQueue.hxx"

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#include <rtl/ref.hxx>

#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCHANGEREQUEST_HPP_
#include <com/sun/star/drawing/framework/XConfigurationChangeRequest.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_CONFIGURATIONCHANGEEVENT_HPP_
#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
#endif

#include <cppuhelper/interfacecontainer.hxx>
#include <tools/link.hxx>

#include <boost/shared_ptr.hpp>

namespace sd { namespace framework {

class ConfigurationController;
class ConfigurationUpdater;

/** The ChangeRequestQueueProcessor ownes the ChangeRequestQueue and
    processes the configuration change requests.

    When after processing one entry the queue is empty then the
    XConfigurationController::update() method is called so that the changes
    made to the local XConfiguration reference are reflected by the UI.

    Queue entries are processed asynchronously by calling PostUserEvent().
*/
class ChangeRequestQueueProcessor
{
public:
    /** The queue processor is created with a reference to an
        ConfigurationController so that its UpdateConfiguration() method can
        be called when the queue becomes empty.
    */
    ChangeRequestQueueProcessor (
        const ::rtl::Reference<ConfigurationController>& rxController,
        const ::boost::shared_ptr<ConfigurationUpdater>& rpUpdater);
    ~ChangeRequestQueueProcessor (void);

    /** Sets the configuration who will be changed by subsequent change
        requests.  This method should be called only by the configuration
        controller who owns the configuration.
    */
    void SetConfiguration (
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfiguration>& rxConfiguration);

    /** The given request is appended to the end of the queue and will
        eventually be processed when all other entries in front of it have
        been processed.
    */
    void AddRequest (const ::com::sun::star::uno::Reference<
        ::com::sun::star::drawing::framework::XConfigurationChangeRequest>& rxRequest);

    /** Returns </TRUE> when the queue is empty.
    */
    bool IsEmpty (void) const;

private:
    mutable ::osl::Mutex maMutex;

    ChangeRequestQueue maQueue;

    /** The id returned by the last PostUserEvent() call.  This id is stored
        so that a pending user event can be removed whent he queue processor
        is destroyed.
    */
    sal_uIntPtr mnUserEventId;

    ::com::sun::star::uno::Reference<
        ::com::sun::star::drawing::framework::XConfiguration> mxConfiguration;

    ::rtl::Reference<ConfigurationController> mpConfigurationController;

    ::boost::shared_ptr<ConfigurationUpdater> mpConfigurationUpdater;

    /** Initiate the processing of the entries in the queue.  The actual
        processing starts asynchronously.
    */
    void StartProcessing (void);

    /** Callback function for the PostUserEvent() call.
    */
    DECL_LINK(ProcessOneEvent,void*);
};

} } // end of namespace sd::framework

#endif
<|endoftext|>


<commit_before>// @(#)root/gpad:$Id$
// Author: Rene Brun   01/07/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TROOT.h"
#include "TButton.h"
#include "TCanvas.h"
#include "TLatex.h"

#include <string.h>

ClassImp(TButton)

/** \class TButton
\ingroup gpad

A TButton object is a user interface object.

A TButton has a name and an associated action.
When the button is clicked with the left mouse button, the corresponding
action is executed.

A TButton can be created by direct invocation of the constructors
or via the graphics editor.

The action can be set via TButton::SetMethod.
The action can be any command. Examples of actions:
  - "34+78" When the button is clicked, the result of addition is printed.
  - ".x macro.C" . Clicking the button executes the macro macro.C
The action can be modified at any time via TButton::SetMethod.

To modify the layout/size/contents of one or several buttons
in a canvas, you must set the canvas editable via TCanvas::SetEditable.
By default a TCanvas is editable.
By default a TDialogCanvas is not editable.
TButtons are in general placed in a TDialogCanvas.

A TButton being a TPad, one can draw graphics primitives in it
when the TCanvas/TDialogCanvas is editable.

Example of a macro creating a dialog canvas with buttons:
~~~ {.cpp}
void but() {
//   example of a dialog canvas with a few buttons

   TDialogCanvas *dialog = new TDialogCanvas("dialog","",200,300);

// Create first button. Clicking on this button will execute 34+56
   TButton *but1 = new TButton("button1","34+56",.05,.8,.45,.88);
   but1->Draw();

// Create second button. Clicking on this button will create a new canvas
   TButton *but2 = new TButton("canvas","c2 = new TCanvas(\"c2\")",.55,.8,.95,.88);
   but2->Draw();

// Create third button. Clicking on this button will invoke the browser
   but3 = new TButton("Browser","br = new TBrowser(\"br\")",0.25,0.54,0.75,0.64);
   but3->SetFillColor(42);
   but3->Draw();

// Create last button with no name. Instead a graph is draw inside the button
// Clicking on this button will invoke the macro $ROOTSYS/tutorials/graphs/graph.C
   button = new TButton("",".x tutorials/graphs/graph.C",0.15,0.15,0.85,0.38);
   button->SetFillColor(42);
   button->Draw();
   button->SetEditable(kTRUE);
   button->cd();

   Double_t x[8] = {0.08,0.21,0.34,0.48,0.61,0.7,0.81,0.92};
   Double_t y[8] = {0.2,0.65,0.4,0.34,0.24,0.43,0.75,0.52};
   TGraph *graph = new TGraph(8,x,y);
   graph->SetMarkerColor(4);
   graph->SetMarkerStyle(21);
   graph->Draw("lp");

   dialog->cd();
}
~~~
Executing the macro above produces the following dialog canvas:

\image html gpad_dialogbuttons.png
*/

////////////////////////////////////////////////////////////////////////////////
/// Button default constructor.

TButton::TButton(): TPad()
{
   fFraming = 0;
   fMethod  = "";
   fLogx    = kFALSE;
   fLogy    = kFALSE;
   SetEditable(kFALSE);
   fFocused = 0;
}

////////////////////////////////////////////////////////////////////////////////
/// Button normal constructor.
///
///   Note that the button coordinates x1,y1,x2,y2 are always in the range [0,1]

TButton::TButton(const char *title, const char *method, Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
           :TPad("button",title,x1,y1,x2,y2,18,2,1), TAttText(22,0,1,61,0.65)
{
   fFraming=0;
   SetBit(kCanDelete);
   fModified = kTRUE;
   fMethod = method;
   if (strlen(title)) {
      TLatex *text = new TLatex(0.5*(fX1+fX2),0.5*(fY1+fY2),title);
      fPrimitives->Add(text);
   }
   fLogx    = kFALSE;
   fLogy    = kFALSE;
   SetEditable(kFALSE);
   fFocused = 0;
}

////////////////////////////////////////////////////////////////////////////////
/// Button default destructor.

TButton::~TButton()
{
   if (fPrimitives) fPrimitives->Delete();
}

////////////////////////////////////////////////////////////////////////////////
/// Draw this button with its current attributes.

void TButton::Draw(Option_t *option)
{
   if (fCanvas) AppendPad(option);
}

////////////////////////////////////////////////////////////////////////////////
/// Execute action corresponding to one event.
///
///  This member function is called when a Button object is clicked.

void TButton::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   //check case where pressing a button deletes itself
   if (!TestBit(kNotDeleted)) return;

   if (IsEditable()) {
      TPad::ExecuteEvent(event,px,py);
      return;
   }

   TPad *cdpad = (TPad*)gROOT->GetSelectedPad();
   HideToolTip(event);

   switch (event) {

   case kMouseEnter:
      TPad::ExecuteEvent(event,px,py);
      break;

   case kButton1Down:
      SetBorderMode(-1);
      fFocused=1;
      Modified();
      Update();
      break;

   case kMouseMotion:

      break;

   case kButton1Motion:
      if (px<XtoAbsPixel(1) && px>XtoAbsPixel(0) &&
          py<YtoAbsPixel(0) && py>YtoAbsPixel(1)) {
         if (!fFocused) {
            SetBorderMode(-1);
            fFocused=1;
            Modified();
            GetCanvas()->Modified();
            Update();
         }
      } else if (fFocused) {
         SetBorderMode(1);
         fFocused=0;
         Modified();
         GetCanvas()->Modified();
         Update();
      }
      break;

   case kButton1Up:
      SetCursor(kWatch);
      if (fFocused) {
         if (cdpad) cdpad->cd();
         gROOT->ProcessLine(GetMethod());
      }
      //check case where pressing a button deletes itself
      if (!TestBit(kNotDeleted)) return;
      SetBorderMode(1);
      Modified();
      Update();
      SetCursor(kCross);
      break;
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Paint this button with its current attributes.

void TButton::Paint(Option_t *option)
{
   TPad::Paint(option);  //only called for Postscript print
}

////////////////////////////////////////////////////////////////////////////////
/// Paint is modified.

void TButton::PaintModified()
{
   if (!fCanvas) return;
   if (!fPrimitives) fPrimitives = new TList();
   TObject *obj = GetListOfPrimitives()->First();
   if (obj && obj->InheritsFrom(TText::Class())) {
      TLatex *text = (TLatex*)obj;
      text->SetTitle(GetTitle());
      text->SetTextSize(GetTextSize());
      text->SetTextFont(GetTextFont());
      text->SetTextAlign(GetTextAlign());
      text->SetTextColor(GetTextColor());
      text->SetTextAngle(GetTextAngle());
   }
   SetLogx(0);
   SetLogy(0);
   TPad::PaintModified();
}

////////////////////////////////////////////////////////////////////////////////
/// Set world coordinate system for the pad.

void TButton::Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
{
   TPad::Range(x1,y1,x2,y2);
}

////////////////////////////////////////////////////////////////////////////////
/// Save primitive as a C++ statement(s) on output stream out

void TButton::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
{
   TPad *padsav = (TPad*)gPad;
   char quote = '"';
   if (gROOT->ClassSaved(TButton::Class())) {
      out<<"   ";
   } else {
      out<<"   TButton *";
   }
   char *cm = (char*)GetMethod();
   Int_t nch = strlen(cm);
   char *cmethod = new char[nch+10];
   Int_t i = 0;
   while(*cm) {
      if (*cm == '"') {
         cmethod[i] = '\\';
         i++;
      }
      cmethod[i] = *cm;
      i++;
      cm++;
   }
   cmethod[i] = 0;
   out<<"button = new TButton("<<quote<<GetTitle()
      <<quote<<","<<quote<<cmethod<<quote
      <<","<<fXlowNDC
      <<","<<fYlowNDC
      <<","<<fXlowNDC+fWNDC
      <<","<<fYlowNDC+fHNDC
      <<");"<<std::endl;
   delete [] cmethod;

   SaveFillAttributes(out,"button",0,1001);
   SaveLineAttributes(out,"button",1,1,1);
   SaveTextAttributes(out,"button",22,0,1,61,.65);

   if (GetBorderSize() != 2) {
      out<<"   button->SetBorderSize("<<GetBorderSize()<<");"<<std::endl;
   }
   if (GetBorderMode() != 1) {
      out<<"   button->SetBorderMode("<<GetBorderMode()<<");"<<std::endl;
   }

   if (GetFraming()) out<<"button->SetFraming();"<<std::endl;
   if (IsEditable()) out<<"button->SetEditable(kTRUE);"<<std::endl;

   out<<"   button->Draw();"<<std::endl;

   TIter next(GetListOfPrimitives());
   TObject *obj = next();  //do not save first primitive

   Int_t nprim = 0;
   while ((obj = next())) {
      if (!nprim) out<<"   button->cd();"<<std::endl;
      nprim++;
      obj->SavePrimitive(out, (Option_t *)next.GetOption());
   }

   if (nprim) out<<"   "<<padsav->GetName()<<"->cd();"<<std::endl;
   padsav->cd();
}

////////////////////////////////////////////////////////////////////////////////
/// if framing is set, button will be highlighted

void TButton::SetFraming(Bool_t f)
{
   fFraming=f;
   if (f) SetBit(kFraming);
   else   ResetBit(kFraming);
}
<commit_msg>Set the Text attributes in Paint like in PaintModified. This fix the issue mentioned here: https://root.cern.ch/phpBB3/viewtopic.php?f=3&t=21435&p=93481&sid=cfe798cdb4bfc583e082f980033d913a#p93481<commit_after>// @(#)root/gpad:$Id$
// Author: Rene Brun   01/07/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "TROOT.h"
#include "TButton.h"
#include "TCanvas.h"
#include "TLatex.h"

#include <string.h>

ClassImp(TButton)

/** \class TButton
\ingroup gpad

A TButton object is a user interface object.

A TButton has a name and an associated action.
When the button is clicked with the left mouse button, the corresponding
action is executed.

A TButton can be created by direct invocation of the constructors
or via the graphics editor.

The action can be set via TButton::SetMethod.
The action can be any command. Examples of actions:
  - "34+78" When the button is clicked, the result of addition is printed.
  - ".x macro.C" . Clicking the button executes the macro macro.C
The action can be modified at any time via TButton::SetMethod.

To modify the layout/size/contents of one or several buttons
in a canvas, you must set the canvas editable via TCanvas::SetEditable.
By default a TCanvas is editable.
By default a TDialogCanvas is not editable.
TButtons are in general placed in a TDialogCanvas.

A TButton being a TPad, one can draw graphics primitives in it
when the TCanvas/TDialogCanvas is editable.

Example of a macro creating a dialog canvas with buttons:
~~~ {.cpp}
void but() {
//   example of a dialog canvas with a few buttons

   TDialogCanvas *dialog = new TDialogCanvas("dialog","",200,300);

// Create first button. Clicking on this button will execute 34+56
   TButton *but1 = new TButton("button1","34+56",.05,.8,.45,.88);
   but1->Draw();

// Create second button. Clicking on this button will create a new canvas
   TButton *but2 = new TButton("canvas","c2 = new TCanvas(\"c2\")",.55,.8,.95,.88);
   but2->Draw();

// Create third button. Clicking on this button will invoke the browser
   but3 = new TButton("Browser","br = new TBrowser(\"br\")",0.25,0.54,0.75,0.64);
   but3->SetFillColor(42);
   but3->Draw();

// Create last button with no name. Instead a graph is draw inside the button
// Clicking on this button will invoke the macro $ROOTSYS/tutorials/graphs/graph.C
   button = new TButton("",".x tutorials/graphs/graph.C",0.15,0.15,0.85,0.38);
   button->SetFillColor(42);
   button->Draw();
   button->SetEditable(kTRUE);
   button->cd();

   Double_t x[8] = {0.08,0.21,0.34,0.48,0.61,0.7,0.81,0.92};
   Double_t y[8] = {0.2,0.65,0.4,0.34,0.24,0.43,0.75,0.52};
   TGraph *graph = new TGraph(8,x,y);
   graph->SetMarkerColor(4);
   graph->SetMarkerStyle(21);
   graph->Draw("lp");

   dialog->cd();
}
~~~
Executing the macro above produces the following dialog canvas:

\image html gpad_dialogbuttons.png
*/

////////////////////////////////////////////////////////////////////////////////
/// Button default constructor.

TButton::TButton(): TPad()
{
   fFraming = 0;
   fMethod  = "";
   fLogx    = kFALSE;
   fLogy    = kFALSE;
   SetEditable(kFALSE);
   fFocused = 0;
}

////////////////////////////////////////////////////////////////////////////////
/// Button normal constructor.
///
///   Note that the button coordinates x1,y1,x2,y2 are always in the range [0,1]

TButton::TButton(const char *title, const char *method, Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
           :TPad("button",title,x1,y1,x2,y2,18,2,1), TAttText(22,0,1,61,0.65)
{
   fFraming=0;
   SetBit(kCanDelete);
   fModified = kTRUE;
   fMethod = method;
   if (strlen(title)) {
      TLatex *text = new TLatex(0.5*(fX1+fX2),0.5*(fY1+fY2),title);
      fPrimitives->Add(text);
   }
   fLogx    = kFALSE;
   fLogy    = kFALSE;
   SetEditable(kFALSE);
   fFocused = 0;
}

////////////////////////////////////////////////////////////////////////////////
/// Button default destructor.

TButton::~TButton()
{
   if (fPrimitives) fPrimitives->Delete();
}

////////////////////////////////////////////////////////////////////////////////
/// Draw this button with its current attributes.

void TButton::Draw(Option_t *option)
{
   if (fCanvas) AppendPad(option);
}

////////////////////////////////////////////////////////////////////////////////
/// Execute action corresponding to one event.
///
///  This member function is called when a Button object is clicked.

void TButton::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   //check case where pressing a button deletes itself
   if (!TestBit(kNotDeleted)) return;

   if (IsEditable()) {
      TPad::ExecuteEvent(event,px,py);
      return;
   }

   TPad *cdpad = (TPad*)gROOT->GetSelectedPad();
   HideToolTip(event);

   switch (event) {

   case kMouseEnter:
      TPad::ExecuteEvent(event,px,py);
      break;

   case kButton1Down:
      SetBorderMode(-1);
      fFocused=1;
      Modified();
      Update();
      break;

   case kMouseMotion:

      break;

   case kButton1Motion:
      if (px<XtoAbsPixel(1) && px>XtoAbsPixel(0) &&
          py<YtoAbsPixel(0) && py>YtoAbsPixel(1)) {
         if (!fFocused) {
            SetBorderMode(-1);
            fFocused=1;
            Modified();
            GetCanvas()->Modified();
            Update();
         }
      } else if (fFocused) {
         SetBorderMode(1);
         fFocused=0;
         Modified();
         GetCanvas()->Modified();
         Update();
      }
      break;

   case kButton1Up:
      SetCursor(kWatch);
      if (fFocused) {
         if (cdpad) cdpad->cd();
         gROOT->ProcessLine(GetMethod());
      }
      //check case where pressing a button deletes itself
      if (!TestBit(kNotDeleted)) return;
      SetBorderMode(1);
      Modified();
      Update();
      SetCursor(kCross);
      break;
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Paint this button with its current attributes.

void TButton::Paint(Option_t *option)
{
   if (!fCanvas) return;
   if (!fPrimitives) fPrimitives = new TList();
   TObject *obj = GetListOfPrimitives()->First();
   if (obj && obj->InheritsFrom(TText::Class())) {
      TLatex *text = (TLatex*)obj;
      text->SetTitle(GetTitle());
      text->SetTextSize(GetTextSize());
      text->SetTextFont(GetTextFont());
      text->SetTextAlign(GetTextAlign());
      text->SetTextColor(GetTextColor());
      text->SetTextAngle(GetTextAngle());
   }
   SetLogx(0);
   SetLogy(0);
   TPad::Paint(option);  //only called for Postscript print
}

////////////////////////////////////////////////////////////////////////////////
/// Paint is modified.

void TButton::PaintModified()
{
   if (!fCanvas) return;
   if (!fPrimitives) fPrimitives = new TList();
   TObject *obj = GetListOfPrimitives()->First();
   if (obj && obj->InheritsFrom(TText::Class())) {
      TLatex *text = (TLatex*)obj;
      text->SetTitle(GetTitle());
      text->SetTextSize(GetTextSize());
      text->SetTextFont(GetTextFont());
      text->SetTextAlign(GetTextAlign());
      text->SetTextColor(GetTextColor());
      text->SetTextAngle(GetTextAngle());
   }
   SetLogx(0);
   SetLogy(0);
   TPad::PaintModified();
}

////////////////////////////////////////////////////////////////////////////////
/// Set world coordinate system for the pad.

void TButton::Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
{
   TPad::Range(x1,y1,x2,y2);
}

////////////////////////////////////////////////////////////////////////////////
/// Save primitive as a C++ statement(s) on output stream out

void TButton::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
{
   TPad *padsav = (TPad*)gPad;
   char quote = '"';
   if (gROOT->ClassSaved(TButton::Class())) {
      out<<"   ";
   } else {
      out<<"   TButton *";
   }
   char *cm = (char*)GetMethod();
   Int_t nch = strlen(cm);
   char *cmethod = new char[nch+10];
   Int_t i = 0;
   while(*cm) {
      if (*cm == '"') {
         cmethod[i] = '\\';
         i++;
      }
      cmethod[i] = *cm;
      i++;
      cm++;
   }
   cmethod[i] = 0;
   out<<"button = new TButton("<<quote<<GetTitle()
      <<quote<<","<<quote<<cmethod<<quote
      <<","<<fXlowNDC
      <<","<<fYlowNDC
      <<","<<fXlowNDC+fWNDC
      <<","<<fYlowNDC+fHNDC
      <<");"<<std::endl;
   delete [] cmethod;

   SaveFillAttributes(out,"button",0,1001);
   SaveLineAttributes(out,"button",1,1,1);
   SaveTextAttributes(out,"button",22,0,1,61,.65);

   if (GetBorderSize() != 2) {
      out<<"   button->SetBorderSize("<<GetBorderSize()<<");"<<std::endl;
   }
   if (GetBorderMode() != 1) {
      out<<"   button->SetBorderMode("<<GetBorderMode()<<");"<<std::endl;
   }

   if (GetFraming()) out<<"button->SetFraming();"<<std::endl;
   if (IsEditable()) out<<"button->SetEditable(kTRUE);"<<std::endl;

   out<<"   button->Draw();"<<std::endl;

   TIter next(GetListOfPrimitives());
   TObject *obj = next();  //do not save first primitive

   Int_t nprim = 0;
   while ((obj = next())) {
      if (!nprim) out<<"   button->cd();"<<std::endl;
      nprim++;
      obj->SavePrimitive(out, (Option_t *)next.GetOption());
   }

   if (nprim) out<<"   "<<padsav->GetName()<<"->cd();"<<std::endl;
   padsav->cd();
}

////////////////////////////////////////////////////////////////////////////////
/// if framing is set, button will be highlighted

void TButton::SetFraming(Bool_t f)
{
   fFraming=f;
   if (f) SetBit(kFraming);
   else   ResetBit(kFraming);
}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Laszlo Papp <djszapi@archlinux.us>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameitemsmodel.h"

#include "core/gluon_global.h"
#include "engine/gameproject.h"

#include <QtCore/QHash>
#include <QtCore/QByteArray>

using namespace GluonPlayer;

GameViewItem::GameViewItem(const QString &gameName, const QString &gameDescription,
                            const QString &projectFileName, const QString &id)
    : m_gameName(gameName)
    , m_gameDescription(gameDescription)
    , m_projectFileName(projectFileName)
    , m_id(id)
{
}

QString GameViewItem::gameName() const
{
    return m_gameName;
}

QString GameViewItem::gameDescription() const
{
    return m_gameDescription;
}

QString GameViewItem::projectFileName() const
{
    return m_projectFileName;
}

QString GameViewItem::id() const
{
    return m_id;
}

GameItemsModel::GameItemsModel( QObject* parent )
    : QAbstractListModel( parent )
{
    QDir m_dir;
    m_dir.cd( GluonCore::Global::dataDirectory() + "/gluon/games" );
    QStringList gameDirNameList;
    gameDirNameList = m_dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot );
    foreach( const QString& gameDirName, gameDirNameList)
    {
        QDir gameDir = m_dir;
        gameDir.cd( gameDirName );
        QStringList gluonProjectFiles = gameDir.entryList( QStringList( GluonEngine::projectFilename ) );
        if( !gluonProjectFiles.isEmpty() )
        {
            QString projectFileName = gameDir.absoluteFilePath( gluonProjectFiles.at( 0 ) );
            GluonEngine::GameProject project;
            project.loadFromFile( projectFileName );
            GameViewItem gameViewItem(project.name(), project.description(),
                                        projectFileName, project.property("id").toString());
            m_gameViewItems.append(gameViewItem);
        }
    }

    QHash<int, QByteArray> roles;
    roles[GameNameRole] = "gameName";
    roles[GameDescriptionRole] = "gameDescription";
    roles[ProjectFileNameRole] = "projectFileName";
    roles[IDRole] = "id";
    setRoleNames(roles);
}

QVariant GameItemsModel::data( const QModelIndex& index, int role ) const
{
    if (index.row() < 0 || index.row() > m_gameViewItems.count())
        return QVariant();

    switch (role) {
    case Qt::UserRole:
        break;
    case GameNameRole:
        return m_gameViewItems.at( index.row() ).gameName();
    case GameDescriptionRole:
        return m_gameViewItems.at( index.row() ).gameDescription();
    case Qt::DisplayRole:
    case ProjectFileNameRole:
        return m_gameViewItems.at( index.row() ).projectFileName();
    case IDRole:
        return m_gameViewItems.at( index.row() ).id();
    default:
        break;
    }

    return QVariant();
}

int GameItemsModel::rowCount( const QModelIndex& /* parent */ ) const
{
    return m_gameViewItems.count();
}

int GameItemsModel::columnCount( const QModelIndex& /* parent */ ) const
{
    return 1;
}

QVariant GameItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( section == 0 )
    {
        return QString( "Game" );
    }

    return QAbstractItemModel::headerData( section, orientation, role );
}

#include "gameitemsmodel.moc"
<commit_msg>Fix the game dir management after the gamebinding change.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Laszlo Papp <djszapi@archlinux.us>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "gameitemsmodel.h"

#include "core/gluon_global.h"
#include "engine/gameproject.h"

#include <QtCore/QHash>
#include <QtCore/QByteArray>

using namespace GluonPlayer;

GameViewItem::GameViewItem(const QString &gameName, const QString &gameDescription,
                            const QString &projectFileName, const QString &id)
    : m_gameName(gameName)
    , m_gameDescription(gameDescription)
    , m_projectFileName(projectFileName)
    , m_id(id)
{
}

QString GameViewItem::gameName() const
{
    return m_gameName;
}

QString GameViewItem::gameDescription() const
{
    return m_gameDescription;
}

QString GameViewItem::projectFileName() const
{
    return m_projectFileName;
}

QString GameViewItem::id() const
{
    return m_id;
}

GameItemsModel::GameItemsModel( QObject* parent )
    : QAbstractListModel( parent )
{
    QDir m_dir;
    m_dir.cd( GluonCore::Global::dataDirectory() + "/gluon/games" );
    QStringList gameDirNameList = m_dir.entryList( QStringList() << QString("*" + GluonEngine::projectSuffix), QDir::Dirs | QDir::NoDotAndDotDot );
    foreach( const QString& gameDirName, gameDirNameList)
    {
        QDir gameDir = m_dir;
        gameDir.cd( gameDirName );
        QStringList gluonProjectFiles = gameDir.entryList( QStringList( GluonEngine::projectFilename ) );
        if( !gluonProjectFiles.isEmpty() )
        {
            QString projectFileName = gameDir.absoluteFilePath( gluonProjectFiles.at( 0 ) );
            GluonEngine::GameProject project;
            project.loadFromFile( projectFileName );
            GameViewItem gameViewItem(project.name(), project.description(),
                                        projectFileName, project.property("id").toString());
            m_gameViewItems.append(gameViewItem);
        }
    }

    QHash<int, QByteArray> roles;
    roles[GameNameRole] = "gameName";
    roles[GameDescriptionRole] = "gameDescription";
    roles[ProjectFileNameRole] = "projectFileName";
    roles[IDRole] = "id";
    setRoleNames(roles);
}

QVariant GameItemsModel::data( const QModelIndex& index, int role ) const
{
    if (index.row() < 0 || index.row() > m_gameViewItems.count())
        return QVariant();

    switch (role) {
    case Qt::UserRole:
        break;
    case GameNameRole:
        return m_gameViewItems.at( index.row() ).gameName();
    case GameDescriptionRole:
        return m_gameViewItems.at( index.row() ).gameDescription();
    case Qt::DisplayRole:
    case ProjectFileNameRole:
        return m_gameViewItems.at( index.row() ).projectFileName();
    case IDRole:
        return m_gameViewItems.at( index.row() ).id();
    default:
        break;
    }

    return QVariant();
}

int GameItemsModel::rowCount( const QModelIndex& /* parent */ ) const
{
    return m_gameViewItems.count();
}

int GameItemsModel::columnCount( const QModelIndex& /* parent */ ) const
{
    return 1;
}

QVariant GameItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( section == 0 )
    {
        return QString( "Game" );
    }

    return QAbstractItemModel::headerData( section, orientation, role );
}

#include "gameitemsmodel.moc"
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/core/util/test_config.h"

#include <grpc/impl/codegen/gpr_types.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/examine_stack.h"
#include "src/core/lib/surface/init.h"
#include "test/core/util/stack_tracer.h"

#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"

int64_t g_fixture_slowdown_factor = 1;
int64_t g_poller_slowdown_factor = 1;

#if GPR_GETPID_IN_UNISTD_H
#include <unistd.h>
static unsigned seed(void) { return static_cast<unsigned>(getpid()); }
#endif

#if GPR_GETPID_IN_PROCESS_H
#include <process.h>
static unsigned seed(void) { return (unsigned)_getpid(); }
#endif

#if GPR_WINDOWS_CRASH_HANDLER
#include <windows.h>

#include <tchar.h>

// disable warning 4091 - dbghelp.h is broken for msvc2015
#pragma warning(disable : 4091)
#define DBGHELP_TRANSLATE_TCHAR
#include <dbghelp.h>

#ifdef _MSC_VER
#pragma comment(lib, "dbghelp.lib")
#endif

static void print_stack_from_context(HANDLE thread, CONTEXT c) {
  STACKFRAME s;  // in/out stackframe
  memset(&s, 0, sizeof(s));
  DWORD imageType;
#ifdef _M_IX86
  // normally, call ImageNtHeader() and use machine info from PE header
  imageType = IMAGE_FILE_MACHINE_I386;
  s.AddrPC.Offset = c.Eip;
  s.AddrPC.Mode = AddrModeFlat;
  s.AddrFrame.Offset = c.Ebp;
  s.AddrFrame.Mode = AddrModeFlat;
  s.AddrStack.Offset = c.Esp;
  s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
  imageType = IMAGE_FILE_MACHINE_AMD64;
  s.AddrPC.Offset = c.Rip;
  s.AddrPC.Mode = AddrModeFlat;
  s.AddrFrame.Offset = c.Rbp;
  s.AddrFrame.Mode = AddrModeFlat;
  s.AddrStack.Offset = c.Rsp;
  s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
  imageType = IMAGE_FILE_MACHINE_IA64;
  s.AddrPC.Offset = c.StIIP;
  s.AddrPC.Mode = AddrModeFlat;
  s.AddrFrame.Offset = c.IntSp;
  s.AddrFrame.Mode = AddrModeFlat;
  s.AddrBStore.Offset = c.RsBSP;
  s.AddrBStore.Mode = AddrModeFlat;
  s.AddrStack.Offset = c.IntSp;
  s.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

  HANDLE process = GetCurrentProcess();

  SYMBOL_INFOW* symbol =
      (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
  symbol->MaxNameLen = 255;
  symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);

  const unsigned short MAX_CALLERS_SHOWN =
      8192;  // avoid flooding the stderr if stacktrace is way too long
  for (int frame = 0; frame < MAX_CALLERS_SHOWN &&
                      StackWalk(imageType, process, thread, &s, &c, 0,
                                SymFunctionTableAccess, SymGetModuleBase, 0);
       frame++) {
    PWSTR symbol_name = L"<<no symbol>>";
    DWORD64 symbol_address = 0;
    if (SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol)) {
      symbol_name = symbol->Name;
      symbol_address = (DWORD64)symbol->Address;
    }

    PWSTR file_name = L"<<no line info>>";
    int line_number = 0;
    IMAGEHLP_LINE64 line;
    line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    DWORD displacement = 0;
    if (SymGetLineFromAddrW64(process, (DWORD64)(s.AddrPC.Offset),
                              &displacement, &line)) {
      file_name = line.FileName;
      line_number = (int)line.LineNumber;
    }

    fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X (%ls:%d)\n", frame,
             (DWORD64)(s.AddrPC.Offset), symbol_name, symbol_address, file_name,
             line_number);
    fflush(stderr);
  }

  free(symbol);
}

static void print_current_stack() {
  CONTEXT context;
  RtlCaptureContext(&context);
  print_stack_from_context(GetCurrentThread(), context);
}

static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
  fprintf(stderr, "Exception handler called, dumping information\n");
  bool try_to_print_stack = true;
  PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord;
  while (exrec) {
    DWORD code = exrec->ExceptionCode;
    DWORD flgs = exrec->ExceptionFlags;
    PVOID addr = exrec->ExceptionAddress;
    if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false;
    fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr);
    exrec = exrec->ExceptionRecord;
  }
  if (try_to_print_stack) {
    print_stack_from_context(GetCurrentThread(), *ex_info->ContextRecord);
  }
  if (IsDebuggerPresent()) {
    __debugbreak();
  } else {
    _exit(1);
  }
  return EXCEPTION_EXECUTE_HANDLER;
}

static void abort_handler(int sig) {
  fprintf(stderr, "Abort handler called.\n");
  print_current_stack();
  if (IsDebuggerPresent()) {
    __debugbreak();
  } else {
    _exit(1);
  }
}

static void install_crash_handler() {
  if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
    fprintf(stderr, "SymInitialize failed: %d\n", GetLastError());
  }
  SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler);
  _set_abort_behavior(0, _WRITE_ABORT_MSG);
  _set_abort_behavior(0, _CALL_REPORTFAULT);
  signal(SIGABRT, abort_handler);
}
#elif GPR_POSIX_CRASH_HANDLER
#include <errno.h>
#include <execinfo.h>
#include <stdio.h>
#include <string.h>

#define SIGNAL_NAMES_LENGTH 32

static const char* const signal_names[] = {
    nullptr,   "SIGHUP",  "SIGINT",    "SIGQUIT", "SIGILL",    "SIGTRAP",
    "SIGABRT", "SIGBUS",  "SIGFPE",    "SIGKILL", "SIGUSR1",   "SIGSEGV",
    "SIGUSR2", "SIGPIPE", "SIGALRM",   "SIGTERM", "SIGSTKFLT", "SIGCHLD",
    "SIGCONT", "SIGSTOP", "SIGTSTP",   "SIGTTIN", "SIGTTOU",   "SIGURG",
    "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH",  "SIGIO",
    "SIGPWR",  "SIGSYS"};

static char g_alt_stack[GPR_MAX(MINSIGSTKSZ, 65536)];

#define MAX_FRAMES 32

/* signal safe output */
static void output_string(const char* string) {
  size_t len = strlen(string);
  ssize_t r;

  do {
    r = write(STDERR_FILENO, string, len);
  } while (r == -1 && errno == EINTR);
}

static void output_num(long num) {
  char buf[GPR_LTOA_MIN_BUFSIZE];
  gpr_ltoa(num, buf);
  output_string(buf);
}

static void crash_handler(int signum, siginfo_t* /*info*/, void* /*data*/) {
  void* addrlist[MAX_FRAMES + 1];
  int addrlen;

  output_string("\n\n\n*******************************\nCaught signal ");
  if (signum > 0 && signum < SIGNAL_NAMES_LENGTH) {
    output_string(signal_names[signum]);
  } else {
    output_num(signum);
  }
  output_string("\n");

  addrlen = backtrace(addrlist, GPR_ARRAY_SIZE(addrlist));

  if (addrlen == 0) {
    output_string("  no backtrace\n");
  } else {
    backtrace_symbols_fd(addrlist, addrlen, STDERR_FILENO);
  }

  /* try to get a core dump for SIGTERM */
  if (signum == SIGTERM) signum = SIGQUIT;
  raise(signum);
}

static void install_crash_handler() {
  stack_t ss;
  struct sigaction sa;

  memset(&ss, 0, sizeof(ss));
  memset(&sa, 0, sizeof(sa));
  ss.ss_size = sizeof(g_alt_stack);
  ss.ss_sp = g_alt_stack;
  GPR_ASSERT(sigaltstack(&ss, nullptr) == 0);
  sa.sa_flags = static_cast<int>(SA_SIGINFO | SA_ONSTACK | SA_RESETHAND);
  sa.sa_sigaction = crash_handler;
  GPR_ASSERT(sigaction(SIGILL, &sa, nullptr) == 0);
  GPR_ASSERT(sigaction(SIGABRT, &sa, nullptr) == 0);
  GPR_ASSERT(sigaction(SIGBUS, &sa, nullptr) == 0);
  GPR_ASSERT(sigaction(SIGSEGV, &sa, nullptr) == 0);
  GPR_ASSERT(sigaction(SIGTERM, &sa, nullptr) == 0);
  GPR_ASSERT(sigaction(SIGQUIT, &sa, nullptr) == 0);
}
#else
static void install_crash_handler() {}
#endif

bool BuiltUnderValgrind() {
#ifdef RUNNING_ON_VALGRIND
  return true;
#else
  return false;
#endif
}

bool BuiltUnderTsan() {
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef THREAD_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderAsan() {
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef ADDRESS_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderMsan() {
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef MEMORY_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderUbsan() {
#ifdef GRPC_UBSAN
  return true;
#else
  return false;
#endif
}

int64_t grpc_test_sanitizer_slowdown_factor() {
  int64_t sanitizer_multiplier = 1;
  if (BuiltUnderValgrind()) {
    sanitizer_multiplier = 20;
  } else if (BuiltUnderTsan()) {
    sanitizer_multiplier = 5;
  } else if (BuiltUnderAsan()) {
    sanitizer_multiplier = 3;
  } else if (BuiltUnderMsan()) {
    sanitizer_multiplier = 4;
  } else if (BuiltUnderUbsan()) {
    sanitizer_multiplier = 5;
  }
  return sanitizer_multiplier;
}

int64_t grpc_test_slowdown_factor() {
  return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
         g_poller_slowdown_factor;
}

gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
  return gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC),
      gpr_time_from_millis(
          grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_s,
          GPR_TIMESPAN));
}

gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
  return gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC),
      gpr_time_from_micros(
          grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_ms,
          GPR_TIMESPAN));
}

void grpc_test_init(int argc, char** argv) {
#if GPR_WINDOWS
  // Windows cannot use absl::InitializeSymbolizer until it fixes mysterious
  // SymInitialize failure using Bazel RBE on Windows
  // https://github.com/grpc/grpc/issues/24178
  install_crash_handler();
#else
  grpc_core::testing::InitializeStackTracer(argv[0]);
  absl::FailureSignalHandlerOptions options;
  absl::InstallFailureSignalHandler(options);
#endif
  gpr_log(GPR_DEBUG,
          "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64
          ", poller=%" PRId64 ", total=%" PRId64,
          grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor,
          g_poller_slowdown_factor, grpc_test_slowdown_factor());
  /* seed rng with pid, so we don't end up with the same random numbers as a
     concurrently running test binary */
  srand(seed());
}

bool grpc_wait_until_shutdown(int64_t time_s) {
  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(time_s);
  while (grpc_is_initialized()) {
    grpc_maybe_wait_for_async_shutdown();
    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_millis(1, GPR_TIMESPAN)));
    if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0) {
      return false;
    }
  }
  return true;
}

namespace grpc {
namespace testing {

TestEnvironment::TestEnvironment(int argc, char** argv) {
  grpc_test_init(argc, argv);
}

TestEnvironment::~TestEnvironment() {
  // This will wait until gRPC shutdown has actually happened to make sure
  // no gRPC resources (such as thread) are active. (timeout = 10s)
  if (!grpc_wait_until_shutdown(10)) {
    gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
  }
  if (BuiltUnderMsan()) {
    // This is a workaround for MSAN. MSAN doesn't like having shutdown thread
    // running. Although the code above waits until shutdown is done, chances
    // are that thread itself is still alive. To workaround this problem, this
    // is going to wait for 0.5 sec to give a chance to the shutdown thread to
    // exit. https://github.com/grpc/grpc/issues/23695
    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_millis(500, GPR_TIMESPAN)));
  }
  gpr_log(GPR_INFO, "TestEnvironment ends");
}

TestGrpcScope::TestGrpcScope() { grpc_init(); }

TestGrpcScope::~TestGrpcScope() {
  grpc_shutdown();
  if (!grpc_wait_until_shutdown(10)) {
    gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
  }
}

}  // namespace testing
}  // namespace grpc
<commit_msg>Enable Abseil crash handler on Windows<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/core/util/test_config.h"

#include <grpc/impl/codegen/gpr_types.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/examine_stack.h"
#include "src/core/lib/surface/init.h"
#include "test/core/util/stack_tracer.h"

#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"

int64_t g_fixture_slowdown_factor = 1;
int64_t g_poller_slowdown_factor = 1;

#if GPR_GETPID_IN_UNISTD_H
#include <unistd.h>
static unsigned seed(void) { return static_cast<unsigned>(getpid()); }
#endif

#if GPR_GETPID_IN_PROCESS_H
#include <process.h>
static unsigned seed(void) { return (unsigned)_getpid(); }
#endif

bool BuiltUnderValgrind() {
#ifdef RUNNING_ON_VALGRIND
  return true;
#else
  return false;
#endif
}

bool BuiltUnderTsan() {
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef THREAD_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderAsan() {
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef ADDRESS_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderMsan() {
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
  return true;
#else
  return false;
#endif
#else
#ifdef MEMORY_SANITIZER
  return true;
#else
  return false;
#endif
#endif
}

bool BuiltUnderUbsan() {
#ifdef GRPC_UBSAN
  return true;
#else
  return false;
#endif
}

int64_t grpc_test_sanitizer_slowdown_factor() {
  int64_t sanitizer_multiplier = 1;
  if (BuiltUnderValgrind()) {
    sanitizer_multiplier = 20;
  } else if (BuiltUnderTsan()) {
    sanitizer_multiplier = 5;
  } else if (BuiltUnderAsan()) {
    sanitizer_multiplier = 3;
  } else if (BuiltUnderMsan()) {
    sanitizer_multiplier = 4;
  } else if (BuiltUnderUbsan()) {
    sanitizer_multiplier = 5;
  }
  return sanitizer_multiplier;
}

int64_t grpc_test_slowdown_factor() {
  return grpc_test_sanitizer_slowdown_factor() * g_fixture_slowdown_factor *
         g_poller_slowdown_factor;
}

gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) {
  return gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC),
      gpr_time_from_millis(
          grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_s,
          GPR_TIMESPAN));
}

gpr_timespec grpc_timeout_milliseconds_to_deadline(int64_t time_ms) {
  return gpr_time_add(
      gpr_now(GPR_CLOCK_MONOTONIC),
      gpr_time_from_micros(
          grpc_test_slowdown_factor() * static_cast<int64_t>(1e3) * time_ms,
          GPR_TIMESPAN));
}

void grpc_test_init(int argc, char** argv) {
  grpc_core::testing::InitializeStackTracer(argv[0]);
  absl::FailureSignalHandlerOptions options;
  absl::InstallFailureSignalHandler(options);
  gpr_log(GPR_DEBUG,
          "test slowdown factor: sanitizer=%" PRId64 ", fixture=%" PRId64
          ", poller=%" PRId64 ", total=%" PRId64,
          grpc_test_sanitizer_slowdown_factor(), g_fixture_slowdown_factor,
          g_poller_slowdown_factor, grpc_test_slowdown_factor());
  /* seed rng with pid, so we don't end up with the same random numbers as a
     concurrently running test binary */
  srand(seed());
}

bool grpc_wait_until_shutdown(int64_t time_s) {
  gpr_timespec deadline = grpc_timeout_seconds_to_deadline(time_s);
  while (grpc_is_initialized()) {
    grpc_maybe_wait_for_async_shutdown();
    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_millis(1, GPR_TIMESPAN)));
    if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), deadline) > 0) {
      return false;
    }
  }
  return true;
}

namespace grpc {
namespace testing {

TestEnvironment::TestEnvironment(int argc, char** argv) {
  grpc_test_init(argc, argv);
}

TestEnvironment::~TestEnvironment() {
  // This will wait until gRPC shutdown has actually happened to make sure
  // no gRPC resources (such as thread) are active. (timeout = 10s)
  if (!grpc_wait_until_shutdown(10)) {
    gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
  }
  if (BuiltUnderMsan()) {
    // This is a workaround for MSAN. MSAN doesn't like having shutdown thread
    // running. Although the code above waits until shutdown is done, chances
    // are that thread itself is still alive. To workaround this problem, this
    // is going to wait for 0.5 sec to give a chance to the shutdown thread to
    // exit. https://github.com/grpc/grpc/issues/23695
    gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                                 gpr_time_from_millis(500, GPR_TIMESPAN)));
  }
  gpr_log(GPR_INFO, "TestEnvironment ends");
}

TestGrpcScope::TestGrpcScope() { grpc_init(); }

TestGrpcScope::~TestGrpcScope() {
  grpc_shutdown();
  if (!grpc_wait_until_shutdown(10)) {
    gpr_log(GPR_ERROR, "Timeout in waiting for gRPC shutdown");
  }
}

}  // namespace testing
}  // namespace grpc
<|endoftext|>


<commit_before>/* Autogenerated with kurento-module-creator */

#include "TelmateFrameGrabberOpenCVImpl.hpp"
#include <gst/gst.h>
#include <KurentoException.hpp>
#include <vector>
#include <string>

#define GST_CAT_DEFAULT kurento_telmate_frame_grabber_opencv_impl
GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoTelmateFrameGrabberOpenCVImpl"

namespace kurento {

TelmateFrameGrabberOpenCVImpl::TelmateFrameGrabberOpenCVImpl() {

    GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                            GST_DEFAULT_NAME);

    this->thrLoop = true;
    this->snapInterval = 1000;
    this->epName = "EP_NAME_UNINITIALIZED";
    this->storagePath = "/tmp";
    this->framesCounter = 0;
    this->outputFormat = FGFMT_JPEG;
    this->lastQueueTimeStamp = 0;
    this->queueLength = 0;
    this->frameQueue = new avis_blocking_queue<VideoFrame*>;

    this->thr = new boost::thread(boost::bind(
            &TelmateFrameGrabberOpenCVImpl::queueHandler, this));
    this->thr->detach();

    GST_INFO("Constructor was called for %s", this->epName.c_str());
}

TelmateFrameGrabberOpenCVImpl::~TelmateFrameGrabberOpenCVImpl() {

    GST_INFO("Destructor was called for %s", this->epName.c_str());

}

void TelmateFrameGrabberOpenCVImpl::cleanup() {

    VideoFrame *ptrVf;

    while(!this->frameQueue->empty()) {
        this->frameQueue->pop(ptrVf); // blocks
        --this->queueLength;
        delete ptrVf;
        ptrVf = NULL;

    }

    this->thrLoop = false;
    boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); /* Give the processing thread some time to exit() */
    GST_INFO("Called release() for %s :: Dequeue completed.", this->epName.c_str());

    delete this->frameQueue;
    this->frameQueue = NULL;

    return;
}

/*
 * This function will be called with each new frame. mat variable
 * contains the current frame. You should insert your image processing code
 * here. Any changes in mat, will be sent through the Media Pipeline.
 */
void TelmateFrameGrabberOpenCVImpl::process(cv::Mat &mat) {
        if ((this->getCurrentTimestampLong() - this->lastQueueTimeStamp) >= this->snapInterval) {

            if(this->thrLoop) { // do not push into the queue if the destructor was called.
                this->lastQueueTimeStamp = this->getCurrentTimestampLong();
                VideoFrame *ptrVf = new VideoFrame();
                ptrVf->mat = mat.clone();
                ptrVf->ts = std::to_string(this->lastQueueTimeStamp);

                this->frameQueue->push(ptrVf);
                ++this->queueLength;
                ++this->framesCounter;
            }
        }
}
/*
 * This function is executed inside the queueHandler thread as a main() function.
 * It pops a VideoFrame from the framequeue and saves it to disk.
 * a boost scoped_lock is implemented to ensure the queue is emptied to disk before
 * the destructor is executed. a 1 second sleep is implemented inside the while() loop
 * to ensure the cpu isn't exhausted while the queue is empty.
 */
void TelmateFrameGrabberOpenCVImpl::queueHandler() {
        VideoFrame *ptrVf;
        cv::Mat image;
        std::vector<int> params;
        std::string image_extension;

        while (this->thrLoop) {

            this->frameQueue->pop(ptrVf); // blocks
            params.clear();     // clear the vector since the last iteration.
            this->lastQueueTimeStamp = this->getCurrentTimestampLong();
            --this->queueLength;

            switch (this->outputFormat) {
                case FGFMT_JPEG:
                    /* Set jpeg params */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
                case FGFMT_PNG:
                    /* Set PNG parameters, compression etc. */
                    params.push_back(CV_IMWRITE_PNG_COMPRESSION);
                    params.push_back(FG_PNG_QUALITY);
                    image_extension = ".png";
                    break;
                default:
                    /* Defaults to jpeg */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
            }

            std::string filename =
                    std::to_string((long) this->framesCounter) + "_" + ptrVf->ts + image_extension;

            if (this->storagePathSubdir.empty()) {
                this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
                boost::filesystem::path dir(this->storagePathSubdir.c_str());
                if (!boost::filesystem::create_directories(dir)) {
                    GST_ERROR("%s create_directories() failed for: %s", this->epName.c_str(),
                              this->storagePathSubdir.c_str());
                }
            }

            std::string fullpath = this->storagePathSubdir + "/" + filename;

            try {
                cv::imwrite(fullpath.c_str(), ptrVf->mat, params);
            }
            catch (...) {
                GST_ERROR("::queueHandler() imgwrite() failed.");
                throw KurentoException(NOT_IMPLEMENTED,
                                       "TelmateFrameGrabberOpenCVImpl::queueHandler() imgwrite() failed. \n");
            }

            ptrVf->mat.release();   // release internal memory allocations

            delete ptrVf;
            ptrVf = NULL;

        }

}

/* This function provides the ability to update the storage path for
 * snapshot storage per endpoint
 */
void TelmateFrameGrabberOpenCVImpl::setStoragePath(std::string storagePath) {

    this->storagePath = storagePath;

    this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
    boost::filesystem::path dir(this->storagePathSubdir.c_str());
    if (!boost::filesystem::create_directories(dir)) {
        GST_ERROR("%s create_directories() failed for: %s", this->epName.c_str(),
                  this->storagePathSubdir.c_str());
    }

    GST_INFO("Storage path has been updated to %s for %s", this->storagePath.c_str(), this->epName.c_str());
}

std::string TelmateFrameGrabberOpenCVImpl::getCurrentTimestampString() {
    struct timeval tp;
    long int ms;
    std::stringstream sstr_ts;

    gettimeofday(&tp, NULL);
    ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    sstr_ts << ms;
    return sstr_ts.str();
}

long TelmateFrameGrabberOpenCVImpl::getCurrentTimestampLong() {
    struct timeval tp;

    gettimeofday(&tp, NULL);
    return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
}

}   // namespace kurento
<commit_msg>allways create directories<commit_after>/* Autogenerated with kurento-module-creator */

#include "TelmateFrameGrabberOpenCVImpl.hpp"
#include <gst/gst.h>
#include <KurentoException.hpp>
#include <vector>
#include <string>

#define GST_CAT_DEFAULT kurento_telmate_frame_grabber_opencv_impl
GST_DEBUG_CATEGORY_STATIC(GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoTelmateFrameGrabberOpenCVImpl"

namespace kurento {

TelmateFrameGrabberOpenCVImpl::TelmateFrameGrabberOpenCVImpl() {

    GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                            GST_DEFAULT_NAME);

    this->thrLoop = true;
    this->snapInterval = 1000;
    this->epName = "EP_NAME_UNINITIALIZED";
    this->storagePath = "/tmp/";
    this->framesCounter = 0;
    this->outputFormat = FGFMT_JPEG;
    this->lastQueueTimeStamp = 0;
    this->queueLength = 0;
    this->frameQueue = new avis_blocking_queue<VideoFrame*>;

    this->thr = new boost::thread(boost::bind(
            &TelmateFrameGrabberOpenCVImpl::queueHandler, this));
    this->thr->detach();

    GST_INFO("Constructor was called for %s", this->epName.c_str());
}

TelmateFrameGrabberOpenCVImpl::~TelmateFrameGrabberOpenCVImpl() {

    GST_INFO("Destructor was called for %s", this->epName.c_str());

}

void TelmateFrameGrabberOpenCVImpl::cleanup() {

    VideoFrame *ptrVf;

    while(!this->frameQueue->empty()) {
        this->frameQueue->pop(ptrVf); // blocks
        --this->queueLength;
        delete ptrVf;
        ptrVf = NULL;

    }

    this->thrLoop = false;
    boost::this_thread::sleep_for(boost::chrono::milliseconds(250)); /* Give the processing thread some time to exit() */
    GST_INFO("Called release() for %s :: Dequeue completed.", this->epName.c_str());

    delete this->frameQueue;
    this->frameQueue = NULL;

    return;
}

/*
 * This function will be called with each new frame. mat variable
 * contains the current frame. You should insert your image processing code
 * here. Any changes in mat, will be sent through the Media Pipeline.
 */
void TelmateFrameGrabberOpenCVImpl::process(cv::Mat &mat) {
        if ((this->getCurrentTimestampLong() - this->lastQueueTimeStamp) >= this->snapInterval) {

            if(this->thrLoop) { // do not push into the queue if the destructor was called.
                this->lastQueueTimeStamp = this->getCurrentTimestampLong();
                VideoFrame *ptrVf = new VideoFrame();
                ptrVf->mat = mat.clone();
                ptrVf->ts = std::to_string(this->lastQueueTimeStamp);

                this->frameQueue->push(ptrVf);
                ++this->queueLength;
                ++this->framesCounter;
            }
        }
}
/*
 * This function is executed inside the queueHandler thread as a main() function.
 * It pops a VideoFrame from the framequeue and saves it to disk.
 * a boost scoped_lock is implemented to ensure the queue is emptied to disk before
 * the destructor is executed. a 1 second sleep is implemented inside the while() loop
 * to ensure the cpu isn't exhausted while the queue is empty.
 */
void TelmateFrameGrabberOpenCVImpl::queueHandler() {
        VideoFrame *ptrVf;
        cv::Mat image;
        std::vector<int> params;
        std::string image_extension;

        while (this->thrLoop) {

            this->frameQueue->pop(ptrVf); // blocks
            params.clear();     // clear the vector since the last iteration.
            this->lastQueueTimeStamp = this->getCurrentTimestampLong();
            --this->queueLength;

            switch (this->outputFormat) {
                case FGFMT_JPEG:
                    /* Set jpeg params */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
                case FGFMT_PNG:
                    /* Set PNG parameters, compression etc. */
                    params.push_back(CV_IMWRITE_PNG_COMPRESSION);
                    params.push_back(FG_PNG_QUALITY);
                    image_extension = ".png";
                    break;
                default:
                    /* Defaults to jpeg */
                    params.push_back(CV_IMWRITE_JPEG_QUALITY);
                    params.push_back(FG_JPEG_QUALITY);
                    image_extension = ".jpeg";
                    break;
            }

            std::string filename =
                    std::to_string((long) this->framesCounter) + "_" + ptrVf->ts + image_extension;

            //if (this->storagePathSubdir.empty()) {
            this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
            boost::filesystem::path dir(this->storagePathSubdir.c_str());
            if (!boost::filesystem::create_directories(dir)) {
               GST_INFO("%s create_directories() failed for: %s", this->epName.c_str(),
                          this->storagePathSubdir.c_str());
            }
            //}

            std::string fullpath = this->storagePathSubdir + "/" + filename;

            try {
                cv::imwrite(fullpath.c_str(), ptrVf->mat, params);
            }
            catch (...) {
                GST_ERROR("::queueHandler() imgwrite() failed.");
                throw KurentoException(NOT_IMPLEMENTED,
                                       "TelmateFrameGrabberOpenCVImpl::queueHandler() imgwrite() failed. \n");
            }

            ptrVf->mat.release();   // release internal memory allocations

            delete ptrVf;
            ptrVf = NULL;

        }

}

/* This function provides the ability to update the storage path for
 * snapshot storage per endpoint
 */
void TelmateFrameGrabberOpenCVImpl::setStoragePath(std::string storagePath) {

    this->storagePath = storagePath;

    this->storagePathSubdir = this->storagePath + "/frames_" + this->getCurrentTimestampString();
    boost::filesystem::path dir(this->storagePathSubdir.c_str());
    if (!boost::filesystem::create_directories(dir)) {
        GST_INFO("%s create_directories() failed for: %s", this->epName.c_str(),
                  this->storagePathSubdir.c_str());
    }

    GST_INFO("Storage path has been updated to %s for %s", this->storagePath.c_str(), this->epName.c_str());
}

std::string TelmateFrameGrabberOpenCVImpl::getCurrentTimestampString() {
    struct timeval tp;
    long int ms;
    std::stringstream sstr_ts;

    gettimeofday(&tp, NULL);
    ms = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    sstr_ts << ms;
    return sstr_ts.str();
}

long TelmateFrameGrabberOpenCVImpl::getCurrentTimestampLong() {
    struct timeval tp;

    gettimeofday(&tp, NULL);
    return (tp.tv_sec * 1000 + tp.tv_usec / 1000);
}

}   // namespace kurento
<|endoftext|>


<commit_before>
// Copyright (c) 2010 libmv authors.
//
// 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.

// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/multiview/projection.hpp"

namespace openMVG {

/// Compute P = K[R|t]
void P_From_KRt(const Mat3 &K,  const Mat3 &R,  const Vec3 &t, Mat34 *P)
{
  assert(P != nullptr);
  *P = P_From_KRt(K, R, t);
}

Mat34 P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t)
{
  return K * HStack(R,t);
}

void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp)
{
  assert(Kp != nullptr);
  assert(Rp != nullptr);
  assert(tp != nullptr);

  // Decompose using the RQ decomposition HZ A4.1.1 pag.579.
  Mat3 K = P.block(0, 0, 3, 3);

  Mat3 Q;
  Q.setIdentity();

  // Set K(2,1) to zero.
  if (K(2,1) != 0)
  {
    double c = -K(2,2);
    double s = K(2,1);
    const double l = sqrt(c * c + s * s);
    c /= l;
    s /= l;
    Mat3 Qx;
    Qx << 1, 0, 0,
          0, c, -s,
          0, s, c;
    K = K * Qx;
    Q = Qx.transpose() * Q;
  }
  // Set K(2,0) to zero.
  if (K(2,0) != 0)
  {
    double c = K(2,2);
    double s = K(2,0);
    const double l = sqrt(c * c + s * s);
    c /= l;
    s /= l;
    Mat3 Qy;
    Qy << c, 0, s,
          0, 1, 0,
         -s, 0, c;
    K = K * Qy;
    Q = Qy.transpose() * Q;
  }
  // Set K(1,0) to zero.
  if (K(1,0) != 0)
  {
    double c = -K(1,1);
    double s = K(1,0);
    const double l = sqrt(c * c + s * s);
    c /= l;
    s /= l;
    Mat3 Qz;
    Qz << c,-s, 0,
          s, c, 0,
          0, 0, 1;
    K = K * Qz;
    Q = Qz.transpose() * Q;
  }

  Mat3 R = Q;

  //Mat3 H = P.block(0, 0, 3, 3);
  // RQ decomposition
  //Eigen::HouseholderQR<Mat3> qr(H);
  //Mat3 K = qr.matrixQR().triangularView<Eigen::Upper>();
  //Mat3 R = qr.householderQ();

  // Ensure that the diagonal is positive and R determinant == 1.
  if (K(2,2) < 0)
  {
    K = -K;
    R = -R;
  }
  if (K(1,1) < 0)
  {
    Mat3 S;
    S << 1, 0, 0,
         0,-1, 0,
         0, 0, 1;
    K = K * S;
    R = S * R;
  }
  if (K(0,0) < 0)
  {
    Mat3 S;
    S << -1, 0, 0,
          0, 1, 0,
          0, 0, 1;
    K = K * S;
    R = S * R;
  }

  // Compute translation.
  Eigen::PartialPivLU<Mat3> lu(K);
  Vec3 t = lu.solve(P.col(3));

  if(R.determinant() < 0)
  {
    R = -R;
    t = -t;
  }

  // scale K so that K(2,2) = 1
  K = K / K(2,2);

  *Kp = K;
  *Rp = R;
  *tp = t;
}

Mat3 F_from_P(const Mat34 & P1, const Mat34 & P2)
{
  Mat3 F12;

  typedef Eigen::Matrix<double, 2, 4> Mat24;
  Mat24 X1 = P1.block<2, 4>(1, 0);
  Mat24 X2;
  X2 << P1.row(2), P1.row(0);
  Mat24 X3 = P1.block<2, 4>(0, 0);
  Mat24 Y1 = P2.block<2, 4>(1, 0);
  Mat24 Y2;
  Y2 << P2.row(2), P2.row(0);
  Mat24 Y3 = P2.block<2, 4>(0, 0);

  Mat4 X1Y1, X2Y1, X3Y1, X1Y2, X2Y2, X3Y2, X1Y3, X2Y3, X3Y3;
  X1Y1 << X1, Y1;
  X2Y1 << X2, Y1;
  X3Y1 << X3, Y1;
  X1Y2 << X1, Y2;
  X2Y2 << X2, Y2;
  X3Y2 << X3, Y2;
  X1Y3 << X1, Y3;
  X2Y3 << X2, Y3;
  X3Y3 << X3, Y3;

  F12 << X1Y1.determinant(), X2Y1.determinant(), X3Y1.determinant(),
          X1Y2.determinant(), X2Y2.determinant(), X3Y2.determinant(),
          X1Y3.determinant(), X2Y3.determinant(), X3Y3.determinant();

  return F12;
}

Vec2 Project(const Mat34 &P, const Vec3 &X)
{
  return Vec3(P * X.homogeneous()).hnormalized();
}

void Project(const Mat34 &P, const Mat3X &X, Mat2X *x)
{
  assert(x != nullptr);
  Project(P, Mat4X(X.colwise().homogeneous()), x);
}

void Project(const Mat34 &P, const Mat4X &X, Mat2X *x)
{
  assert(x != nullptr);
  *x = Project(P, X);
}

Mat2X Project(const Mat34 &P, const Mat3X &X)
{
  return Project(P, Mat4X(X.colwise().homogeneous()));
}

Mat2X Project(const Mat34 &P, const Mat4X &X)
{
  return Mat3X(P * X).colwise().hnormalized();
}

void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X)
{
  assert(X != nullptr);
  *X = H.hnormalized();
}

void EuclideanToHomogeneous(const Mat &X, Mat *H)
{
  assert(H != nullptr);
  *H = X.colwise().homogeneous();
}

double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X)
{
  return (R*X)[2] + t[2];
}

Vec3 EuclideanToHomogeneous(const Vec2 &x)
{
  return x.homogeneous();
}

void HomogeneousToEuclidean(const Mat &H, Mat *X)
{
  assert(X != nullptr);
  *X = H.colwise().hnormalized();
}

Mat3X EuclideanToHomogeneous(const Mat2X &x)
{
  return x.colwise().homogeneous();
}

void EuclideanToHomogeneous(const Mat2X &x, Mat3X *h)
{
  assert(h != nullptr);
  *h = x.colwise().homogeneous();
}

void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e)
{
  assert(e != nullptr);
  *e = h.colwise().hnormalized();
}

void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n)
{
  assert(n != nullptr);
  HomogeneousToNormalizedCamera(x.colwise().homogeneous(), K, n);
}

void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n)
{
  assert(n != nullptr);
  *n = (K.inverse() * x).colwise().hnormalized();
}

/// Estimates the root mean square error (2D)
double reprojectionErrorRMSE(const Mat2X &x_image,
                           const Mat4X &X_world,
                           const Mat34 &P)
{
    const std::size_t num_points = x_image.cols();
    const Mat2X dx = Project(P, X_world) - x_image;
    return std::sqrt(dx.squaredNorm() / num_points);
}

/// Estimates the root mean square error (2D)
double reprojectionErrorRMSE(const Mat2X &x_image,
                           const Mat3X &X_world,
                           const Mat3 &K,
                           const Mat3 &R,
                           const Vec3 &t)
{
    Mat34 P;
    P_From_KRt(K, R, t, &P);
    return reprojectionErrorRMSE(x_image, X_world.colwise().homogeneous(), P);
}

} // namespace openMVG

<commit_msg>[multiview] renaming<commit_after>
// Copyright (c) 2010 libmv authors.
//
// 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.

// Copyright (c) 2012, 2013 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <openMVG/multiview/projection.hpp>

#include <cmath>

namespace openMVG {

/// Compute P = K[R|t]
void P_From_KRt(const Mat3 &K,  const Mat3 &R,  const Vec3 &t, Mat34 *P)
{
  assert(P != nullptr);
  *P = P_From_KRt(K, R, t);
}

Mat34 P_From_KRt(const Mat3 &K, const Mat3 &R, const Vec3 &t)
{
  return K * HStack(R,t);
}

void KRt_From_P(const Mat34 &P, Mat3 *Kp, Mat3 *Rp, Vec3 *tp)
{
  assert(Kp != nullptr);
  assert(Rp != nullptr);
  assert(tp != nullptr);

  // Decompose using the RQ decomposition HZ A4.1.1 pag.579.
  Mat3 K = P.block(0, 0, 3, 3);

  Mat3 Q;
  Q.setIdentity();

  // Set K(2,1) to zero.
  if (K(2,1) != 0)
  {
    double c = -K(2,2);
    double s = K(2,1);
    const double lenght = std::sqrt(c * c + s * s);
    c /= lenght;
    s /= lenght;
    Mat3 Qx;
    Qx << 1, 0, 0,
          0, c, -s,
          0, s, c;
    K = K * Qx;
    Q = Qx.transpose() * Q;
  }
  // Set K(2,0) to zero.
  if (K(2,0) != 0)
  {
    double c = K(2,2);
    double s = K(2,0);
    const double length = std::sqrt(c * c + s * s);
    c /= length;
    s /= length;
    Mat3 Qy;
    Qy << c, 0, s,
          0, 1, 0,
         -s, 0, c;
    K = K * Qy;
    Q = Qy.transpose() * Q;
  }
  // Set K(1,0) to zero.
  if (K(1,0) != 0)
  {
    double c = -K(1,1);
    double s = K(1,0);
    const double length = sqrt(c * c + s * s);
    c /= length;
    s /= length;
    Mat3 Qz;
    Qz << c,-s, 0,
          s, c, 0,
          0, 0, 1;
    K = K * Qz;
    Q = Qz.transpose() * Q;
  }

  Mat3 R = Q;

  //Mat3 H = P.block(0, 0, 3, 3);
  // RQ decomposition
  //Eigen::HouseholderQR<Mat3> qr(H);
  //Mat3 K = qr.matrixQR().triangularView<Eigen::Upper>();
  //Mat3 R = qr.householderQ();

  // Ensure that the diagonal is positive and R determinant == 1.
  if (K(2,2) < 0)
  {
    K = -K;
    R = -R;
  }
  if (K(1,1) < 0)
  {
    Mat3 S;
    S << 1, 0, 0,
         0,-1, 0,
         0, 0, 1;
    K = K * S;
    R = S * R;
  }
  if (K(0,0) < 0)
  {
    Mat3 S;
    S << -1, 0, 0,
          0, 1, 0,
          0, 0, 1;
    K = K * S;
    R = S * R;
  }

  // Compute translation.
  Eigen::PartialPivLU<Mat3> lu(K);
  Vec3 t = lu.solve(P.col(3));

  if(R.determinant() < 0)
  {
    R = -R;
    t = -t;
  }

  // scale K so that K(2,2) = 1
  K = K / K(2,2);

  *Kp = K;
  *Rp = R;
  *tp = t;
}

Mat3 F_from_P(const Mat34 & P1, const Mat34 & P2)
{
  Mat3 F12;

  typedef Eigen::Matrix<double, 2, 4> Mat24;
  Mat24 X1 = P1.block<2, 4>(1, 0);
  Mat24 X2;
  X2 << P1.row(2), P1.row(0);
  Mat24 X3 = P1.block<2, 4>(0, 0);
  Mat24 Y1 = P2.block<2, 4>(1, 0);
  Mat24 Y2;
  Y2 << P2.row(2), P2.row(0);
  Mat24 Y3 = P2.block<2, 4>(0, 0);

  Mat4 X1Y1, X2Y1, X3Y1, X1Y2, X2Y2, X3Y2, X1Y3, X2Y3, X3Y3;
  X1Y1 << X1, Y1;
  X2Y1 << X2, Y1;
  X3Y1 << X3, Y1;
  X1Y2 << X1, Y2;
  X2Y2 << X2, Y2;
  X3Y2 << X3, Y2;
  X1Y3 << X1, Y3;
  X2Y3 << X2, Y3;
  X3Y3 << X3, Y3;

  F12 << X1Y1.determinant(), X2Y1.determinant(), X3Y1.determinant(),
          X1Y2.determinant(), X2Y2.determinant(), X3Y2.determinant(),
          X1Y3.determinant(), X2Y3.determinant(), X3Y3.determinant();

  return F12;
}

Vec2 Project(const Mat34 &P, const Vec3 &X)
{
  return Vec3(P * X.homogeneous()).hnormalized();
}

void Project(const Mat34 &P, const Mat3X &X, Mat2X *x)
{
  assert(x != nullptr);
  Project(P, Mat4X(X.colwise().homogeneous()), x);
}

void Project(const Mat34 &P, const Mat4X &X, Mat2X *x)
{
  assert(x != nullptr);
  *x = Project(P, X);
}

Mat2X Project(const Mat34 &P, const Mat3X &X)
{
  return Project(P, Mat4X(X.colwise().homogeneous()));
}

Mat2X Project(const Mat34 &P, const Mat4X &X)
{
  return Mat3X(P * X).colwise().hnormalized();
}

void HomogeneousToEuclidean(const Vec4 &H, Vec3 *X)
{
  assert(X != nullptr);
  *X = H.hnormalized();
}

void EuclideanToHomogeneous(const Mat &X, Mat *H)
{
  assert(H != nullptr);
  *H = X.colwise().homogeneous();
}

double Depth(const Mat3 &R, const Vec3 &t, const Vec3 &X)
{
  return (R*X)[2] + t[2];
}

Vec3 EuclideanToHomogeneous(const Vec2 &x)
{
  return x.homogeneous();
}

void HomogeneousToEuclidean(const Mat &H, Mat *X)
{
  assert(X != nullptr);
  *X = H.colwise().hnormalized();
}

Mat3X EuclideanToHomogeneous(const Mat2X &x)
{
  return x.colwise().homogeneous();
}

void EuclideanToHomogeneous(const Mat2X &x, Mat3X *h)
{
  assert(h != nullptr);
  *h = x.colwise().homogeneous();
}

void HomogeneousToEuclidean(const Mat3X &h, Mat2X *e)
{
  assert(e != nullptr);
  *e = h.colwise().hnormalized();
}

void EuclideanToNormalizedCamera(const Mat2X &x, const Mat3 &K, Mat2X *n)
{
  assert(n != nullptr);
  HomogeneousToNormalizedCamera(x.colwise().homogeneous(), K, n);
}

void HomogeneousToNormalizedCamera(const Mat3X &x, const Mat3 &K, Mat2X *n)
{
  assert(n != nullptr);
  *n = (K.inverse() * x).colwise().hnormalized();
}

/// Estimates the root mean square error (2D)
double reprojectionErrorRMSE(const Mat2X &x_image,
                           const Mat4X &X_world,
                           const Mat34 &P)
{
    const std::size_t num_points = x_image.cols();
    const Mat2X dx = Project(P, X_world) - x_image;
    return std::sqrt(dx.squaredNorm() / num_points);
}

/// Estimates the root mean square error (2D)
double reprojectionErrorRMSE(const Mat2X &x_image,
                           const Mat3X &X_world,
                           const Mat3 &K,
                           const Mat3 &R,
                           const Vec3 &t)
{
    Mat34 P;
    P_From_KRt(K, R, t, &P);
    return reprojectionErrorRMSE(x_image, X_world.colwise().homogeneous(), P);
}

} // namespace openMVG

<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by Norman Krmer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This 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
    General Public License for more details.

    You should have received a copy of the GNU General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "oggdata.h"
#include "isound/loader.h"
#include "iutil/comp.h"

CS_IMPLEMENT_PLUGIN

SCF_IMPLEMENT_IBASE (csOggSoundData)
  SCF_IMPLEMENTS_INTERFACE (iSoundData)
SCF_IMPLEMENT_IBASE_END

static size_t cs_ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource)
{
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;
  size_t br = MIN (size*nmemb, ds->length-ds->pos);

  memcpy (ptr, ds->data+ds->pos, br);

  ds->pos +=br;
  return br;
}

static int cs_ogg_seek (void *datasource, int64_t offset, int whence)
{
  size_t np;
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;

  if (whence == SEEK_SET)
    np = offset;
  else if (whence == SEEK_CUR)
    np = ds->pos + offset;
  else if (whence == SEEK_END)
    np = ds->length + offset;
  else
    return -1;

  if (np > ds->length)
    return -1;

  ds->pos = np;
  return 0;
}

static int cs_ogg_close (void *)
{
  return 0;
}

static long cs_ogg_tell (void *datasource)
{
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;
  return ds->pos;
}

csOggSoundData::cs_ov_callbacks::cs_ov_callbacks ()
{
  read_func = cs_ogg_read;
  seek_func = cs_ogg_seek;
  close_func = cs_ogg_close;
  tell_func = cs_ogg_tell;
}

CS_IMPLEMENT_STATIC_VAR (GetCallbacks, csOggSoundData::cs_ov_callbacks, ())

csOggSoundData::csOggSoundData (iBase *parent, uint8 *data, size_t len)
{
  SCF_CONSTRUCT_IBASE (parent);
#ifdef CS_LITTLE_ENDIAN
  endian = 0;
#else
  endian = 1;
#endif

  ds = new datastore (data, len, true);
  ogg_ok = false;
  buf = NULL;
  len = 0;
  current_section = 0;
  fmt.Bits = 16;
  fmt.Channels = 2;
}

csOggSoundData::~csOggSoundData ()
{
  ov_clear (&vf);
  delete [] buf;
  delete ds;
}

bool csOggSoundData::Initialize(const csSoundFormat *fmt)
{
  if (!ogg_ok)
  {
    ogg_ok = ov_open_callbacks(ds, &vf, NULL, 0, *(ov_callbacks*)GetCallbacks ()) == 0;
    if (fmt->Channels != -1)
      this->fmt.Channels = fmt->Channels;
    if (fmt->Freq != -1)
      this->fmt.Freq = fmt->Freq;

  }
  return ogg_ok;
}

bool csOggSoundData::IsOgg (void *Buffer, size_t len)
{
  datastore *dd = new datastore ((uint8*)Buffer, len, false);
  OggVorbis_File f;
  bool ok = ov_open_callbacks(dd, &f, NULL, 0, *(ov_callbacks*)GetCallbacks ()) == 0;
  ov_clear (&f);
  delete dd;
  return ok;
}

const csSoundFormat* csOggSoundData::GetFormat()
{
  return &fmt;
}

bool csOggSoundData::IsStatic()
{
  return false;
}

long csOggSoundData::GetStaticSampleCount()
{
  return -1;
}

void *csOggSoundData::GetStaticData()
{
  return NULL;
}

void csOggSoundData::ResetStreamed()
{
  ogg_ok = ov_raw_seek (&vf, 0) == 0;
}

void *csOggSoundData::ReadStreamed(long &NumSamples)
{
  if (ogg_ok)
  {
    long buffersize = NumSamples * (fmt.Bits >> 3) * fmt.Channels;

    if (buffersize > len)
    {
      buf = (uint8*) realloc (buf, buffersize);
      len = buffersize;
    }

    long bytes_read = ov_read (&vf, (char*)buf, buffersize, endian,
			       fmt.Bits>>3, 1, &current_section);

    NumSamples = bytes_read / ((fmt.Bits >> 3) * fmt.Channels);
    return buf;
  }

  NumSamples = 0;
  return NULL;
}

// ogg loader

class csOggLoader : public iSoundLoader
{
public:
  SCF_DECLARE_IBASE;

  struct eiComponent : public iComponent
  {
    SCF_DECLARE_EMBEDDED_IBASE (csOggLoader);
    virtual bool Initialize (iObjectRegistry *){return true;}
  }scfiComponent;

  csOggLoader (iBase *parent)
  {
    SCF_CONSTRUCT_IBASE (parent);
    SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);
  }

  virtual csPtr<iSoundData> LoadSound (void *Buffer, unsigned long Size) const
  {
    csOggSoundData *sd=NULL;
    if (csOggSoundData::IsOgg (Buffer, Size))
      sd = new csOggSoundData ((iBase*)this, (uint8*)Buffer, Size);
    return csPtr<iSoundData> (sd);
  }
};

SCF_IMPLEMENT_IBASE (csOggLoader)
  SCF_IMPLEMENTS_INTERFACE (iSoundLoader)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csOggLoader::eiComponent)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

SCF_IMPLEMENT_FACTORY (csOggLoader);

SCF_EXPORT_CLASS_TABLE (sndogg)
  SCF_EXPORT_CLASS (csOggLoader, "crystalspace.sound.loader.ogg", "Ogg Vorbis Sound Loader")
SCF_EXPORT_CLASS_TABLE_END

<commit_msg>fix ogg loader crash when sound hasn't been initialized<commit_after>/*
    Copyright (C) 2001 by Norman Krmer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This 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
    General Public License for more details.

    You should have received a copy of the GNU General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "oggdata.h"
#include "isound/loader.h"
#include "iutil/comp.h"

CS_IMPLEMENT_PLUGIN

SCF_IMPLEMENT_IBASE (csOggSoundData)
  SCF_IMPLEMENTS_INTERFACE (iSoundData)
SCF_IMPLEMENT_IBASE_END

static size_t cs_ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource)
{
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;
  size_t br = MIN (size*nmemb, ds->length-ds->pos);

  memcpy (ptr, ds->data+ds->pos, br);

  ds->pos +=br;
  return br;
}

static int cs_ogg_seek (void *datasource, int64_t offset, int whence)
{
  size_t np;
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;

  if (whence == SEEK_SET)
    np = offset;
  else if (whence == SEEK_CUR)
    np = ds->pos + offset;
  else if (whence == SEEK_END)
    np = ds->length + offset;
  else
    return -1;

  if (np > ds->length)
    return -1;

  ds->pos = np;
  return 0;
}

static int cs_ogg_close (void *)
{
  return 0;
}

static long cs_ogg_tell (void *datasource)
{
  csOggSoundData::datastore *ds = (csOggSoundData::datastore*)datasource;
  return ds->pos;
}

csOggSoundData::cs_ov_callbacks::cs_ov_callbacks ()
{
  read_func = cs_ogg_read;
  seek_func = cs_ogg_seek;
  close_func = cs_ogg_close;
  tell_func = cs_ogg_tell;
}

CS_IMPLEMENT_STATIC_VAR (GetCallbacks, csOggSoundData::cs_ov_callbacks, ())

csOggSoundData::csOggSoundData (iBase *parent, uint8 *data, size_t len)
{
  SCF_CONSTRUCT_IBASE (parent);
#ifdef CS_LITTLE_ENDIAN
  endian = 0;
#else
  endian = 1;
#endif

  ds = new datastore (data, len, true);
  ogg_ok = false;
  buf = NULL;
  len = 0;
  current_section = 0;
  fmt.Bits = 16;
  fmt.Channels = 2;
  memset (&vf, 0, sizeof(vf));
}

csOggSoundData::~csOggSoundData ()
{
  ov_clear (&vf);
  delete [] buf;
  delete ds;
}

bool csOggSoundData::Initialize(const csSoundFormat *fmt)
{
  if (!ogg_ok)
  {
    ogg_ok = ov_open_callbacks(ds, &vf, NULL, 0, *(ov_callbacks*)GetCallbacks ()) == 0;
    if (fmt->Channels != -1)
      this->fmt.Channels = fmt->Channels;
    if (fmt->Freq != -1)
      this->fmt.Freq = fmt->Freq;

  }
  return ogg_ok;
}

bool csOggSoundData::IsOgg (void *Buffer, size_t len)
{
  datastore *dd = new datastore ((uint8*)Buffer, len, false);
  OggVorbis_File f;
  bool ok = ov_open_callbacks(dd, &f, NULL, 0, *(ov_callbacks*)GetCallbacks ()) == 0;
  ov_clear (&f);
  delete dd;
  return ok;
}

const csSoundFormat* csOggSoundData::GetFormat()
{
  return &fmt;
}

bool csOggSoundData::IsStatic()
{
  return false;
}

long csOggSoundData::GetStaticSampleCount()
{
  return -1;
}

void *csOggSoundData::GetStaticData()
{
  return NULL;
}

void csOggSoundData::ResetStreamed()
{
  ogg_ok = ov_raw_seek (&vf, 0) == 0;
}

void *csOggSoundData::ReadStreamed(long &NumSamples)
{
  if (ogg_ok)
  {
    long buffersize = NumSamples * (fmt.Bits >> 3) * fmt.Channels;

    if (buffersize > len)
    {
      buf = (uint8*) realloc (buf, buffersize);
      len = buffersize;
    }

    long bytes_read = ov_read (&vf, (char*)buf, buffersize, endian,
			       fmt.Bits>>3, 1, &current_section);

    NumSamples = bytes_read / ((fmt.Bits >> 3) * fmt.Channels);
    return buf;
  }

  NumSamples = 0;
  return NULL;
}

// ogg loader

class csOggLoader : public iSoundLoader
{
public:
  SCF_DECLARE_IBASE;

  struct eiComponent : public iComponent
  {
    SCF_DECLARE_EMBEDDED_IBASE (csOggLoader);
    virtual bool Initialize (iObjectRegistry *){return true;}
  }scfiComponent;

  csOggLoader (iBase *parent)
  {
    SCF_CONSTRUCT_IBASE (parent);
    SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);
  }

  virtual csPtr<iSoundData> LoadSound (void *Buffer, unsigned long Size) const
  {
    csOggSoundData *sd=NULL;
    if (csOggSoundData::IsOgg (Buffer, Size))
      sd = new csOggSoundData ((iBase*)this, (uint8*)Buffer, Size);
    return csPtr<iSoundData> (sd);
  }
};

SCF_IMPLEMENT_IBASE (csOggLoader)
  SCF_IMPLEMENTS_INTERFACE (iSoundLoader)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csOggLoader::eiComponent)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

SCF_IMPLEMENT_FACTORY (csOggLoader);

SCF_EXPORT_CLASS_TABLE (sndogg)
  SCF_EXPORT_CLASS (csOggLoader, "crystalspace.sound.loader.ogg", "Ogg Vorbis Sound Loader")
SCF_EXPORT_CLASS_TABLE_END

<|endoftext|>