<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkSurfaceVtkMapper3D.h"
#include "mitkDataTreeNode.h"
#include "mitkProperties.h"
#include "mitkColorProperty.h"
#include "mitkLookupTableProperty.h"
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyDataNormals.h>

//##ModelId=3E70F60301D5
const mitk::Surface* mitk::SurfaceVtkMapper3D::GetInput()
{
  return static_cast<const mitk::Surface * > ( GetData() );
}

//##ModelId=3E70F60301F4
mitk::SurfaceVtkMapper3D::SurfaceVtkMapper3D()
{
  m_VtkPolyDataMapper = vtkPolyDataMapper::New();
  m_VtkPolyDataNormals = vtkPolyDataNormals::New();

  m_Actor = vtkActor::New();
  m_Actor->SetMapper(m_VtkPolyDataMapper);

  m_GenerateNormals = false;
}

//##ModelId=3E70F60301F5
mitk::SurfaceVtkMapper3D::~SurfaceVtkMapper3D()
{
  m_VtkPolyDataMapper->Delete();
  m_VtkPolyDataNormals->Delete();

  if(m_Prop3D != m_Actor)
    m_Actor->Delete();
}

//##ModelId=3EF19FA803BF
void mitk::SurfaceVtkMapper3D::GenerateData(mitk::BaseRenderer* renderer)
{
  m_Prop3D=NULL;

  if(IsVisible(renderer)==false)
  {
    m_Actor->VisibilityOff();
    return;
  }
  m_Actor->VisibilityOn();

  //
  // get the TimeSlicedGeometry of the input object
  //
  mitk::Surface::Pointer input  = const_cast< mitk::Surface* >( this->GetInput() );
  const TimeSlicedGeometry* inputTimeGeometry = dynamic_cast< const TimeSlicedGeometry* >( input->GetUpdatedGeometry() );
  if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) )
    return;

  //
  // get the world time
  //
  const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D();
  assert( worldGeometry != NULL );
  ScalarType time = worldGeometry->GetTimeBoundsInMS()[ 0 ];

  //
  // convert the world time in time steps of the input object
  //
  int timestep=0;
  if( time > -ScalarTypeNumericTraits::max() )
    timestep = inputTimeGeometry->MSToTimeStep( time );
  if( inputTimeGeometry->IsValidTime( timestep ) == false )
    return;
//  std::cout << "time: "<< time << std::endl;
//  std::cout << "timestep: "<<timestep << std::endl;

  //
  // set the input-object at time t for the mapper
  //

  vtkPolyData * polydata = input->GetVtkPolyData( timestep );
  if(polydata == NULL)
    return;

  if ( m_GenerateNormals )
  {
    m_VtkPolyDataNormals->SetInput( polydata );
    m_VtkPolyDataMapper->SetInput( m_VtkPolyDataNormals->GetOutput() );
  }
  else
  {
    m_VtkPolyDataMapper->SetInput( polydata );
  }

  //
  // apply properties read from the PropertyList
  //
  ApplyProperties(m_Actor, renderer);

  m_Prop3D = m_Actor;
}

void mitk::SurfaceVtkMapper3D::ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer)
{
  bool useCellData;
  if (dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("useCellDataForColouring").GetPointer()) == NULL)
    useCellData = false;
  else
    useCellData = dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("useCellDataForColouring").GetPointer())->GetValue();

  bool usePointData;
  if (dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("usePointDataForColouring").GetPointer()) == NULL)
    usePointData = false;
  else
    usePointData = dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("usePointDataForColouring").GetPointer())->GetValue();

  if (useCellData)
  {
    m_VtkPolyDataMapper->SetColorModeToDefault();
    m_VtkPolyDataMapper->SetScalarRange(0,255);
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_VtkPolyDataMapper->SetScalarModeToUseCellData();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    m_Actor->GetProperty()->SetInterpolationToPhong();
  }
  else if (usePointData)
  {
    float scalarsMin = 0;
    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMinimum").GetPointer()) != NULL)
      scalarsMin = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMinimum").GetPointer())->GetValue();

    float scalarsMax = 0.1;
    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMaximum").GetPointer()) != NULL)
      scalarsMax = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMaximum").GetPointer())->GetValue();

    m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax);
    m_VtkPolyDataMapper->SetColorModeToMapScalars();
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    m_Actor->GetProperty()->SetInterpolationToPhong();
  }
  else
  {
    Superclass::ApplyProperties(m_Actor, renderer);
    m_VtkPolyDataMapper->ScalarVisibilityOff();
  }

  int scalarMode = VTK_COLOR_MODE_DEFAULT;
  if(this->GetDataTreeNode()->GetIntProperty("scalar mode", scalarMode, renderer))
  {
    m_VtkPolyDataMapper->SetScalarMode(scalarMode);
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    //m_Actor->GetProperty()->SetInterpolationToPhong();
  }

  mitk::LookupTableProperty::Pointer lookupTableProp;
  lookupTableProp = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataTreeNode()->GetProperty("LookupTable", renderer).GetPointer());
	if (lookupTableProp.IsNotNull() )
	{
    m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable().GetVtkLookupTable());
  }

  mitk::LevelWindow levelWindow;
  if(this->GetDataTreeNode()->GetLevelWindow(levelWindow, renderer, "levelWindow"))
  {
    m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax());
  }
  else
  if(this->GetDataTreeNode()->GetLevelWindow(levelWindow, renderer))
  {
    m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax());
  }

  bool wireframe=false;
  GetDataTreeNode()->GetVisibility(wireframe, renderer, "wireframe");
  if(wireframe)
    m_Actor->GetProperty()->SetRepresentationToWireframe();
  else
    m_Actor->GetProperty()->SetRepresentationToSurface();
}
<commit_msg>FIX: never return empty prop (always set m_Prop3D to m_Actor). Before: when invisible when OpenGLRenderer::UpdateIncludingVtkActors was called, prop was NULL, thus not added to prop-list in vtkRenderer and stayed invisible after switching to visible, until some called UpdateIncludinVtkActors again.<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkSurfaceVtkMapper3D.h"
#include "mitkDataTreeNode.h"
#include "mitkProperties.h"
#include "mitkColorProperty.h"
#include "mitkLookupTableProperty.h"
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyDataNormals.h>

//##ModelId=3E70F60301D5
const mitk::Surface* mitk::SurfaceVtkMapper3D::GetInput()
{
  return static_cast<const mitk::Surface * > ( GetData() );
}

//##ModelId=3E70F60301F4
mitk::SurfaceVtkMapper3D::SurfaceVtkMapper3D()
{
  m_VtkPolyDataMapper = vtkPolyDataMapper::New();
  m_VtkPolyDataNormals = vtkPolyDataNormals::New();

  m_Actor = vtkActor::New();
  m_Actor->SetMapper(m_VtkPolyDataMapper);

  m_Prop3D = m_Actor;

  m_GenerateNormals = false;
}

//##ModelId=3E70F60301F5
mitk::SurfaceVtkMapper3D::~SurfaceVtkMapper3D()
{
  m_VtkPolyDataMapper->Delete();
  m_VtkPolyDataNormals->Delete();

  if(m_Prop3D != m_Actor)
    m_Actor->Delete();
}

//##ModelId=3EF19FA803BF
void mitk::SurfaceVtkMapper3D::GenerateData(mitk::BaseRenderer* renderer)
{
  bool visible = IsVisible(renderer);

  if(visible==false)
  {
    m_Actor->VisibilityOff();
    return;
  }

  //
  // get the TimeSlicedGeometry of the input object
  //
  mitk::Surface::Pointer input  = const_cast< mitk::Surface* >( this->GetInput() );
  const TimeSlicedGeometry* inputTimeGeometry = dynamic_cast< const TimeSlicedGeometry* >( input->GetUpdatedGeometry() );
  if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) )
  {
    m_Actor->VisibilityOff();
    return;
  }

  //
  // get the world time
  //
  const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D();
  assert( worldGeometry != NULL );
  ScalarType time = worldGeometry->GetTimeBoundsInMS()[ 0 ];

  //
  // convert the world time in time steps of the input object
  //
  int timestep=0;
  if( time > -ScalarTypeNumericTraits::max() )
    timestep = inputTimeGeometry->MSToTimeStep( time );
  if( inputTimeGeometry->IsValidTime( timestep ) == false )
  {
    m_Actor->VisibilityOff();
    return;
  }
//  std::cout << "time: "<< time << std::endl;
//  std::cout << "timestep: "<<timestep << std::endl;

  //
  // set the input-object at time t for the mapper
  //

  vtkPolyData * polydata = input->GetVtkPolyData( timestep );
  if(polydata == NULL)
  {
    m_Actor->VisibilityOff();
    return;
  }

  if ( m_GenerateNormals )
  {
    m_VtkPolyDataNormals->SetInput( polydata );
    m_VtkPolyDataMapper->SetInput( m_VtkPolyDataNormals->GetOutput() );
  }
  else
  {
    m_VtkPolyDataMapper->SetInput( polydata );
  }

  //
  // apply properties read from the PropertyList
  //
  ApplyProperties(m_Actor, renderer);

  if(visible)
    m_Actor->VisibilityOn();
}

void mitk::SurfaceVtkMapper3D::ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer)
{
  bool useCellData;
  if (dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("useCellDataForColouring").GetPointer()) == NULL)
    useCellData = false;
  else
    useCellData = dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("useCellDataForColouring").GetPointer())->GetValue();

  bool usePointData;
  if (dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("usePointDataForColouring").GetPointer()) == NULL)
    usePointData = false;
  else
    usePointData = dynamic_cast<mitk::BoolProperty *>(this->GetDataTreeNode()->GetProperty("usePointDataForColouring").GetPointer())->GetValue();

  if (useCellData)
  {
    m_VtkPolyDataMapper->SetColorModeToDefault();
    m_VtkPolyDataMapper->SetScalarRange(0,255);
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_VtkPolyDataMapper->SetScalarModeToUseCellData();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    m_Actor->GetProperty()->SetInterpolationToPhong();
  }
  else if (usePointData)
  {
    float scalarsMin = 0;
    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMinimum").GetPointer()) != NULL)
      scalarsMin = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMinimum").GetPointer())->GetValue();

    float scalarsMax = 0.1;
    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMaximum").GetPointer()) != NULL)
      scalarsMax = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("ScalarsRangeMaximum").GetPointer())->GetValue();

    m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax);
    m_VtkPolyDataMapper->SetColorModeToMapScalars();
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    m_Actor->GetProperty()->SetInterpolationToPhong();
  }
  else
  {
    Superclass::ApplyProperties(m_Actor, renderer);
    m_VtkPolyDataMapper->ScalarVisibilityOff();
  }

  int scalarMode = VTK_COLOR_MODE_DEFAULT;
  if(this->GetDataTreeNode()->GetIntProperty("scalar mode", scalarMode, renderer))
  {
    m_VtkPolyDataMapper->SetScalarMode(scalarMode);
    m_VtkPolyDataMapper->ScalarVisibilityOn();
    m_Actor->GetProperty()->SetSpecular (1);
    m_Actor->GetProperty()->SetSpecularPower (50);
    //m_Actor->GetProperty()->SetInterpolationToPhong();
  }

  mitk::LookupTableProperty::Pointer lookupTableProp;
  lookupTableProp = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataTreeNode()->GetProperty("LookupTable", renderer).GetPointer());
	if (lookupTableProp.IsNotNull() )
	{
    m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable().GetVtkLookupTable());
  }

  mitk::LevelWindow levelWindow;
  if(this->GetDataTreeNode()->GetLevelWindow(levelWindow, renderer, "levelWindow"))
  {
    m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax());
  }
  else
  if(this->GetDataTreeNode()->GetLevelWindow(levelWindow, renderer))
  {
    m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax());
  }

  bool wireframe=false;
  GetDataTreeNode()->GetVisibility(wireframe, renderer, "wireframe");
  if(wireframe)
    m_Actor->GetProperty()->SetRepresentationToWireframe();
  else
    m_Actor->GetProperty()->SetRepresentationToSurface();
}
<|endoftext|>


<commit_before>// main window and event handling for X11

#include <stdio.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <GL/glx.h>

#include "drawstuff/drawstuff.h"
#include "drawstuff/version.h"
#include "internal.h"

//***************************************************************************
// error handling for unix

static void printMessage (char *msg1, char *msg2, va_list ap)
{
  fflush (stderr);
  fflush (stdout);
  fprintf (stderr,"\n%s: ",msg1);
  vfprintf (stderr,msg2,ap);
  fprintf (stderr,"\n");
  fflush (stderr);
}

extern "C" void dsError (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("Error",msg,ap);
  exit (1);
}

extern "C" void dsDebug (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("INTERNAL ERROR",msg,ap);
  // *((char *)0) = 0;	 ... commit SEGVicide ?
  abort();
}

extern "C" void dsPrint (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  vprintf (msg,ap);
}

//***************************************************************************
// openGL window

// X11 display info
static Display *display=0;
static int screen=0;
static XVisualInfo *visual=0;		// best visual for openGL
static Colormap colormap=0;		// window's colormap
static Atom wm_protocols_atom = 0;
static Atom wm_delete_window_atom = 0;

// window and openGL
static Window win=0;			// X11 window, 0 if not initialized
static int width=0,height=0;		// window size
static GLXContext glx_context=0;	// openGL rendering context
static int last_key_pressed=0;		// last key pressed in the window
static int run=1;			// 1 if simulation running
static int pause=0;			// 1 if in `pause' mode
static int singlestep=0;		// 1 if single step key pressed
static int writeframes=0;		// 1 if frame files to be written

static void createMainWindow (int _width, int _height)
{
  // create X11 display connection
  display = XOpenDisplay (0);
  if (!display) dsError (0,"can not open X11 display");
  screen = DefaultScreen(display);

  // get GL visual
  static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
			     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
			     GLX_BLUE_SIZE,4, None};
  visual = glXChooseVisual (display,screen,attribList);
  if (!visual) dsError ("no good X11 visual found for OpenGL");

  // create colormap
  colormap = XCreateColormap (display,RootWindow(display,screen),
			      visual->visual,AllocNone);

  // initialize variables
  win = 0;
  width = _width;
  height = _height;
  glx_context = 0;
  last_key_pressed = 0;

  if (width < 1 || height < 1) dsDebug (0,"bad window width or height");

  // create the window
  XSetWindowAttributes attributes;
  attributes.background_pixel = BlackPixel(display,screen);
  attributes.colormap = colormap;
  attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
    KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
    StructureNotifyMask;
  win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
		       0,visual->depth, InputOutput,visual->visual,
		       CWBackPixel | CWColormap | CWEventMask,&attributes);

  // associate a GLX context with the window
  glx_context = glXCreateContext (display,visual,0,GL_TRUE);
  if (!glx_context) dsError ("can't make an OpenGL context");

  // set the window title
  XTextProperty window_name;
  window_name.value = (unsigned char *) "Simulation";
  window_name.encoding = XA_STRING;
  window_name.format = 8;
  window_name.nitems = strlen((char *) window_name.value);
  XSetWMName (display,win,&window_name);

  // participate in the window manager 'delete yourself' protocol
  wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
  wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
  if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
    dsError ("XSetWMProtocols() call failed");

  // pop up the window
  XMapWindow (display,win);
  XSync (display,win);
}

static void destroyMainWindow()
{
  glXDestroyContext (display,glx_context);
  XDestroyWindow (display,win);
  XSync (display,0);
  display = 0;
  win = 0;
  glx_context = 0;
}

static void handleEvent (XEvent &event, dsFunctions *fn)
{
  static int mx=0,my=0; 	// mouse position
  static int mode = 0;		// mouse button bits

  switch (event.type) {

  case ButtonPress: {
    if (event.xbutton.button == Button1) mode |= 1;
    if (event.xbutton.button == Button2) mode |= 2;
    if (event.xbutton.button == Button3) mode |= 4;
    mx = event.xbutton.x;
    my = event.xbutton.y;
  }
  return;

  case ButtonRelease: {
    if (event.xbutton.button == Button1) mode &= (~1);
    if (event.xbutton.button == Button2) mode &= (~2);
    if (event.xbutton.button == Button3) mode &= (~4);
    mx = event.xbutton.x;
    my = event.xbutton.x;
  }
  return;

  case MotionNotify: {
    if (event.xmotion.is_hint) {
      Window root,child;
      unsigned int mask;
      XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
		     &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
		     &mask);
    }
    dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
    mx = event.xmotion.x;
    my = event.xmotion.y;
  }
  return;

  case KeyPress: {
    KeySym key;
    XLookupString (&event.xkey,NULL,0,&key,0);
    if ( (event.xkey.state & (ShiftMask | ControlMask)) == 0) {
      if (key >= ' ' && key <= 126) fn->command (key);
    }
    else if (event.xkey.state & ControlMask) {
      switch (key) {
      case 't': case 'T':
	dsSetTextures (dsGetTextures() ^ 1);
	break;
      case 's': case 'S':
	dsSetShadows (dsGetShadows() ^ 1);
	break;
      case 'x': case 'X':
	run = 0;
	break;
      case 'p': case 'P':
	pause ^= 1;
	singlestep = 0;
	break;
      case 'o': case 'O':
	if (pause) singlestep = 1;
	break;
      case 'v': case 'V': {
	float xyz[3],hpr[3];
	dsGetViewpoint (xyz,hpr);
	printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
		xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
	break;
      }
      case 'w': case 'W':
	writeframes ^= 1;
	if (writeframes) printf ("Now writing frames to PPM files\n");
	break;
      }
    }
    last_key_pressed = key;		// a kludgy place to put this...
  }
  return;

  case KeyRelease: {
    // hmmmm...
  }
  return;

  case ClientMessage:
    if (event.xclient.message_type == wm_protocols_atom &&
	event.xclient.format == 32 &&
	Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
      run = 0;
      return;
    }
    return;

  case ConfigureNotify:
    width = event.xconfigure.width;
    height = event.xconfigure.height;
    return;
  }
}

// return the index of the highest bit
static int getHighBitIndex (unsigned int x)
{
  int i = 0;
  while (x) {
    i++;
    x >>= 1;
  }
  return i-1;
}

// shift x left by i, where i can be positive or negative
#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))

static void captureFrame (int num)
{
  fprintf (stderr,"capturing frame %04d\n",num);

  char s[100];
  sprintf (s,"frame/frame%04d.ppm",num);
  FILE *f = fopen (s,"wb");
  if (!f) dsError ("can't open \"%s\" for writing",s);
  fprintf (f,"P6\n%d %d\n255\n",width,height);
  XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);

  int rshift = 7 - getHighBitIndex (image->red_mask);
  int gshift = 7 - getHighBitIndex (image->green_mask);
  int bshift = 7 - getHighBitIndex (image->blue_mask);

  for (int y=0; y<height; y++) {
    for (int x=0; x<width; x++) {
      unsigned long pixel = XGetPixel (image,x,y);
      unsigned char b[3];
      b[0] = SHIFTL(pixel & image->red_mask,rshift);
      b[1] = SHIFTL(pixel & image->green_mask,gshift);
      b[2] = SHIFTL(pixel & image->blue_mask,bshift);
      fwrite (b,3,1,f);
    }
  }
  fclose (f);
  XDestroyImage (image);
}

void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
			int initial_pause)
{
  pause = initial_pause;
  createMainWindow (window_width, window_height);
  glXMakeCurrent (display,win,glx_context);

  dsStartGraphics (window_width,window_height,fn);
  if (fn->start) fn->start();

  fprintf (stderr,
	   "\n"
	   "Simulation test environment v%d.%02d\n"
	   "   Ctrl-P : pause / unpause.\n"
	   "   Ctrl-O : single step when paused.\n"
	   "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
	   "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
	   "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
	   "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
	   "   Ctrl-X : exit.\n"
	   "\n",DS_VERSION >> 8,DS_VERSION & 0xff);

  int frame = 1;
  run = 1;
  while (run) {
    // read in and process all pending events for the main window
    XEvent event;
    while (run && XPending (display)) {
      XNextEvent (display,&event);
      handleEvent (event,fn);
    }

    dsDrawFrame (width,height,fn,pause && !singlestep);
    singlestep = 0;

    glFlush();
    glXSwapBuffers (display,win);
    XSync (display,0);

    // capture frames if necessary
    printf ("%d %d\n",pause,writeframes);
    if (pause==0 && writeframes) {
      captureFrame (frame);
      frame++;
    }
  };

  if (fn->stop) fn->stop();
  dsStopGraphics();

  destroyMainWindow();
}
<commit_msg>remove printf.<commit_after>// main window and event handling for X11

#include <stdio.h>
#include <stdarg.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <GL/glx.h>

#include "drawstuff/drawstuff.h"
#include "drawstuff/version.h"
#include "internal.h"

//***************************************************************************
// error handling for unix

static void printMessage (char *msg1, char *msg2, va_list ap)
{
  fflush (stderr);
  fflush (stdout);
  fprintf (stderr,"\n%s: ",msg1);
  vfprintf (stderr,msg2,ap);
  fprintf (stderr,"\n");
  fflush (stderr);
}

extern "C" void dsError (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("Error",msg,ap);
  exit (1);
}

extern "C" void dsDebug (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  printMessage ("INTERNAL ERROR",msg,ap);
  // *((char *)0) = 0;	 ... commit SEGVicide ?
  abort();
}

extern "C" void dsPrint (char *msg, ...)
{
  va_list ap;
  va_start (ap,msg);
  vprintf (msg,ap);
}

//***************************************************************************
// openGL window

// X11 display info
static Display *display=0;
static int screen=0;
static XVisualInfo *visual=0;		// best visual for openGL
static Colormap colormap=0;		// window's colormap
static Atom wm_protocols_atom = 0;
static Atom wm_delete_window_atom = 0;

// window and openGL
static Window win=0;			// X11 window, 0 if not initialized
static int width=0,height=0;		// window size
static GLXContext glx_context=0;	// openGL rendering context
static int last_key_pressed=0;		// last key pressed in the window
static int run=1;			// 1 if simulation running
static int pause=0;			// 1 if in `pause' mode
static int singlestep=0;		// 1 if single step key pressed
static int writeframes=0;		// 1 if frame files to be written

static void createMainWindow (int _width, int _height)
{
  // create X11 display connection
  display = XOpenDisplay (0);
  if (!display) dsError (0,"can not open X11 display");
  screen = DefaultScreen(display);

  // get GL visual
  static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
			     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
			     GLX_BLUE_SIZE,4, None};
  visual = glXChooseVisual (display,screen,attribList);
  if (!visual) dsError ("no good X11 visual found for OpenGL");

  // create colormap
  colormap = XCreateColormap (display,RootWindow(display,screen),
			      visual->visual,AllocNone);

  // initialize variables
  win = 0;
  width = _width;
  height = _height;
  glx_context = 0;
  last_key_pressed = 0;

  if (width < 1 || height < 1) dsDebug (0,"bad window width or height");

  // create the window
  XSetWindowAttributes attributes;
  attributes.background_pixel = BlackPixel(display,screen);
  attributes.colormap = colormap;
  attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
    KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
    StructureNotifyMask;
  win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
		       0,visual->depth, InputOutput,visual->visual,
		       CWBackPixel | CWColormap | CWEventMask,&attributes);

  // associate a GLX context with the window
  glx_context = glXCreateContext (display,visual,0,GL_TRUE);
  if (!glx_context) dsError ("can't make an OpenGL context");

  // set the window title
  XTextProperty window_name;
  window_name.value = (unsigned char *) "Simulation";
  window_name.encoding = XA_STRING;
  window_name.format = 8;
  window_name.nitems = strlen((char *) window_name.value);
  XSetWMName (display,win,&window_name);

  // participate in the window manager 'delete yourself' protocol
  wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
  wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
  if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
    dsError ("XSetWMProtocols() call failed");

  // pop up the window
  XMapWindow (display,win);
  XSync (display,win);
}

static void destroyMainWindow()
{
  glXDestroyContext (display,glx_context);
  XDestroyWindow (display,win);
  XSync (display,0);
  display = 0;
  win = 0;
  glx_context = 0;
}

static void handleEvent (XEvent &event, dsFunctions *fn)
{
  static int mx=0,my=0; 	// mouse position
  static int mode = 0;		// mouse button bits

  switch (event.type) {

  case ButtonPress: {
    if (event.xbutton.button == Button1) mode |= 1;
    if (event.xbutton.button == Button2) mode |= 2;
    if (event.xbutton.button == Button3) mode |= 4;
    mx = event.xbutton.x;
    my = event.xbutton.y;
  }
  return;

  case ButtonRelease: {
    if (event.xbutton.button == Button1) mode &= (~1);
    if (event.xbutton.button == Button2) mode &= (~2);
    if (event.xbutton.button == Button3) mode &= (~4);
    mx = event.xbutton.x;
    my = event.xbutton.x;
  }
  return;

  case MotionNotify: {
    if (event.xmotion.is_hint) {
      Window root,child;
      unsigned int mask;
      XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
		     &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
		     &mask);
    }
    dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
    mx = event.xmotion.x;
    my = event.xmotion.y;
  }
  return;

  case KeyPress: {
    KeySym key;
    XLookupString (&event.xkey,NULL,0,&key,0);
    if ( (event.xkey.state & (ShiftMask | ControlMask)) == 0) {
      if (key >= ' ' && key <= 126) fn->command (key);
    }
    else if (event.xkey.state & ControlMask) {
      switch (key) {
      case 't': case 'T':
	dsSetTextures (dsGetTextures() ^ 1);
	break;
      case 's': case 'S':
	dsSetShadows (dsGetShadows() ^ 1);
	break;
      case 'x': case 'X':
	run = 0;
	break;
      case 'p': case 'P':
	pause ^= 1;
	singlestep = 0;
	break;
      case 'o': case 'O':
	if (pause) singlestep = 1;
	break;
      case 'v': case 'V': {
	float xyz[3],hpr[3];
	dsGetViewpoint (xyz,hpr);
	printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
		xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
	break;
      }
      case 'w': case 'W':
	writeframes ^= 1;
	if (writeframes) printf ("Now writing frames to PPM files\n");
	break;
      }
    }
    last_key_pressed = key;		// a kludgy place to put this...
  }
  return;

  case KeyRelease: {
    // hmmmm...
  }
  return;

  case ClientMessage:
    if (event.xclient.message_type == wm_protocols_atom &&
	event.xclient.format == 32 &&
	Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
      run = 0;
      return;
    }
    return;

  case ConfigureNotify:
    width = event.xconfigure.width;
    height = event.xconfigure.height;
    return;
  }
}

// return the index of the highest bit
static int getHighBitIndex (unsigned int x)
{
  int i = 0;
  while (x) {
    i++;
    x >>= 1;
  }
  return i-1;
}

// shift x left by i, where i can be positive or negative
#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))

static void captureFrame (int num)
{
  fprintf (stderr,"capturing frame %04d\n",num);

  char s[100];
  sprintf (s,"frame/frame%04d.ppm",num);
  FILE *f = fopen (s,"wb");
  if (!f) dsError ("can't open \"%s\" for writing",s);
  fprintf (f,"P6\n%d %d\n255\n",width,height);
  XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);

  int rshift = 7 - getHighBitIndex (image->red_mask);
  int gshift = 7 - getHighBitIndex (image->green_mask);
  int bshift = 7 - getHighBitIndex (image->blue_mask);

  for (int y=0; y<height; y++) {
    for (int x=0; x<width; x++) {
      unsigned long pixel = XGetPixel (image,x,y);
      unsigned char b[3];
      b[0] = SHIFTL(pixel & image->red_mask,rshift);
      b[1] = SHIFTL(pixel & image->green_mask,gshift);
      b[2] = SHIFTL(pixel & image->blue_mask,bshift);
      fwrite (b,3,1,f);
    }
  }
  fclose (f);
  XDestroyImage (image);
}

void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
			int initial_pause)
{
  pause = initial_pause;
  createMainWindow (window_width, window_height);
  glXMakeCurrent (display,win,glx_context);

  dsStartGraphics (window_width,window_height,fn);
  if (fn->start) fn->start();

  fprintf (stderr,
	   "\n"
	   "Simulation test environment v%d.%02d\n"
	   "   Ctrl-P : pause / unpause.\n"
	   "   Ctrl-O : single step when paused.\n"
	   "   Ctrl-T : toggle textures (or say `-notex' on command line).\n"
	   "   Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n"
	   "   Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n"
	   "   Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n"
	   "   Ctrl-X : exit.\n"
	   "\n",DS_VERSION >> 8,DS_VERSION & 0xff);

  int frame = 1;
  run = 1;
  while (run) {
    // read in and process all pending events for the main window
    XEvent event;
    while (run && XPending (display)) {
      XNextEvent (display,&event);
      handleEvent (event,fn);
    }

    dsDrawFrame (width,height,fn,pause && !singlestep);
    singlestep = 0;

    glFlush();
    glXSwapBuffers (display,win);
    XSync (display,0);

    // capture frames if necessary
    if (pause==0 && writeframes) {
      captureFrame (frame);
      frame++;
    }
  };

  if (fn->stop) fn->stop();
  dsStopGraphics();

  destroyMainWindow();
}
<|endoftext|>


<commit_before>#include <PCH.h>
#include <Cores/UI/UICore.h>

#include <AppCore/Overlay.h>
#include <Engine/Engine.h>
#include <UI/d3d11/GPUDriverD3D11.h>
#include <UI/d3d11/GPUContextD3D11.h>
#include <UI/FileSystemBasic.h>
#include <UI/FileLogger.h>
#include <UI/FontLoaderWin.h>
#include <UI/UIWindow.h>
#include <Ultralight/platform/Platform.h>
#include <Ultralight/platform/Config.h>
#include <Ultralight/Renderer.h>

#if ME_EDITOR

#include <Cores/EditorCore.h>
#include <EditorApp.h>
#include <Havana.h>

#endif

UICore::UICore(IWindow* window, Moonlight::Renderer* renderer)
	: Base(ComponentFilter().Requires<BasicUIView>())
{
	SetIsSerializable(false);

	m_renderer = renderer;
	m_window = AdoptRef(*new UIWindow(window, GetOverlayManager()));

	std::string fileSystemRoot = Path("").Directory;
	m_fs.reset(new ultralight::FileSystemBasic(fileSystemRoot.c_str()));

	ultralight::Config config;
	config.device_scale = 1.0f;
	config.enable_images = true;
	config.face_winding = ultralight::FaceWinding::kFaceWinding_Clockwise;
	config.force_repaint = true;
	config.font_family_standard = "Arial";
	// ??????
	config.resource_path = "M:\\Projects\\C++\\stack\\Engine\\Modules\\Havana\\..\\..\\..\\Build\\Debug Editor";
	//config_.cache_path = ultralight::String16(std::string(fileSystemRoot.Directory + "ultralight.log").c_str());

	m_context.reset(new ultralight::GPUContextD3D11());
	if (!m_context->Initialize(m_window->width(), m_window->height(), m_window->scale(), m_window->is_fullscreen(), true, false, 1))
	{
		YIKES("Failed to initialize ultralight context");
	}

	m_driver.reset(new ultralight::GPUDriverD3D11(m_context.get(), &m_renderer->GetDevice()));
	m_logger.reset(new ultralight::FileLogger(ultralight::String(std::string(fileSystemRoot + "Ultralight.log").c_str())));
	m_fontLoader.reset(new ultralight::FontLoaderWin());

	ultralight::Platform& platform = ultralight::Platform::instance();
	platform.set_config(config);
	platform.set_file_system(m_fs.get());
	platform.set_font_loader(m_fontLoader.get());
	platform.set_gpu_driver(m_driver.get());
	platform.set_logger(m_logger.get());

	m_uiRenderer = ultralight::Renderer::Create();
}

UICore::~UICore()
{
	CLog::Log(CLog::LogType::Debug, "UICore Destroyed...");
}

void UICore::Init()
{
	CLog::Log(CLog::LogType::Debug, "UICore Initialized...");
}

void UICore::OnEntityAdded(Entity& NewEntity)
{
	BasicUIView& view = NewEntity.GetComponent<BasicUIView>();

	InitUIView(view);
}

void UICore::OnEntityRemoved(Entity& InEntity)
{
	BasicUIView& view = InEntity.GetComponent<BasicUIView>();

	GetOverlayManager()->Remove(m_overlays[view.Index].get());
	m_overlays.erase(m_overlays.begin() + view.Index);
}

void UICore::OnStop()
{
	for (auto overlay : m_overlays)
	{
		GetOverlayManager()->Remove(overlay.get());
	}
	m_overlays.clear();
}

void UICore::Update(float dt)
{
	auto& entities = GetEntities();
	for (auto& InEntity : entities)
	{
		BasicUIView& view = InEntity.GetComponent<BasicUIView>();
		if (!view.IsInitialized)
		{
			InitUIView(view);
		}
	}

	ultralight::MouseEvent mouseEvent;
	mouseEvent.type = ultralight::MouseEvent::kType_MouseMoved;

	Vector2 mousePosition = GetEngine().GetInput().GetMousePosition();

#if ME_EDITOR
	if (!static_cast<EditorApp*>(GetEngine().GetGame())->IsGameRunning())
	{
		return;
	}

	Havana* editor = static_cast<EditorCore*>(GetEngine().GetWorld().lock()->GetCore(EditorCore::GetTypeId()))->GetEditor();

	Vector2 windowPosition = GetEngine().GetWindow()->GetPosition();

	mouseEvent.x = (windowPosition.X() + mousePosition.X()) - editor->GameViewRenderLocation.X();
	mouseEvent.y = (windowPosition.Y() + mousePosition.Y()) - editor->GameViewRenderLocation.Y();

	if (mousePosition.IsZero())
	{
		return;
	}
#else
	mouseEvent.x = mousePosition.X();
	mouseEvent.y = mousePosition.Y();
#endif

	static bool hasPressed = false;
	if (GetEngine().GetInput().GetMouseState().leftButton && !hasPressed)
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_Left;
		mouseEvent.type = ultralight::MouseEvent::kType_MouseDown;
		hasPressed = true;
	}
	else if (!GetEngine().GetInput().GetMouseState().leftButton && hasPressed)
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_Left;
		mouseEvent.type = ultralight::MouseEvent::kType_MouseUp;
		hasPressed = false;
	}
	else
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_None;
	}

#if ME_EDITOR
	if (m_renderer->GetViewportMode() == ViewportMode::Game)
#endif
	{
		for (auto& view : m_overlays)
		{
			view->view()->FireMouseEvent(mouseEvent);
		}
	}

	// Update internal logic (timers, event callbacks, etc.)
	m_uiRenderer->Update();
}

void UICore::Render()
{
	OPTICK_EVENT("UI Render", Optick::Category::Rendering);
	m_driver->BeginSynchronize();

	// Render all active views to command lists and dispatch calls to GPUDriver
	m_uiRenderer->Render();

	m_driver->EndSynchronize();

	// Draw any pending commands to screen
	if (m_driver->HasCommandsPending())
	{
		m_context->BeginDrawing();
		m_driver->DrawCommandList();

		// Perform any additional drawing (Overlays) here...
		//DrawOverlays();

		// Flip buffers here.
		if (m_window)
		{
			Draw();
		}
		m_context->EndDrawing();
	}
}

void UICore::OnResize(const Vector2& NewSize)
{
	if (m_context)
	{
		m_context->Resize((int)NewSize.X(), (int)NewSize.Y());
		for (auto overlay : overlays_)
		{
			overlay->Resize((int)NewSize.X(), (int)NewSize.Y());
		}
	}
}

void UICore::InitUIView(BasicUIView& view)
{
	ultralight::Ref<ultralight::View> newView = m_uiRenderer->CreateView(Camera::CurrentCamera->OutputSize.X(), Camera::CurrentCamera->OutputSize.Y(), true, nullptr);

	ultralight::RefPtr<ultralight::Overlay> overlay = ultralight::Overlay::Create(*m_window.get(), newView, 0, 0);
	overlay->view()->set_load_listener(&view);

	//overlay->view()->LoadHTML(view.SourceFile.Read().c_str());
	ultralight::String str = "file:///" + ultralight::String(view.FilePath.LocalPath.c_str());
	overlay->view()->LoadURL(str);

	m_overlays.push_back(overlay);
	GetOverlayManager()->Add(overlay.get());

	view.IsInitialized = true;
	view.Index = m_overlays.size() - 1;
}

ultralight::OverlayManager* UICore::GetOverlayManager()
{
	return this;
}<commit_msg>💋 Fixing the build<commit_after>#include <PCH.h>
#include <Cores/UI/UICore.h>

#include <AppCore/Overlay.h>
#include <Components/Camera.h>
#include <Engine/Engine.h>
#include <UI/d3d11/GPUDriverD3D11.h>
#include <UI/d3d11/GPUContextD3D11.h>
#include <UI/FileSystemBasic.h>
#include <UI/FileLogger.h>
#include <UI/FontLoaderWin.h>
#include <UI/UIWindow.h>
#include <Ultralight/platform/Platform.h>
#include <Ultralight/platform/Config.h>
#include <Ultralight/Renderer.h>

#if ME_EDITOR

#include <Cores/EditorCore.h>
#include <EditorApp.h>
#include <Havana.h>

#endif

UICore::UICore(IWindow* window, Moonlight::Renderer* renderer)
	: Base(ComponentFilter().Requires<BasicUIView>())
{
	SetIsSerializable(false);

	m_renderer = renderer;
	m_window = AdoptRef(*new UIWindow(window, GetOverlayManager()));

	std::string fileSystemRoot = Path("").Directory;
	m_fs.reset(new ultralight::FileSystemBasic(fileSystemRoot.c_str()));

	ultralight::Config config;
	config.device_scale = 1.0f;
	config.enable_images = true;
	config.face_winding = ultralight::FaceWinding::kFaceWinding_Clockwise;
	config.force_repaint = true;
	config.font_family_standard = "Arial";
	// ??????
	config.resource_path = "M:\\Projects\\C++\\stack\\Engine\\Modules\\Havana\\..\\..\\..\\Build\\Debug Editor";
	//config_.cache_path = ultralight::String16(std::string(fileSystemRoot.Directory + "ultralight.log").c_str());

	m_context.reset(new ultralight::GPUContextD3D11());
	if (!m_context->Initialize(m_window->width(), m_window->height(), m_window->scale(), m_window->is_fullscreen(), true, false, 1))
	{
		YIKES("Failed to initialize ultralight context");
	}

	m_driver.reset(new ultralight::GPUDriverD3D11(m_context.get(), &m_renderer->GetDevice()));
	m_logger.reset(new ultralight::FileLogger(ultralight::String(std::string(fileSystemRoot + "Ultralight.log").c_str())));
	m_fontLoader.reset(new ultralight::FontLoaderWin());

	ultralight::Platform& platform = ultralight::Platform::instance();
	platform.set_config(config);
	platform.set_file_system(m_fs.get());
	platform.set_font_loader(m_fontLoader.get());
	platform.set_gpu_driver(m_driver.get());
	platform.set_logger(m_logger.get());

	m_uiRenderer = ultralight::Renderer::Create();
}

UICore::~UICore()
{
	CLog::Log(CLog::LogType::Debug, "UICore Destroyed...");
}

void UICore::Init()
{
	CLog::Log(CLog::LogType::Debug, "UICore Initialized...");
}

void UICore::OnEntityAdded(Entity& NewEntity)
{
	BasicUIView& view = NewEntity.GetComponent<BasicUIView>();

	InitUIView(view);
}

void UICore::OnEntityRemoved(Entity& InEntity)
{
	BasicUIView& view = InEntity.GetComponent<BasicUIView>();

	GetOverlayManager()->Remove(m_overlays[view.Index].get());
	m_overlays.erase(m_overlays.begin() + view.Index);
}

void UICore::OnStop()
{
	for (auto overlay : m_overlays)
	{
		GetOverlayManager()->Remove(overlay.get());
	}
	m_overlays.clear();
}

void UICore::Update(float dt)
{
	auto& entities = GetEntities();
	for (auto& InEntity : entities)
	{
		BasicUIView& view = InEntity.GetComponent<BasicUIView>();
		if (!view.IsInitialized)
		{
			InitUIView(view);
		}
	}

	ultralight::MouseEvent mouseEvent;
	mouseEvent.type = ultralight::MouseEvent::kType_MouseMoved;

	Vector2 mousePosition = GetEngine().GetInput().GetMousePosition();

#if ME_EDITOR
	if (!static_cast<EditorApp*>(GetEngine().GetGame())->IsGameRunning())
	{
		return;
	}

	Havana* editor = static_cast<EditorCore*>(GetEngine().GetWorld().lock()->GetCore(EditorCore::GetTypeId()))->GetEditor();

	Vector2 windowPosition = GetEngine().GetWindow()->GetPosition();

	mouseEvent.x = (windowPosition.X() + mousePosition.X()) - editor->GameViewRenderLocation.X();
	mouseEvent.y = (windowPosition.Y() + mousePosition.Y()) - editor->GameViewRenderLocation.Y();

	if (mousePosition.IsZero())
	{
		return;
	}
#else
	mouseEvent.x = mousePosition.X();
	mouseEvent.y = mousePosition.Y();
#endif

	static bool hasPressed = false;
	if (GetEngine().GetInput().GetMouseState().leftButton && !hasPressed)
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_Left;
		mouseEvent.type = ultralight::MouseEvent::kType_MouseDown;
		hasPressed = true;
	}
	else if (!GetEngine().GetInput().GetMouseState().leftButton && hasPressed)
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_Left;
		mouseEvent.type = ultralight::MouseEvent::kType_MouseUp;
		hasPressed = false;
	}
	else
	{
		mouseEvent.button = ultralight::MouseEvent::Button::kButton_None;
	}

#if ME_EDITOR
	if (m_renderer->GetViewportMode() == ViewportMode::Game)
#endif
	{
		for (auto& view : m_overlays)
		{
			view->view()->FireMouseEvent(mouseEvent);
		}
	}

	// Update internal logic (timers, event callbacks, etc.)
	m_uiRenderer->Update();
}

void UICore::Render()
{
	OPTICK_EVENT("UI Render", Optick::Category::Rendering);
	m_driver->BeginSynchronize();

	// Render all active views to command lists and dispatch calls to GPUDriver
	m_uiRenderer->Render();

	m_driver->EndSynchronize();

	// Draw any pending commands to screen
	if (m_driver->HasCommandsPending())
	{
		m_context->BeginDrawing();
		m_driver->DrawCommandList();

		// Perform any additional drawing (Overlays) here...
		//DrawOverlays();

		// Flip buffers here.
		if (m_window)
		{
			Draw();
		}
		m_context->EndDrawing();
	}
}

void UICore::OnResize(const Vector2& NewSize)
{
	if (m_context)
	{
		m_context->Resize((int)NewSize.X(), (int)NewSize.Y());
		for (auto overlay : overlays_)
		{
			overlay->Resize((int)NewSize.X(), (int)NewSize.Y());
		}
	}
}

void UICore::InitUIView(BasicUIView& view)
{
	ultralight::Ref<ultralight::View> newView = m_uiRenderer->CreateView(Camera::CurrentCamera->OutputSize.X(), Camera::CurrentCamera->OutputSize.Y(), true, nullptr);

	ultralight::RefPtr<ultralight::Overlay> overlay = ultralight::Overlay::Create(*m_window.get(), newView, 0, 0);
	overlay->view()->set_load_listener(&view);

	//overlay->view()->LoadHTML(view.SourceFile.Read().c_str());
	ultralight::String str = "file:///" + ultralight::String(view.FilePath.LocalPath.c_str());
	overlay->view()->LoadURL(str);

	m_overlays.push_back(overlay);
	GetOverlayManager()->Add(overlay.get());

	view.IsInitialized = true;
	view.Index = m_overlays.size() - 1;
}

ultralight::OverlayManager* UICore::GetOverlayManager()
{
	return this;
}<|endoftext|>


<commit_before>/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic framework code for a JUCE plugin processor.

  ==============================================================================
*/

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
VispiControllerVstAudioProcessor::VispiControllerVstAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
     : AudioProcessor (BusesProperties()
                     #if ! JucePlugin_IsMidiEffect
                      #if ! JucePlugin_IsSynth
                       .withInput  ("Input",  AudioChannelSet::stereo(), true)
                      #endif
                       .withOutput ("Output", AudioChannelSet::stereo(), true)
                     #endif
                       ),
    messenger("vispi", 12345),
    playlistFilename("~/live_videos.xspf"),
    videoSelectionCC(99)
#endif
{
    String playlistStatus = loadPlaylist(playlistFilename) ? "Playlist ok" : "Playlist fail";
    std::cout << playlistStatus << std::endl;
}

VispiControllerVstAudioProcessor::~VispiControllerVstAudioProcessor()
{
}

//==============================================================================
const String VispiControllerVstAudioProcessor::getName() const
{
    return JucePlugin_Name;
}

bool VispiControllerVstAudioProcessor::acceptsMidi() const
{
   #if JucePlugin_WantsMidiInput
    return true;
   #else
    return false;
   #endif
}

bool VispiControllerVstAudioProcessor::producesMidi() const
{
   #if JucePlugin_ProducesMidiOutput
    return true;
   #else
    return false;
   #endif
}

bool VispiControllerVstAudioProcessor::isMidiEffect() const
{
    #if JucePlugin_IsMidiEffect
     return true;
    #else
     return false;
    #endif
}

double VispiControllerVstAudioProcessor::getTailLengthSeconds() const
{
    return 0.0;
}

int VispiControllerVstAudioProcessor::getNumPrograms()
{
    return 1;   // NB: some hosts don't cope very well if you tell them there are 0 programs,
                // so this should be at least 1, even if you're not really implementing programs.
}

int VispiControllerVstAudioProcessor::getCurrentProgram()
{
    return 0;
}

void VispiControllerVstAudioProcessor::setCurrentProgram (int index)
{
}

const String VispiControllerVstAudioProcessor::getProgramName (int index)
{
    return String();
}

void VispiControllerVstAudioProcessor::changeProgramName (int index, const String& newName)
{
}

//==============================================================================
void VispiControllerVstAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // Use this method as the place to do any pre-playback
    // initialisation that you need..
}

void VispiControllerVstAudioProcessor::releaseResources()
{
    // When playback stops, you can use this as an opportunity to free up any
    // spare memory, etc.
}

#ifndef JucePlugin_PreferredChannelConfigurations
bool VispiControllerVstAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
  #if JucePlugin_IsMidiEffect
    ignoreUnused (layouts);
    return true;
  #else
    // This is the place where you check if the layout is supported.
    // In this template code we only support mono or stereo.
    if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
     && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
        return false;

    // This checks if the input layout matches the output layout
   #if ! JucePlugin_IsSynth
    if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
        return false;
   #endif

    return true;
  #endif
}
#endif

void VispiControllerVstAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    /*
    const int totalNumInputChannels  = getTotalNumInputChannels();
    const int totalNumOutputChannels = getTotalNumOutputChannels();

    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // This is here to avoid people getting screaming feedback
    // when they first compile a plugin, but obviously you don't need to keep
    // this code if your algorithm always overwrites all the output channels.
    for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        float* channelData = buffer.getWritePointer (channel);

        // ..do something to the data...
    }
    */
    buffer.clear();

    MidiBuffer processedMidi;
    int time;
    MidiMessage m;

    for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
    {
        if (m.isController() && m.getControllerNumber() == videoSelectionCC)
        {
            //videoSelection = m.getControllerValue(); // % playlist length...
            processVideoSelection(m.getControllerValue());
        } else if(m.isNoteOn()) {
            processVideoSelection(m.getNoteNumber());
        }

        processedMidi.addEvent (m, time);
    }

    midiMessages.swapWith (processedMidi);
}

void VispiControllerVstAudioProcessor::processVideoSelection(const int n) {
    messenger.pushVideoFile("a real video file name " + String(n));
}

bool VispiControllerVstAudioProcessor::loadPlaylist(const String& path) {

    File file(path);
    if(!file.exists()) return false;
    playlistData = XmlDocument::parse(file);
    if(playlistData == nullptr) return false;

    ScopedLock fileNamesLock(fileNamesMutex);
    fileNames.clear();
    // now populate our fileNames vector...

    XmlElement * tracklist = playlistData->getChildByName("trackList");
    if(tracklist == nullptr) return false;
    XmlElement * track = tracklist->getChildByName("track");

    while(track != nullptr)
    {

        XmlElement * location = track->getChildByName("location");
        if(location != nullptr) {
            fileNames.push_back(xspfUriToString(location->getAllSubText()));
        }

        track = track->getNextElementWithTagName("track");
    }

    return true;
}

const String VispiControllerVstAudioProcessor::xspfUriToString(const String& uri)
{
    return URL::removeEscapeChars(uri.fromLastOccurrenceOf("/", false, false));

}

/*
void loadData()
{
    demoData = XmlDocument::parse (BinaryData::demo_table_data_xml);

    dataList   = demoData->getChildByName ("DATA");
    columnList = demoData->getChildByName ("COLUMNS");

    numRows = dataList->getNumChildElements();
}
*/

//==============================================================================
bool VispiControllerVstAudioProcessor::hasEditor() const
{
    return true; // (change this to false if you choose to not supply an editor)
}

AudioProcessorEditor* VispiControllerVstAudioProcessor::createEditor()
{
    return new VispiControllerVstAudioProcessorEditor (*this);
}

//==============================================================================
void VispiControllerVstAudioProcessor::getStateInformation (MemoryBlock& destData)
{
    // You should use this method to store your parameters in the memory block.
    // You could do that either as raw data, or use the XML or ValueTree classes
    // as intermediaries to make it easy to save and load complex data.
}

void VispiControllerVstAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    // You should use this method to restore your parameters from this memory block,
    // whose contents will have been created by the getStateInformation() call.
}

//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new VispiControllerVstAudioProcessor();
}
<commit_msg>sends video file as necessary<commit_after>/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic framework code for a JUCE plugin processor.

  ==============================================================================
*/

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
VispiControllerVstAudioProcessor::VispiControllerVstAudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
     : AudioProcessor (BusesProperties()
                     #if ! JucePlugin_IsMidiEffect
                      #if ! JucePlugin_IsSynth
                       .withInput  ("Input",  AudioChannelSet::stereo(), true)
                      #endif
                       .withOutput ("Output", AudioChannelSet::stereo(), true)
                     #endif
                       ),
    messenger("vispi", 12345),
    playlistFilename("~/live_videos.xspf"),
    videoSelectionCC(99)
#endif
{
    String playlistStatus = loadPlaylist(playlistFilename) ? "Playlist ok" : "Playlist fail";
    std::cout << playlistStatus << std::endl;
}

VispiControllerVstAudioProcessor::~VispiControllerVstAudioProcessor()
{
}

//==============================================================================
const String VispiControllerVstAudioProcessor::getName() const
{
    return JucePlugin_Name;
}

bool VispiControllerVstAudioProcessor::acceptsMidi() const
{
   #if JucePlugin_WantsMidiInput
    return true;
   #else
    return false;
   #endif
}

bool VispiControllerVstAudioProcessor::producesMidi() const
{
   #if JucePlugin_ProducesMidiOutput
    return true;
   #else
    return false;
   #endif
}

bool VispiControllerVstAudioProcessor::isMidiEffect() const
{
    #if JucePlugin_IsMidiEffect
     return true;
    #else
     return false;
    #endif
}

double VispiControllerVstAudioProcessor::getTailLengthSeconds() const
{
    return 0.0;
}

int VispiControllerVstAudioProcessor::getNumPrograms()
{
    return 1;   // NB: some hosts don't cope very well if you tell them there are 0 programs,
                // so this should be at least 1, even if you're not really implementing programs.
}

int VispiControllerVstAudioProcessor::getCurrentProgram()
{
    return 0;
}

void VispiControllerVstAudioProcessor::setCurrentProgram (int index)
{
}

const String VispiControllerVstAudioProcessor::getProgramName (int index)
{
    return String();
}

void VispiControllerVstAudioProcessor::changeProgramName (int index, const String& newName)
{
}

//==============================================================================
void VispiControllerVstAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    // Use this method as the place to do any pre-playback
    // initialisation that you need..
}

void VispiControllerVstAudioProcessor::releaseResources()
{
    // When playback stops, you can use this as an opportunity to free up any
    // spare memory, etc.
}

#ifndef JucePlugin_PreferredChannelConfigurations
bool VispiControllerVstAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
  #if JucePlugin_IsMidiEffect
    ignoreUnused (layouts);
    return true;
  #else
    // This is the place where you check if the layout is supported.
    // In this template code we only support mono or stereo.
    if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
     && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
        return false;

    // This checks if the input layout matches the output layout
   #if ! JucePlugin_IsSynth
    if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
        return false;
   #endif

    return true;
  #endif
}
#endif

void VispiControllerVstAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
    /*
    const int totalNumInputChannels  = getTotalNumInputChannels();
    const int totalNumOutputChannels = getTotalNumOutputChannels();

    // In case we have more outputs than inputs, this code clears any output
    // channels that didn't contain input data, (because these aren't
    // guaranteed to be empty - they may contain garbage).
    // This is here to avoid people getting screaming feedback
    // when they first compile a plugin, but obviously you don't need to keep
    // this code if your algorithm always overwrites all the output channels.
    for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    // This is the place where you'd normally do the guts of your plugin's
    // audio processing...
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        float* channelData = buffer.getWritePointer (channel);

        // ..do something to the data...
    }
    */
    buffer.clear();

    MidiBuffer processedMidi;
    int time;
    MidiMessage m;

    for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);)
    {
        if (m.isController() && m.getControllerNumber() == videoSelectionCC)
        {
            //videoSelection = m.getControllerValue(); // % playlist length...
            processVideoSelection(m.getControllerValue());
        } else if(m.isNoteOn()) {
            processVideoSelection(m.getNoteNumber());
        }

        processedMidi.addEvent (m, time);
    }

    midiMessages.swapWith (processedMidi);
}

void VispiControllerVstAudioProcessor::processVideoSelection(const int n) {
    if(n<getNumFiles()) {
        messenger.pushVideoFile(getFileName(n));
    }
}

bool VispiControllerVstAudioProcessor::loadPlaylist(const String& path) {

    File file(path);
    if(!file.exists()) return false;
    playlistData = XmlDocument::parse(file);
    if(playlistData == nullptr) return false;

    ScopedLock fileNamesLock(fileNamesMutex);
    fileNames.clear();
    // now populate our fileNames vector...

    XmlElement * tracklist = playlistData->getChildByName("trackList");
    if(tracklist == nullptr) return false;
    XmlElement * track = tracklist->getChildByName("track");

    while(track != nullptr)
    {

        XmlElement * location = track->getChildByName("location");
        if(location != nullptr) {
            fileNames.push_back(xspfUriToString(location->getAllSubText()));
        }

        track = track->getNextElementWithTagName("track");
    }

    return true;
}

const String VispiControllerVstAudioProcessor::xspfUriToString(const String& uri)
{
    return URL::removeEscapeChars(uri.fromLastOccurrenceOf("/", false, false));

}

//==============================================================================
bool VispiControllerVstAudioProcessor::hasEditor() const
{
    return true; // (change this to false if you choose to not supply an editor)
}

AudioProcessorEditor* VispiControllerVstAudioProcessor::createEditor()
{
    return new VispiControllerVstAudioProcessorEditor (*this);
}

//==============================================================================
void VispiControllerVstAudioProcessor::getStateInformation (MemoryBlock& destData)
{
    // You should use this method to store your parameters in the memory block.
    // You could do that either as raw data, or use the XML or ValueTree classes
    // as intermediaries to make it easy to save and load complex data.
}

void VispiControllerVstAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    // You should use this method to restore your parameters from this memory block,
    // whose contents will have been created by the getStateInformation() call.
}

//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
    return new VispiControllerVstAudioProcessor();
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"

namespace webrtc {

namespace {
const CodecInst kOpusSettings = {105, "opus", 48000, 960, 1, 32000};
}  // namespace

class AudioEncoderOpusTest : public ::testing::Test {
 protected:
  void CreateCodec(int num_channels) {
    codec_inst_.channels = num_channels;
    encoder_.reset(new AudioEncoderOpus(codec_inst_));
    auto expected_app =
        num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio;
    EXPECT_EQ(expected_app, encoder_->application());
  }

  CodecInst codec_inst_ = kOpusSettings;
  rtc::scoped_ptr<AudioEncoderOpus> encoder_;
};

TEST_F(AudioEncoderOpusTest, DefaultApplicationModeMono) {
  CreateCodec(1);
}

TEST_F(AudioEncoderOpusTest, DefaultApplicationModeStereo) {
  CreateCodec(2);
}

TEST_F(AudioEncoderOpusTest, ChangeApplicationMode) {
  CreateCodec(2);
  EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}

TEST_F(AudioEncoderOpusTest, ResetWontChangeApplicationMode) {
  CreateCodec(2);

  // Trigger a reset.
  encoder_->Reset();
  // Verify that the mode is still kAudio.
  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());

  // Now change to kVoip.
  EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());

  // Trigger a reset again.
  encoder_->Reset();
  // Verify that the mode is still kVoip.
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}

TEST_F(AudioEncoderOpusTest, ToggleDtx) {
  CreateCodec(2);
  // Enable DTX
  EXPECT_TRUE(encoder_->SetDtx(true));
  // Verify that the mode is still kAudio.
  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
  // Turn off DTX.
  EXPECT_TRUE(encoder_->SetDtx(false));
}

TEST_F(AudioEncoderOpusTest, SetBitrate) {
  CreateCodec(1);
  // Constants are replicated from audio_encoder_opus.cc.
  const int kMinBitrateBps = 500;
  const int kMaxBitrateBps = 512000;
  // Set a too low bitrate.
  encoder_->SetTargetBitrate(kMinBitrateBps - 1);
  EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
  // Set a too high bitrate.
  encoder_->SetTargetBitrate(kMaxBitrateBps + 1);
  EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
  // Set the minimum rate.
  encoder_->SetTargetBitrate(kMinBitrateBps);
  EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
  // Set the maximum rate.
  encoder_->SetTargetBitrate(kMaxBitrateBps);
  EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
  // Set rates from 1000 up to 32000 bps.
  for (int rate = 1000; rate <= 32000; rate += 1000) {
    encoder_->SetTargetBitrate(rate);
    EXPECT_EQ(rate, encoder_->GetTargetBitrate());
  }
}

namespace {

// These constants correspond to those used in
// AudioEncoderOpus::SetProjectedPacketLossRate.
const double kPacketLossRate20 = 0.20;
const double kPacketLossRate10 = 0.10;
const double kPacketLossRate5 = 0.05;
const double kPacketLossRate1 = 0.01;
const double kLossRate20Margin = 0.02;
const double kLossRate10Margin = 0.01;
const double kLossRate5Margin = 0.01;

// Repeatedly sets packet loss rates in the range [from, to], increasing by
// 0.01 in each step. The function verifies that the actual loss rate is
// |expected_return|.
void TestSetPacketLossRate(AudioEncoderOpus* encoder,
                           double from,
                           double to,
                           double expected_return) {
  for (double loss = from; loss <= to;
       (to >= from) ? loss += 0.01 : loss -= 0.01) {
    encoder->SetProjectedPacketLossRate(loss);
    EXPECT_DOUBLE_EQ(expected_return, encoder->packet_loss_rate());
  }
}

}  // namespace

TEST_F(AudioEncoderOpusTest, PacketLossRateOptimized) {
  CreateCodec(1);

  // Note that the order of the following calls is critical.
  TestSetPacketLossRate(encoder_.get(), 0.0, 0.0, 0.0);
  TestSetPacketLossRate(encoder_.get(), kPacketLossRate1,
                        kPacketLossRate5 + kLossRate5Margin - 0.01,
                        kPacketLossRate1);
  TestSetPacketLossRate(encoder_.get(), kPacketLossRate5 + kLossRate5Margin,
                        kPacketLossRate10 + kLossRate10Margin - 0.01,
                        kPacketLossRate5);
  TestSetPacketLossRate(encoder_.get(), kPacketLossRate10 + kLossRate10Margin,
                        kPacketLossRate20 + kLossRate20Margin - 0.01,
                        kPacketLossRate10);
  TestSetPacketLossRate(encoder_.get(), kPacketLossRate20 + kLossRate20Margin,
                        1.0, kPacketLossRate20);
  TestSetPacketLossRate(encoder_.get(), kPacketLossRate20 + kLossRate20Margin,
                        kPacketLossRate20 - kLossRate20Margin,
                        kPacketLossRate20);
  TestSetPacketLossRate(
      encoder_.get(), kPacketLossRate20 - kLossRate20Margin - 0.01,
      kPacketLossRate10 - kLossRate10Margin, kPacketLossRate10);
  TestSetPacketLossRate(encoder_.get(),
                        kPacketLossRate10 - kLossRate10Margin - 0.01,
                        kPacketLossRate5 - kLossRate5Margin, kPacketLossRate5);
  TestSetPacketLossRate(encoder_.get(),
                        kPacketLossRate5 - kLossRate5Margin - 0.01,
                        kPacketLossRate1, kPacketLossRate1);
  TestSetPacketLossRate(encoder_.get(), 0.0, 0.0, 0.0);
}

}  // namespace webrtc
<commit_msg>AudioEncoderOpusTest.PacketLossRateOptimized: Fix bug and make prettier<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"

namespace webrtc {

namespace {
const CodecInst kOpusSettings = {105, "opus", 48000, 960, 1, 32000};
}  // namespace

class AudioEncoderOpusTest : public ::testing::Test {
 protected:
  void CreateCodec(int num_channels) {
    codec_inst_.channels = num_channels;
    encoder_.reset(new AudioEncoderOpus(codec_inst_));
    auto expected_app =
        num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio;
    EXPECT_EQ(expected_app, encoder_->application());
  }

  CodecInst codec_inst_ = kOpusSettings;
  rtc::scoped_ptr<AudioEncoderOpus> encoder_;
};

TEST_F(AudioEncoderOpusTest, DefaultApplicationModeMono) {
  CreateCodec(1);
}

TEST_F(AudioEncoderOpusTest, DefaultApplicationModeStereo) {
  CreateCodec(2);
}

TEST_F(AudioEncoderOpusTest, ChangeApplicationMode) {
  CreateCodec(2);
  EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}

TEST_F(AudioEncoderOpusTest, ResetWontChangeApplicationMode) {
  CreateCodec(2);

  // Trigger a reset.
  encoder_->Reset();
  // Verify that the mode is still kAudio.
  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());

  // Now change to kVoip.
  EXPECT_TRUE(encoder_->SetApplication(AudioEncoder::Application::kSpeech));
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());

  // Trigger a reset again.
  encoder_->Reset();
  // Verify that the mode is still kVoip.
  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
}

TEST_F(AudioEncoderOpusTest, ToggleDtx) {
  CreateCodec(2);
  // Enable DTX
  EXPECT_TRUE(encoder_->SetDtx(true));
  // Verify that the mode is still kAudio.
  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
  // Turn off DTX.
  EXPECT_TRUE(encoder_->SetDtx(false));
}

TEST_F(AudioEncoderOpusTest, SetBitrate) {
  CreateCodec(1);
  // Constants are replicated from audio_encoder_opus.cc.
  const int kMinBitrateBps = 500;
  const int kMaxBitrateBps = 512000;
  // Set a too low bitrate.
  encoder_->SetTargetBitrate(kMinBitrateBps - 1);
  EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
  // Set a too high bitrate.
  encoder_->SetTargetBitrate(kMaxBitrateBps + 1);
  EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
  // Set the minimum rate.
  encoder_->SetTargetBitrate(kMinBitrateBps);
  EXPECT_EQ(kMinBitrateBps, encoder_->GetTargetBitrate());
  // Set the maximum rate.
  encoder_->SetTargetBitrate(kMaxBitrateBps);
  EXPECT_EQ(kMaxBitrateBps, encoder_->GetTargetBitrate());
  // Set rates from 1000 up to 32000 bps.
  for (int rate = 1000; rate <= 32000; rate += 1000) {
    encoder_->SetTargetBitrate(rate);
    EXPECT_EQ(rate, encoder_->GetTargetBitrate());
  }
}

namespace {

// Returns a vector with the n evenly-spaced numbers a, a + (b - a)/(n - 1),
// ..., b.
std::vector<double> IntervalSteps(double a, double b, size_t n) {
  DCHECK_GT(n, 1u);
  const double step = (b - a) / (n - 1);
  std::vector<double> points;
  for (size_t i = 0; i < n; ++i)
    points.push_back(a + i * step);
  return points;
}

// Sets the packet loss rate to each number in the vector in turn, and verifies
// that the loss rate as reported by the encoder is |expected_return| for all
// of them.
void TestSetPacketLossRate(AudioEncoderOpus* encoder,
                           const std::vector<double>& losses,
                           double expected_return) {
  for (double loss : losses) {
    encoder->SetProjectedPacketLossRate(loss);
    EXPECT_DOUBLE_EQ(expected_return, encoder->packet_loss_rate());
  }
}

}  // namespace

TEST_F(AudioEncoderOpusTest, PacketLossRateOptimized) {
  CreateCodec(1);
  auto I = [](double a, double b) { return IntervalSteps(a, b, 10); };
  const double eps = 1e-15;

  // Note that the order of the following calls is critical.

  // clang-format off
  TestSetPacketLossRate(encoder_.get(), I(0.00      , 0.01 - eps), 0.00);
  TestSetPacketLossRate(encoder_.get(), I(0.01 + eps, 0.06 - eps), 0.01);
  TestSetPacketLossRate(encoder_.get(), I(0.06 + eps, 0.11 - eps), 0.05);
  TestSetPacketLossRate(encoder_.get(), I(0.11 + eps, 0.22 - eps), 0.10);
  TestSetPacketLossRate(encoder_.get(), I(0.22 + eps, 1.00      ), 0.20);

  TestSetPacketLossRate(encoder_.get(), I(1.00      , 0.18 + eps), 0.20);
  TestSetPacketLossRate(encoder_.get(), I(0.18 - eps, 0.09 + eps), 0.10);
  TestSetPacketLossRate(encoder_.get(), I(0.09 - eps, 0.04 + eps), 0.05);
  TestSetPacketLossRate(encoder_.get(), I(0.04 - eps, 0.01 + eps), 0.01);
  TestSetPacketLossRate(encoder_.get(), I(0.01 - eps, 0.00      ), 0.00);
  // clang-format on
}

}  // namespace webrtc
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2015                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_DETAIL_SPLIT_JOIN_HPP
#define CAF_DETAIL_SPLIT_JOIN_HPP

#include <vector>

#include "caf/actor.hpp"
#include "caf/locks.hpp"
#include "caf/spawn.hpp"
#include "caf/event_based_actor.hpp"

#include "caf/detail/shared_spinlock.hpp"

namespace caf {
namespace detail {

using actor_msg_vec = std::vector<std::pair<actor, message>>;

template <class T, class Split, class Join>
class split_join_collector : public event_based_actor {
public:
  split_join_collector(T init_value, Split s, Join j, actor_msg_vec xs)
      : workset_(std::move(xs)),
        awaited_results_(workset_.size()),
        join_(std::move(j)),
        split_(std::move(s)),
        value_(std::move(init_value)) {
    // nop
  }

  behavior make_behavior() override {
    return {
      others >> [=] {
        rp_ = make_response_promise();
        split_(workset_, current_message());
        // first message is the forwarded request
        for (auto& x : workset_) {
          sync_send(x.first, std::move(x.second)).then(
            others >> [=] {
              join_(value_, this->current_message());
              if (--awaited_results_ == 0) {
                rp_.deliver(make_message(value_));
                quit();
              }
            }
          );
        }
        // no longer needed
        workset_.clear();
      }
    };
  }

private:
  actor_msg_vec workset_;
  size_t awaited_results_;
  Join join_;
  Split split_;
  T value_;
  response_promise rp_;
};

struct nop_split {
  inline void operator()(actor_msg_vec& xs, message& y) const {
    for (auto& x : xs) {
      x.second = y;
    }
  }
};

template <class T, class Split, class Join>
class split_join {
public:
  split_join(T init_value, Split s, Join j)
      : init_(std::move(init_value)),
        sf_(std::move(s)),
        jf_(std::move(j)) {
    // nop
  }

  void operator()(upgrade_lock<detail::shared_spinlock>& ulock,
                  const std::vector<actor>& workers,
                  mailbox_element_ptr& ptr,
                  execution_unit* host) {
    if (ptr->sender == invalid_actor_addr) {
      return;
    }
    actor_msg_vec xs(workers.size());
    for (size_t i = 0; i < workers.size(); ++i) {
      xs[i].first = workers[i];
    }
    ulock.unlock();
    using collector_t = split_join_collector<T, Split, Join>;
    auto hdl = spawn<collector_t, lazy_init>(init_, sf_, jf_, std::move(xs));
    hdl->enqueue(std::move(ptr), host);
  }

private:
  T init_;
  Split sf_; // split function
  Join jf_;  // join function
};

} // namespace detail
} // namespace caf

#endif // CAF_DETAIL_SPLIT_JOIN_HPP

<commit_msg>Fix memory leak in `split_join` policy<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2015                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_DETAIL_SPLIT_JOIN_HPP
#define CAF_DETAIL_SPLIT_JOIN_HPP

#include <vector>

#include "caf/actor.hpp"
#include "caf/locks.hpp"
#include "caf/spawn.hpp"
#include "caf/event_based_actor.hpp"

#include "caf/detail/shared_spinlock.hpp"

namespace caf {
namespace detail {

using actor_msg_vec = std::vector<std::pair<actor, message>>;

template <class T, class Split, class Join>
class split_join_collector : public event_based_actor {
public:
  split_join_collector(T init_value, Split s, Join j, actor_msg_vec xs)
      : workset_(std::move(xs)),
        awaited_results_(workset_.size()),
        join_(std::move(j)),
        split_(std::move(s)),
        value_(std::move(init_value)) {
    // nop
  }

  behavior make_behavior() override {
    return {
      // first message is the forwarded request
      others >> [=] {
        auto rp = this->make_response_promise();
        split_(workset_, this->current_message());
        for (auto& x : workset_)
          this->send(x.first, std::move(x.second));
        this->become(
          // collect results
          others >> [=] {
            join_(value_, this->current_message());
            if (--awaited_results_ == 0) {
              rp.deliver(make_message(value_));
              quit();
            }
          }
        );
        // no longer needed
        workset_.clear();
      }
    };
  }

private:
  actor_msg_vec workset_;
  size_t awaited_results_;
  Join join_;
  Split split_;
  T value_;
};

struct nop_split {
  inline void operator()(actor_msg_vec& xs, message& y) const {
    for (auto& x : xs) {
      x.second = y;
    }
  }
};

template <class T, class Split, class Join>
class split_join {
public:
  split_join(T init_value, Split s, Join j)
      : init_(std::move(init_value)),
        sf_(std::move(s)),
        jf_(std::move(j)) {
    // nop
  }

  void operator()(upgrade_lock<detail::shared_spinlock>& ulock,
                  const std::vector<actor>& workers,
                  mailbox_element_ptr& ptr,
                  execution_unit* host) {
    if (ptr->sender == invalid_actor_addr) {
      return;
    }
    actor_msg_vec xs(workers.size());
    for (size_t i = 0; i < workers.size(); ++i) {
      xs[i].first = workers[i];
    }
    ulock.unlock();
    using collector_t = split_join_collector<T, Split, Join>;
    auto hdl = spawn<collector_t, lazy_init>(init_, sf_, jf_, std::move(xs));
    hdl->enqueue(std::move(ptr), host);
  }

private:
  T init_;
  Split sf_; // split function
  Join jf_;  // join function
};

} // namespace detail
} // namespace caf

#endif // CAF_DETAIL_SPLIT_JOIN_HPP

<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2004 David Faure <faure@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// Test program for libkdepim/email.h
#include "email.h"

#include <kcmdlineargs.h>
#include <kapplication.h>
#include <kdebug.h>

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

static bool check(const QString& txt, const QString& a, const QString& b)
{
  if (a == b) {
    kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "ok" << endl;
  }
  else {
    kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "KO !" << endl;
    exit(1);
  }
  return true;
}

static bool checkGetNameAndEmail(const QString& input, const QString& expName, const QString& expEmail, bool expRetVal)
{
  QString name, email;
  bool retVal = KPIM::getNameAndMail(input, name, email);
  check( "getNameAndMail " + input + " retVal", retVal?"true":"false", expRetVal?"true":"false" );
  check( "getNameAndMail " + input + " name", name, expName );
  check( "getNameAndMail " + input + " email", email, expEmail );
  return true;
}

int main(int argc, char *argv[])
{
  KApplication::disableAutoDcopRegistration();
  KCmdLineArgs::init( argc, argv, "testemail", 0, 0, 0, 0 );
  KApplication app( false, false );

  // Empty input
  checkGetNameAndEmail( QString::null, QString::null, QString::null, false );

  // Email only
  checkGetNameAndEmail( "faure@kde.org", QString::null, "faure@kde.org", false );

  // Normal case
  checkGetNameAndEmail( "David Faure <faure@kde.org>", "David Faure", "faure@kde.org", true );

  // Double-quotes
  checkGetNameAndEmail( "\"Faure, David\" <faure@kde.org>", "Faure, David", "faure@kde.org", true );
  checkGetNameAndEmail( "<faure@kde.org> \"David Faure\"", "David Faure", "faure@kde.org", true );

  // Parenthesis
  checkGetNameAndEmail( "faure@kde.org (David Faure)", "David Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "(David Faure) faure@kde.org", "David Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "My Name (me) <me@home.net>", "My Name (me)", "me@home.net", true ); // #93513

  // Double-quotes inside parenthesis
  checkGetNameAndEmail( "faure@kde.org (David \"Crazy\" Faure)", "David \"Crazy\" Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "(David \"Crazy\" Faure) faure@kde.org", "David \"Crazy\" Faure", "faure@kde.org", true );

  // Parenthesis inside double-quotes
  checkGetNameAndEmail( "\"Faure (David)\" <faure@kde.org>", "Faure (David)", "faure@kde.org", true );
  checkGetNameAndEmail( "<faure@kde.org> \"Faure (David)\"", "Faure (David)", "faure@kde.org", true );

  // Space in email
  checkGetNameAndEmail( "David Faure < faure@kde.org >", "David Faure", "faure@kde.org", true );

  // Check that '@' in name doesn't confuse it
  checkGetNameAndEmail( "faure@kde.org (a@b)", "a@b", "faure@kde.org", true );
  // Interestingly, this isn't supported.
  //checkGetNameAndEmail( "\"a@b\" <faure@kde.org>", "a@b", "faure@kde.org", true );

  // While typing, when there's no '@' yet
  checkGetNameAndEmail( "foo", "foo", QString::null, false );
  checkGetNameAndEmail( "foo <", "foo", QString::null, false );
  checkGetNameAndEmail( "foo <b", "foo", "b", true );

  // If multiple emails are there, only return the first one
  checkGetNameAndEmail( "\"Faure, David\" <faure@kde.org>, KHZ <khz@khz.khz>", "Faure, David", "faure@kde.org", true );

  // No '@'
  checkGetNameAndEmail(  "foo <distlist>", "foo", "distlist", true );

  printf("\nTest OK !\n");

  return 0;
}

<commit_msg>Testframework for isValidEmailAddress added Thanks Till for educating me in how to fix this Approved by TIll<commit_after>/* This file is part of the KDE project
   Copyright (C) 2004 David Faure <faure@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// Test program for libkdepim/email.h
#include "email.h"

#include <kcmdlineargs.h>
#include <kapplication.h>
#include <kdebug.h>

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

using namespace KPIM;

static bool check(const QString& txt, const QString& a, const QString& b)
{
  if (a == b) {
    kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "ok" << endl;
  }
  else {
    kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "KO !" << endl;
    exit(1);
  }
  return true;
}

static bool checkGetNameAndEmail(const QString& input, const QString& expName, const QString& expEmail, bool expRetVal)
{
  QString name, email;
  bool retVal = KPIM::getNameAndMail(input, name, email);
  check( "getNameAndMail " + input + " retVal", retVal?"true":"false", expRetVal?"true":"false" );
  check( "getNameAndMail " + input + " name", name, expName );
  check( "getNameAndMail " + input + " email", email, expEmail );
  return true;
}

// convert this to a switch instead but hey, nothing speedy in here is needed but still.. it would be nice
static QString emailTestParseResultToString( emailParseResult errorCode )
{
  if( errorCode == TooManyAts ) {
    return "TooManyAts";
  } else if( errorCode == TooFewAts ) {
    return "TooFewAts";
  } else if( errorCode == AddressEmpty ) {
    return "AddressEmpty";
  } else if( errorCode == MissingLocalPart ) {
    return "MissingLocalPart";
  } else if( errorCode == MissingDomainPart ) {
    return "MissingDomainPart";
  } else if( errorCode == UnbalancedParens ) {
    return "UnbalancedParens";
  } else if( errorCode == AddressOk ) {
    return "AddressOk";
  } else if( errorCode == UnclosedAngleAddr ) {
    return "UnclosedAngleAddr";
  } else if( errorCode == UnexpectedEnd ) {
    return "UnexpectedEnd";
  } else if( errorCode == UnopenedAngleAddr ) {
    return "UnopenedAngleAddr";
  }
  return "unknown errror code";
}

static bool checkIsValidEmailAddress( const QString& input, const QString&  expErrorCode )
{
  emailParseResult errorCode = KPIM::isValidEmailAddress( input );
  QString errorC = emailTestParseResultToString( errorCode );
  check( "isValidEmailAddress " + input + " errorCode ", errorC , expErrorCode );
  return true;
}

int main(int argc, char *argv[])
{
  KApplication::disableAutoDcopRegistration();
  KCmdLineArgs::init( argc, argv, "testemail", 0, 0, 0, 0 );
  KApplication app( false, false );

  // Empty input
  checkGetNameAndEmail( QString::null, QString::null, QString::null, false );

  // Email only
  checkGetNameAndEmail( "faure@kde.org", QString::null, "faure@kde.org", false );

  // Normal case
  checkGetNameAndEmail( "David Faure <faure@kde.org>", "David Faure", "faure@kde.org", true );

  // Double-quotes
  checkGetNameAndEmail( "\"Faure, David\" <faure@kde.org>", "Faure, David", "faure@kde.org", true );
  checkGetNameAndEmail( "<faure@kde.org> \"David Faure\"", "David Faure", "faure@kde.org", true );

  // Parenthesis
  checkGetNameAndEmail( "faure@kde.org (David Faure)", "David Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "(David Faure) faure@kde.org", "David Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "My Name (me) <me@home.net>", "My Name (me)", "me@home.net", true ); // #93513

  // Double-quotes inside parenthesis
  checkGetNameAndEmail( "faure@kde.org (David \"Crazy\" Faure)", "David \"Crazy\" Faure", "faure@kde.org", true );
  checkGetNameAndEmail( "(David \"Crazy\" Faure) faure@kde.org", "David \"Crazy\" Faure", "faure@kde.org", true );

  // Parenthesis inside double-quotes
  checkGetNameAndEmail( "\"Faure (David)\" <faure@kde.org>", "Faure (David)", "faure@kde.org", true );
  checkGetNameAndEmail( "<faure@kde.org> \"Faure (David)\"", "Faure (David)", "faure@kde.org", true );

  // Space in email
  checkGetNameAndEmail( "David Faure < faure@kde.org >", "David Faure", "faure@kde.org", true );

  // Check that '@' in name doesn't confuse it
  checkGetNameAndEmail( "faure@kde.org (a@b)", "a@b", "faure@kde.org", true );
  // Interestingly, this isn't supported.
  //checkGetNameAndEmail( "\"a@b\" <faure@kde.org>", "a@b", "faure@kde.org", true );

  // While typing, when there's no '@' yet
  checkGetNameAndEmail( "foo", "foo", QString::null, false );
  checkGetNameAndEmail( "foo <", "foo", QString::null, false );
  checkGetNameAndEmail( "foo <b", "foo", "b", true );

  // If multiple emails are there, only return the first one
  checkGetNameAndEmail( "\"Faure, David\" <faure@kde.org>, KHZ <khz@khz.khz>", "Faure, David", "faure@kde.org", true );

  // No '@'
  checkGetNameAndEmail(  "foo <distlist>", "foo", "distlist", true );

  // To many @'s
  checkIsValidEmailAddress( "matt@@fruitsalad.org", "TooManyAts" );

  // To few @'s
  checkIsValidEmailAddress( "mattfruitsalad.org", "TooFewAts" );

  // An empty string
  checkIsValidEmailAddress( QString::null , "AddressEmpty" );

  // email address starting with a @
  checkIsValidEmailAddress( "@mattfruitsalad.org", "MissingLocalPart" );

  // make sure that starting @ and an additional @ in the same email address don't conflict
  // trap the starting @ first and break
  checkIsValidEmailAddress( "@matt@fruitsalad.org", "MissingLocalPart" );

  // email address ending with a @
  checkIsValidEmailAddress( "mattfruitsalad.org@", "MissingDomainPart" );

  // make sure that ending with@ and an additional @ in the email address don't conflict
  checkIsValidEmailAddress( "matt@fruitsalad.org@", "MissingDomainPart" );

  // unbalanced Parens
  checkIsValidEmailAddress( "mattjongel)@fruitsalad.org", "UnbalancedParens" );

  // unbalanced Parens the other way around
  checkIsValidEmailAddress( "mattjongel(@fruitsalad.org", "UnbalancedParens" );

  // Correct parens just to make sure it works
  checkIsValidEmailAddress( "matt(jongel)@fruitsalad.org", "AddressOk" );

  // Check that anglebrackets are closed
  checkIsValidEmailAddress( "matt douhan<matt@fruitsalad.org", "UnclosedAngleAddr" );

  // Check that angle brackets are closed the other way around
  checkIsValidEmailAddress( "matt douhan>matt@fruitsalad.org", "UnopenedAngleAddr" );

  // Check that angle brackets are closed the other way around, and anglebrackets in domainpart
  // instead of local part
  // checkIsValidEmailAddress( "matt douhanmatt@<fruitsalad.org", "UnclosedAngleAddr" );

  // check that a properly formated anglebrackets situation is OK
  checkIsValidEmailAddress( "matt douhan<matt@fruitsalad.org>", "AddressOk" );

  // a full email address with comments angle brackets and the works should be valid too
  checkIsValidEmailAddress( "Matt (jongel) Douhan <matt@fruitsalad.org>", "AddressOk" );

  // Double quotes
  checkIsValidEmailAddress( "\"Matt Douhan\" <matt@fruitsalad.org>", "AddressOk" );

  // Double quotes inside parens
  checkIsValidEmailAddress( "Matt (\"jongel\") Douhan <matt@fruitsalad.org>", "AddressOk" );

  // Parens inside double quotes
  checkIsValidEmailAddress( "Matt \"(jongel)\" Douhan <matt@fruitsalad.org>", "AddressOk" );

  // Space in email
  checkIsValidEmailAddress( "Matt Douhan < matt@fruitsalad.org >", "AddressOk" );

  // @ is allowed inisde doublequotes
  checkIsValidEmailAddress( "\"matt@jongel\" <matt@fruitsalad.org>", "AddressOk" );

  // a , inside a double quoted string is OK, how do I know this? well Ingo says so
  // and it makes sense since it is also a seperator of email addresses
  checkIsValidEmailAddress( "\"Douhan, Matt\" <matt@fruitsalad.org>", "AddressOk" );

  printf("\nTest OK !\n");

  return 0;
}

<|endoftext|>