/*         ______   ___    ___
 *        /\  _  \ /\_ \  /\_ \
 *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
 *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
 *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
 *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
 *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
 *                                           /\____/
 *                                           \_/__/
 *
 *      The 3D scene renderer.
 *
 *      By Calin Andrian.
 *
 *	Merging into Allegro and API changes by Bertrand Coconnier.
 *
 *      See readme.txt for copyright information.
 */

#include <float.h>
#include <limits.h>

#include "allegro.h"
#include "allegro/internal/aintern.h"

/* hash tables divide the screen height in (up to) HASH_NUM parts */
#define HASH_NUM 256
/* each part is made of 2^HASH_SHIFT lines */
#define HASH_SHIFT 3
/* Consequently, scanline sorting algorithm can handle up to
   HASH_NUM * 2^HASH_SHIFT lines
 */

static POLYGON_EDGE *scene_edge = NULL, *scene_inact;
static POLYGON_INFO *scene_poly = NULL;
static int scene_nedge = 0, scene_maxedge = 0;
static int scene_npoly = 0, scene_maxpoly = 0;
static BITMAP *scene_bmp;
static COLOR_MAP *scene_cmap;
static int scene_alpha;
static int last_x, scene_y;
static uintptr_t scene_addr;
static float last_z;
static POLYGON_EDGE **hash = NULL;

float scene_gap = 100.0;

/* create_scene:
 *  Allocate memory for a scene, nedge and npoly are your estimate of how
 *  many edges and how many polygons you will render (you cannot get over
 *  the limit specified here).
 *  If you use same values in succesive calls, the space will be reused.
 *  Returns negative numbers if allocations fail, zero on success.
 */
int create_scene(int nedge, int npoly)
{
   if (nedge != scene_maxedge) {        /* don't realloc, we don't need */
      scene_maxedge = 0;                /* the old data */
      if (scene_edge) _AL_FREE(scene_edge);
      scene_edge = _AL_MALLOC(nedge * sizeof(POLYGON_EDGE));
      if (!scene_edge) return -1;
   }

   if (npoly != scene_maxpoly) {
      scene_maxpoly = 0;
      if (scene_poly) _AL_FREE(scene_poly);
      scene_poly = _AL_MALLOC(npoly * sizeof(POLYGON_INFO));
      if (!scene_poly) {
         _AL_FREE(scene_edge);
         scene_edge = NULL;
         return -2;
      }
   }

   if (!hash) {
      hash = _AL_MALLOC(HASH_NUM * sizeof(POLYGON_EDGE*));
      if (!hash) {
         _AL_FREE(scene_edge);
	 _AL_FREE(scene_poly);
         return -3;
      }
   }

   scene_maxedge = nedge;
   scene_maxpoly = npoly;
   return 0;
}

/* clear_scene:
 *  Initializes a scene. The bitmap is the bitmap you will eventually render
 *  on.
 */
void clear_scene(BITMAP* bmp)
{
   int i;
   ASSERT(bmp);
   ASSERT(hash);

   scene_inact = NULL;
   scene_bmp = bmp;
   scene_nedge = scene_npoly = 0;

   for (i=0; i<HASH_NUM; i++)
      hash[i] = NULL;
}

/* destroy_scene:
 *  Deallocate memory previously allocated by create_scene.
 */
void destroy_scene(void)
{
   if (scene_edge) {
      _AL_FREE(scene_edge);
      scene_edge = NULL;
   }

   if (scene_poly) {
      _AL_FREE(scene_poly);
      scene_poly = NULL;
   }

   if (hash) {
      _AL_FREE(hash);
      hash = NULL;
   }

   scene_maxedge = scene_maxpoly = 0;
}

/* _add_edge_hash:
 *  Adds an edge structure to a linked list, returning the new head pointer.
 *  This function uses hash tables when sort_by_x == FALSE to speed up edge
 *  sorting.
 */
static POLYGON_EDGE *_add_edge_hash(POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)
{
   POLYGON_EDGE *pos = list;
   POLYGON_EDGE *prev = NULL;

   if (sort_by_x) {
      while ((pos) && (pos->x < edge->x)) {
	 prev = pos;
	 pos = pos->next;
      }
   }
   else {
      int i;
      int empty = 1, first = 1;

      i = edge->top >> HASH_SHIFT;

      ASSERT(i < HASH_NUM);

      if (hash[i]) {
         pos = hash[i];
         prev = pos->prev;
         empty = 0;
      }

      while ((pos) && (pos->top < edge->top)) {
         prev = pos;
         pos = pos->next;
         first = 0;
      }

      if (first || empty)
         hash[i] = edge;
   }

   edge->next = pos;
   edge->prev = prev;

   if (pos)
      pos->prev = edge;

   if (prev) {
      prev->next = edge;
      return list;
   }
   else
      return edge;
}

/* poly_plane:
 *  Computes the plane's equation coefficients A, B, C, D, in the original
 *  space (before projection) for perspective projection:
 *    Axz + Byz + Cz + D = 0
 *  This routine changed by Bertrand Coconnier in order to handle coincident
 *  vertices in the polygon (According to Ben Davis' hack in poly3d.c).
 *  Now the function computes the polygon area in planes xy, yz, and xz in
 *  order to obtain the polygon normal. Plane equation coefficients are
 *  then computed.
 */
static void poly_plane(V3D *vtx[], POLYGON_INFO *poly, int vc)
{
   int i;
   float d;
   /* Vertices are persp-projected. Plane equation must be computed in
    * the original space, so we have to "un-persp-project" vertices.
    */
   float z0 = fixtof(vtx[0]->z);
   float x0 = fixtof(vtx[0]->x) * z0; /* "un-persp-projection" */
   float y0 = fixtof(vtx[0]->y) * z0; /* "un-persp-projection" */
   float z = fixtof(vtx[vc-1]->z);
   float x = fixtof(vtx[vc-1]->x) * z; /* "un-persp-projection" */
   float y = fixtof(vtx[vc-1]->y) * z; /* "un-persp-projection" */

   poly->a = (z0 + z) * (y - y0); /* area in plane yz */
   poly->b = (x0 + x) * (z - z0); /* area in plane zx */
   poly->c = (y0 + y) * (x - x0); /* area in plane xy */

   for(i=1; i<vc; i++) {
      z = fixtof(vtx[i]->z);
      x = fixtof(vtx[i]->x) * z;
      y = fixtof(vtx[i]->y) * z;
      poly->a += (z0 + z) * (y0 - y); /* area in plane yz */
      poly->b += (x0 + x) * (z0 - z); /* area in plane zx */
      poly->c += (y0 + y) * (x0 - x); /* area in plane xy */
      x0 = x;
      y0 = y;
      z0 = z;
   }

   /* dot product of the plane normal (poly->a, poly->b, poly->c) with
    * the vector (x, y, z)
    */
   d = poly->a * x + poly->b * y + poly->c * z;
   /* prepare A, B, C for extracting 1/z */
   if ((d < 1e-10) && (d > -1e-10)) {
      if (d >= 0)
         d = 1e-10;
      else
         d = -1e-10;
   }
   poly->a /= d; poly->b /= d; poly->c /= d;
}

/* poly_plane_f:
 *  Floating point version of poly_plane.
 *  See poly_plane comments.
 */
static void poly_plane_f(V3D_f *vtx[], POLYGON_INFO *poly, int vc)
{
   int i;
   float d;

   float z0 = vtx[0]->z;
   float x0 = vtx[0]->x * z0;
   float y0 = vtx[0]->y * z0;
   float z = vtx[vc-1]->z;
   float x = vtx[vc-1]->x * z;
   float y = vtx[vc-1]->y * z;

   poly->a = (z0 + z) * (y - y0);
   poly->b = (x0 + x) * (z - z0);
   poly->c = (y0 + y) * (x - x0);

   for(i=1; i<vc; i++) {
      z = vtx[i]->z;
      x = vtx[i]->x * z;
      y = vtx[i]->y * z;
      poly->a += (z0 + z) * (y0 - y);
      poly->b += (x0 + x) * (z0 - z);
      poly->c += (y0 + y) * (x0 - x);
      x0 = x;
      y0 = y;
      z0 = z;
   }

   d = poly->a * x + poly->b * y + poly->c * z;

   if ((d < 1e-10) && (d > -1e-10)) {
      if (d >= 0)
         d = 1e-10;
      else
         d = -1e-10;
   }
   poly->a /= d; poly->b /= d; poly->c /= d;
}

/* far_z:
 *  Compares z values of the plane to which 'edge' belongs and the plane
 *  of 'poly', in point x, y.
 *  Returns true if 'edge' is farther than 'poly'.
 */
static int far_z(int y, POLYGON_EDGE *edge, POLYGON_INFO *poly)
{
   float z1, z2, zd;

   z1 = edge->dat.z;

   /* z2 = 1/z of the plane in the point x, y */
   z2 = poly->a * fixtof(edge->x) + poly->b * y + poly->c;
   zd = (z2 - z1) * scene_gap;
   if (zd > z1)
      return 1;
   if (zd < -z1)
      return 0;

   return (z2 - z1 + 100.0 * (poly->a - edge->poly->a) > 0);
}

/* init_poly:
 *  Initializes different elements in the poly structure.
 */
static void init_poly(int type, POLYGON_INFO *poly)
{
   static int flag_table[] = {
      INTERP_Z,
      INTERP_Z,
      INTERP_Z,
      INTERP_Z,
      INTERP_Z,
      INTERP_Z | INTERP_THRU,
      INTERP_Z | INTERP_THRU,
      INTERP_Z | INTERP_BLEND,
      INTERP_Z | INTERP_BLEND,
      INTERP_Z | INTERP_THRU | INTERP_BLEND,
      INTERP_Z | INTERP_THRU | INTERP_BLEND,
      INTERP_Z | INTERP_THRU | INTERP_TRANS,
      INTERP_Z | INTERP_THRU | INTERP_TRANS,
      INTERP_Z | INTERP_THRU | INTERP_TRANS,
      INTERP_Z | INTERP_THRU | INTERP_TRANS
   };

   poly->alt_drawer = _optim_alternative_drawer;
   poly->inside = 0;

   type &= ~POLYTYPE_ZBUF;
   poly->flags |= flag_table[type];

   if (poly->flags & POLYTYPE_ZBUF) {
      poly->flags |= INTERP_THRU;
   }

   poly->cmap = color_map;
   poly->alpha = _blender_alpha;

   if (bitmap_color_depth(scene_bmp) == 8) {
      poly->flags &= ~INTERP_BLEND;
   }
   else {
      if (poly->flags & INTERP_BLEND) {
         poly->b15 = _blender_col_15;
         poly->b16 = _blender_col_16;
         poly->b24 = _blender_col_24;
         poly->b32 = _blender_col_32;
      }
   }

   if ((type == POLYTYPE_FLAT) && (_drawing_mode != DRAW_MODE_SOLID)) {
      poly->flags |= INTERP_NOSOLID;
      poly->dmode = _drawing_mode;
      switch(_drawing_mode) {
         case DRAW_MODE_MASKED_PATTERN:
            poly->flags |= INTERP_THRU;
         case DRAW_MODE_COPY_PATTERN:
         case DRAW_MODE_SOLID_PATTERN:
            poly->dpat = _drawing_pattern;
            poly->xanchor = _drawing_x_anchor;
            poly->yanchor = _drawing_y_anchor;
            break;
         default:
            poly->flags |= INTERP_THRU;
            poly->dpat = NULL;
            poly->xanchor = poly->yanchor = 0;
            break;
      }
   }

   scene_npoly++;
}

/* scene_polygon3d:
 *  Put a polygon in the rendering list. Nothing is really rendered at this
 *  moment. Should be called between clear_scene() and render_scene().
 *  Unlike polygon3d(), the polygon may be concave or self-intersecting.
 *  Shapes that penetrate one another may look OK, but they are not really
 *  handled by this code.
 *  Note that the texture is stored as a pointer only, and you should keep
 *  the actual bitmap until render_scene(), where it is used.
 *  Returns zero on success, or a negative number if the polygon won't be
 *  rendered for lack of rendering routine.
 */
int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[])
{
   int c;
   V3D *v1, *v2;
   POLYGON_EDGE *edge;
   POLYGON_INFO *poly;

   ASSERT(scene_nedge + vc <= scene_maxedge);
   ASSERT(scene_npoly < scene_maxpoly);

   edge = &scene_edge[scene_nedge];
   poly = &scene_poly[scene_npoly];

   /* set up the drawing mode */
   poly->drawer = _get_scanline_filler(type, &poly->flags, &poly->info,
                                      texture, scene_bmp);
   if (!poly->drawer)
      return -1;

   init_poly(type, poly);
   poly->color = vtx[0]->c;
   poly_plane(vtx, poly, vc);

   v2 = vtx[vc-1];

   /* fill the edge table */
   for (c=0; c<vc; c++) {
      v1 = v2;
      v2 = vtx[c];

      if (_fill_3d_edge_structure(edge, v1, v2, poly->flags, scene_bmp)) {
         edge->poly = poly;
	 scene_inact = _add_edge_hash(scene_inact, edge, FALSE);
	 edge++;
         scene_nedge++;
      }
   }
   return 0;
}

/* scene_polygon3d_f:
 *  Floating point version of scene_polygon3d.
 */
int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[])
{
   int c;
   V3D_f *v1, *v2;
   POLYGON_EDGE *edge;
   POLYGON_INFO *poly;

   ASSERT(scene_nedge + vc <= scene_maxedge);
   ASSERT(scene_npoly < scene_maxpoly);

   edge = &scene_edge[scene_nedge];
   poly = &scene_poly[scene_npoly];

   /* set up the drawing mode */
   poly->drawer = _get_scanline_filler(type, &poly->flags, &poly->info,
                                      texture, scene_bmp);
   if (!poly->drawer)
      return -1;

   init_poly(type, poly);
   poly->color = vtx[0]->c;
   poly_plane_f(vtx, poly, vc);

   v2 = vtx[vc-1];

   /* fill the edge table */
   for (c=0; c<vc; c++) {
      v1 = v2;
      v2 = vtx[c];

      if (_fill_3d_edge_structure_f(edge, v1, v2, poly->flags, scene_bmp)) {
         edge->poly = poly;
	 scene_inact = _add_edge_hash(scene_inact, edge, FALSE);
	 edge++;
         scene_nedge++;
      }
   }
   return 0;
}

/* scene_segment:
 *  Draws a piece of the scanline, corresponding to a polygon. The start and
 *  end values for x are taken from e01 and e02, the polygon style from poly.
 */
static void scene_segment(POLYGON_EDGE *e01, POLYGON_EDGE *e02,
                          POLYGON_INFO *poly)
{
   int x, w, gap, flags;
   fixed step, width;
   float w1, step_f;
   int x01 = fixceil(e01->x);
   int x02 = fixceil(e02->x);
   float z01 = e01->dat.z;
   POLYGON_EDGE *e1 = poly->left_edge;
   POLYGON_EDGE *e2 = poly->right_edge;
   POLYGON_SEGMENT *info = &poly->info, *dat1, *dat2;
   SCANLINE_FILLER drawer;

   if ((x01 < last_x) && (z01 < last_z))
      x01 = last_x;
   if (scene_bmp->clip) {
      if (x01 < scene_bmp->cl)
         x01 = scene_bmp->cl;
      if (x02 > scene_bmp->cr)
         x02 = scene_bmp->cr;
   }
   if (x01 >= x02)
      return;

   if (!e2) {
      e2 = e02;
      while (e2 && (e2->poly != poly))
        e2 = e2->next;

      if (!e2) return;
      poly->right_edge = e2;
   }

   x = fixceil(e1->x);
   w = fixceil(e2->x) - x;
   if (w <= 0) return;

   /* Subpixel and subtexel accuracy */
   step = (x << 16) - e1->x;
   step_f = fixtof(step);
   width = e2->x - e1->x;
   w1 = 65536. / width;

   flags = poly->flags;
   dat1 = &e1->dat;
   dat2 = &e2->dat;

   if (flags & INTERP_FLAT) {
      info->c = poly->color;
   }
   else {
      if (flags & INTERP_1COL) {
         info->dc = fixdiv(dat2->c - dat1->c, width);
         info->c = dat1->c + fixmul(step, info->dc);
      }

      if (flags & INTERP_3COL) {
         info->dr = fixdiv(dat2->r - dat1->r, width);
         info->dg = fixdiv(dat2->g - dat1->g, width);
         info->db = fixdiv(dat2->b - dat1->b, width);
         info->r = dat1->r + fixmul(step, info->dr);
         info->g = dat1->g + fixmul(step, info->dg);
         info->b = dat1->b + fixmul(step, info->db);
      }

      if (flags & INTERP_FIX_UV) {
         info->du = fixdiv(dat2->u - dat1->u, width);
         info->dv = fixdiv(dat2->v - dat1->v, width);
         info->u = dat1->u + fixmul(step, info->du);
         info->v = dat1->v + fixmul(step, info->dv);
      }

      if (flags & INTERP_FLOAT_UV) {
         info->dfu = (dat2->fu - dat1->fu) * w1;
         info->dfv = (dat2->fv - dat1->fv) * w1;
         info->fu = dat1->fu + step_f * info->dfu;
         info->fv = dat1->fv + step_f * info->dfv;
      }
   }

   info->dz = (dat2->z - dat1->z) * w1;
   info->z = dat1->z + step_f * info->dz;

   if (x < x01) {
      gap = x01 - x;
      x = x01;
      w -= gap;
      _clip_polygon_segment_f(info, gap, poly->flags);
   }

   if (x + w >= x02)
      w = x02 - x;

   if (w <= 0) return;

   if ((flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0)) {
      float z1 = 1. / info->z;
      info->u = info->fu * z1;
      info->v = info->fv * z1;
      info->du = info->dfu * z1;
      info->dv = info->dfv * z1;
      drawer = poly->alt_drawer;
   }
   else
      drawer = poly->drawer;

   color_map = poly->cmap;
   _blender_alpha = poly->alpha;
   if (flags & INTERP_BLEND) {
      _blender_col_15 = poly->b15;
      _blender_col_16 = poly->b16;
      _blender_col_24 = poly->b24;
      _blender_col_32 = poly->b32;
   }

   if (drawer == _poly_scanline_dummy) {
      if (flags & INTERP_NOSOLID) {
         drawing_mode(poly->dmode, poly->dpat, poly->xanchor, poly->yanchor);
         scene_bmp->vtable->hfill(scene_bmp, x, scene_y, x+w-1, poly->color);
         solid_mode();
      }
      else
         scene_bmp->vtable->hfill(scene_bmp, x, scene_y, x+w-1, poly->color);
   }
   else {
      int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(scene_bmp));
      if (flags & INTERP_ZBUF)
         info->zbuf_addr = bmp_write_line(_zbuffer, scene_y) + x * sizeof(float);

      info->read_addr = bmp_read_line(scene_bmp, scene_y) + dx;
      drawer(scene_addr + dx, w, info);
   }
}

/* scene_trans_seg:
 *  Checks whether p0 is visible either directly or through transparent
 *  polygons on top of it. If it's visible, draws all the visible stack
 *  with x values from e1 and e2. At entry, p is the top polygon.
 *  Returns nonzero if something was drawn.
 */
static int scene_trans_seg(POLYGON_EDGE *e1, POLYGON_EDGE *e2,
                           POLYGON_INFO *p0, POLYGON_INFO *p)
{
   int c;

   if (!p) return 0;
   c = 1;
   while (1) {
      if (p == p0) c = 0;
      if (!(p->flags & INTERP_THRU) || !p->next) break;
      p = p->next;
   }
   if (c) return 0;

   /* p is first opaque or the very last */
   while (p) {
      scene_segment(e1, e2, p);
      p = p->prev;
   }
   return 1;
}

/* render_scene:
 *  Renders all the specified scene_polygon3d()'s on the bitmap passed to
 *  clear_scene(). Rendering is done one scanline at a time, with no pixel
 *  being processed more than once. Note that between clear_scene() and
 *  render_scene() you shouldn't change the clip rectangle of the destination
 *  bitmap. Also, all the textures passed to scene_polygon3d() are stored
 *  as pointers only and actually used in render_scene().
 */
void render_scene(void)
{
   int p;
   #ifdef ALLEGRO_DOS
      int old87 = 0;
   #endif
   POLYGON_EDGE *edge, *start_edge = NULL;
   POLYGON_EDGE *active_edges = NULL, *last_edge = NULL;
   POLYGON_INFO *active_poly = NULL;

   ASSERT(scene_maxedge > 0);
   ASSERT(scene_maxpoly > 0);

   scene_cmap = color_map;
   scene_alpha = _blender_alpha;
   solid_mode();
   /* set fpu to single-precision, truncate mode */
   #ifdef ALLEGRO_DOS
      old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC);
   #endif

   acquire_bitmap(scene_bmp);
   bmp_select(scene_bmp);

   for (p=0; p<scene_npoly; p++) {
      scene_poly[p].inside = 0;
   }

   /* for each scanline in the clip region... */
   for (scene_y=scene_bmp->ct; scene_y<scene_bmp->cb; scene_y++) {
      scene_addr = bmp_write_line(scene_bmp, scene_y);

      /* check for newly active edges */
      edge = scene_inact;
      while ((edge) && (edge->top == scene_y)) {
	 POLYGON_EDGE *next_edge = edge->next;
	 scene_inact = _remove_edge(scene_inact, edge);
	 active_edges = _add_edge_hash(active_edges, edge, TRUE);
	 edge = next_edge;
      }

      /* no edges on this line */
      if (!active_edges) continue;

      /* fill the scanline */
      last_x = INT_MIN;
      last_z = 0.0;
      for (edge=active_edges; edge; edge=edge->next) {
         int x = fixceil(edge->x);
         POLYGON_INFO *poly = edge->poly;

         /* one polygon changes status */
         poly->inside = 1 - poly->inside;
         if (poly->inside) {
            POLYGON_INFO *pos = active_poly;
            POLYGON_INFO *prev = NULL;

            poly->left_edge = edge;
	    poly->right_edge = NULL;

            /* find its place in the list */
            while (pos && far_z(scene_y, edge, pos)) {
               prev = pos;
               pos = pos->next;
            }
            /* poly overlaps pos. Was pos visible ? */
            if (scene_trans_seg(start_edge, edge, pos, active_poly)) {
               start_edge = edge;
            }
            /* link */
            poly->next = pos;
            poly->prev = prev;
            if (pos) pos->prev = poly;
            if (prev)
	       prev->next = poly;
            else {
               start_edge = edge;
               active_poly = poly;
            }
         }
	 else {
            poly->right_edge = edge;
            /* poly ends here. Was it visible ? */
            if (scene_trans_seg(start_edge, edge, poly, active_poly)) {
               start_edge = edge;
               if (x > last_x) {
                  last_x = x;
                  last_z = edge->dat.z;
               }
            }
            /* unlink */
            if (poly->next)
	       poly->next->prev = poly->prev;
            if (poly->prev)
	       poly->prev->next = poly->next;
            else
               active_poly = poly->next;
         }
         /* prepare for backward scan */
         last_edge = edge;
      }

      /* update edges, remove dead ones, re-sort */
      edge = last_edge;
      active_edges = NULL;

      while (edge) {
	 POLYGON_EDGE *prev_edge = edge->prev;
	 if (scene_y < edge->bottom) {
            POLYGON_SEGMENT *dat = &edge->dat;
            int flags = edge->poly->flags;

	    edge->x += edge->dx;
            dat->z += dat->dz;

	    if (!(flags & INTERP_FLAT)) {
	       if (flags & INTERP_1COL)
	          dat->c += dat->dc;

               if (flags & INTERP_3COL) {
	          dat->r += dat->dr;
	          dat->g += dat->dg;
	          dat->b += dat->db;
	       }

	       if (flags & INTERP_FIX_UV) {
	          dat->u += dat->du;
	          dat->v += dat->dv;
	       }

	       if (flags & INTERP_FLOAT_UV) {
	          dat->fu += dat->dfu;
	          dat->fv += dat->dfv;
	       }
	    }

            active_edges = _add_edge_hash(active_edges, edge, TRUE);
	 }
	 edge = prev_edge;
      }
   }

   bmp_unwrite_line(scene_bmp);
   release_bitmap(scene_bmp);

   /* reset fpu mode */
   #ifdef ALLEGRO_DOS
      _control87(old87, MCW_PC | MCW_RC);
   #endif
   color_map = scene_cmap;
   _blender_alpha = scene_alpha;
   solid_mode();

   /* mark the tables as full */
   scene_nedge = scene_maxedge;
   scene_npoly = scene_maxpoly;
}

{'repo_name': 'SuperIlu/DOjS', 'stars': '117', 'repo_language': 'C', 'file_name': 'sst1vid.h', 'mime_type': 'text/x-c', 'hash': 4560710270536239318, 'source_dataset': 'data'}


%% -*- mode: erlang -*-

%% accept R15B02.., any R16B except R16B03
%% also accept OTP v17, altough it may not work properly on that release yet..
{require_otp_vsn, "R16B$|R16B[^0]|R16B0[^3]|R16B03-1|17|18|19|20|21|22"}.

{erl_opts, [debug_info]}.
{yrl_opts, [{includefile, "include/erlydtl_preparser.hrl"}]}.

{'repo_name': 'erlydtl/erlydtl', 'stars': '470', 'repo_language': 'Erlang', 'file_name': 'erlydtl_preparser.hrl', 'mime_type': 'text/plain', 'hash': -2479304613114316309, 'source_dataset': 'data'}


#ifndef BOOST_METAPARSE_V1_RANGE_HPP
#define BOOST_METAPARSE_V1_RANGE_HPP

// Copyright Abel Sinkovics (abel@sinkovics.hu)  2014.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <boost/metaparse/v1/accept_when.hpp>
#include <boost/metaparse/v1/one_char.hpp>
#include <boost/metaparse/v1/util/in_range_c.hpp>
#include <boost/metaparse/v1/error/unexpected_character.hpp>

namespace boost
{
  namespace metaparse
  {
    namespace v1
    {
      template <class From, class To>
      struct range :
        accept_when<
          one_char,
          util::in_range_c<char, From::type::value, To::type::value>,
          error::unexpected_character
        >
      {};
    }
  }
}

#endif

{'repo_name': 'FantasticLBP/Hotels', 'stars': '312', 'repo_language': 'Objective-C', 'file_name': 'IQKeyboardManager.strings', 'mime_type': 'text/plain', 'hash': 7969970578832166008, 'source_dataset': 'data'}


/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2017, Telestax Inc and individual contributors
 * by the @authors tag.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.restcomm.media.core.rtp.rfc2833;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URL;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.restcomm.media.core.codec.g711.alaw.Decoder;
import org.restcomm.media.core.codec.g711.ulaw.Encoder;
import org.restcomm.media.core.component.audio.AudioComponent;
import org.restcomm.media.core.component.audio.AudioMixer;
import org.restcomm.media.core.component.dsp.DspFactoryImpl;
import org.restcomm.media.core.component.oob.OOBComponent;
import org.restcomm.media.core.component.oob.OOBMixer;
import org.restcomm.media.core.network.deprecated.PortManager;
import org.restcomm.media.core.network.deprecated.RtpPortManager;
import org.restcomm.media.core.network.deprecated.UdpManager;
import org.restcomm.media.core.network.netty.NettyNetworkManager;
import org.restcomm.media.core.network.netty.channel.NettyNetworkChannelGlobalContext;
import org.restcomm.media.core.pcap.AsyncPcapChannel;
import org.restcomm.media.core.pcap.AsyncPcapChannelHandler;
import org.restcomm.media.core.pcap.PcapPacketEncoder;
import org.restcomm.media.core.pcap.PcapPlayer;
import org.restcomm.media.core.resource.dtmf.DetectorImpl;
import org.restcomm.media.core.rtp.RtpChannel;
import org.restcomm.media.core.rtp.RtpClock;
import org.restcomm.media.core.rtp.crypto.DtlsSrtpServerProvider;
import org.restcomm.media.core.rtp.statistics.RtpStatistics;
import org.restcomm.media.core.scheduler.Clock;
import org.restcomm.media.core.scheduler.PriorityQueueScheduler;
import org.restcomm.media.core.scheduler.Scheduler;
import org.restcomm.media.core.scheduler.ServiceScheduler;
import org.restcomm.media.core.scheduler.WallClock;
import org.restcomm.media.core.sdp.format.AVProfile;
import org.restcomm.media.core.spi.ConnectionMode;
import org.restcomm.media.core.spi.dtmf.DtmfDetectorListener;
import org.restcomm.media.core.spi.dtmf.DtmfEvent;
import org.restcomm.media.core.spi.format.AudioFormat;
import org.restcomm.media.core.spi.format.FormatFactory;
import org.restcomm.media.core.spi.format.Formats;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;

/**
 * @author Henrique Rosa (henrique.rosa@telestax.com)
 *
 */
public class DtmfRfc2833Test {

    // Netty IO Stack
    private ScheduledThreadPoolExecutor executor;
    private ListeningScheduledExecutorService scheduler;
    private NioEventLoopGroup eventGroup;
    private Bootstrap bootstrap;
    private NettyNetworkManager networkManager;

    // PCAP stack
    private AsyncPcapChannel channel;
    private PcapPlayer player;

    // Legacy IO Stack
    private Scheduler ioScheduler;
    private UdpManager udpManager;
    private PortManager portManager;

    // Media Stack
    private Clock clock;
    private PriorityQueueScheduler mediaScheduler;
    private AudioMixer mixer;
    private OOBMixer oobMixer;
    private AudioComponent inbandDetectorComponent;
    private OOBComponent oobDetectorComponent;
    private DspFactoryImpl dspFactory;

    // DTMF Detector
    private DetectorImpl dtmfDetector;

    // RTP stack
    private RtpClock rtpClock;
    private RtpClock oobClock;
    private RtpStatistics rtpStatistics;
    private RtpChannel rtpChannel;

    @Before
    public void before() throws Exception {
        // Media Formats
        AudioFormat pcma = FormatFactory.createAudioFormat("pcma", 8000, 8, 1);
        Formats fmts = new Formats();
        fmts.add(pcma);

        Formats dstFormats = new Formats();
        dstFormats.add(FormatFactory.createAudioFormat("LINEAR", 8000, 16, 1));

        // Netty IO Stack
        this.executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5);
        this.executor.prestartAllCoreThreads();
        this.executor.setRemoveOnCancelPolicy(true);
        this.scheduler = MoreExecutors.listeningDecorator(executor);
        this.eventGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors(), scheduler);
        this.bootstrap = new Bootstrap().channel(NioDatagramChannel.class).group(eventGroup);
        this.networkManager = new NettyNetworkManager(bootstrap);

        // Legacy IO Stack
        this.ioScheduler = new ServiceScheduler(this.clock);
        this.ioScheduler.start();
        this.portManager = new RtpPortManager(6000, 65000);
        this.udpManager = new UdpManager(this.ioScheduler, this.portManager, this.portManager);
        this.udpManager.setBindAddress("127.0.0.1");
        this.udpManager.setLocalBindAddress("127.0.0.1");
        this.udpManager.start();

        // Media Stack
        this.clock = new WallClock();
        this.mediaScheduler = new PriorityQueueScheduler(this.clock);
        this.mediaScheduler.start();
        this.mixer = new AudioMixer(this.mediaScheduler);
        this.oobMixer = new OOBMixer(this.mediaScheduler);
        this.dspFactory = new DspFactoryImpl();
        this.dspFactory.addCodec(Encoder.class.getName());
        this.dspFactory.addCodec(Decoder.class.getName());
        this.dspFactory.addCodec(org.restcomm.media.core.codec.g711.alaw.Encoder.class.getName());
        this.dspFactory.addCodec(org.restcomm.media.core.codec.g711.alaw.Decoder.class.getName());

        // RTP Stack
        this.rtpClock = new RtpClock(this.clock);
        this.oobClock = new RtpClock(this.clock);
        this.rtpStatistics = new RtpStatistics(this.rtpClock);
        this.rtpChannel = new RtpChannel(1, 50, this.rtpStatistics, this.rtpClock, this.oobClock, mediaScheduler, udpManager, mock(DtlsSrtpServerProvider.class));
        this.rtpChannel.setInputDsp(this.dspFactory.newProcessor());
        this.mixer.addComponent(this.rtpChannel.getAudioComponent());
        this.oobMixer.addComponent(this.rtpChannel.getOobComponent());
    }

    @SuppressWarnings("unchecked")
    @After
    public void after() {
        // DTMF Detector
        if (this.dtmfDetector != null) {
            this.dtmfDetector.deactivate();
            this.dtmfDetector = null;
        }

        // RTP stack
        if (this.rtpChannel != null) {
            this.rtpChannel.close();
            this.rtpChannel = null;
        }
        if (this.rtpStatistics != null) {
            this.rtpStatistics.reset();
            this.rtpStatistics = null;
        }
        this.rtpClock = null;

        // Media Stack
        this.oobMixer.stop();
        this.mixer.stop();
        this.mediaScheduler.stop();

        // Legacy IO
        this.udpManager.stop();
        this.ioScheduler.stop();

        // PCAP Stack
        if (player != null) {
            if (player.isPlaying()) {
                player.stop();
            }
            player = null;
        }

        if (channel != null) {
            if (channel.isOpen()) {
                channel.close(mock(FutureCallback.class));
            }
            channel = null;
        }

        if (dtmfDetector != null) {
            this.dtmfDetector.deactivate();
            this.dtmfDetector = null;
        }

        this.networkManager = null;
        this.bootstrap = null;

        if (this.eventGroup != null) {
            if (!this.eventGroup.isShutdown()) {
                this.eventGroup.shutdownGracefully(0L, 0L, TimeUnit.NANOSECONDS);
            }
            this.eventGroup = null;
        }

        if (this.scheduler != null) {
            if (!this.scheduler.isShutdown()) {
                scheduler.shutdown();
            }
            scheduler = null;
        }

        if (this.executor != null) {
            if (!this.executor.isShutdown()) {
                this.executor.shutdown();
            }
            this.executor = null;
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testDetectHashFromPcap() throws Exception {
        // given
        // int rtpEventPacketCount = 35;
        // int rtpEventPacketLength = 24;
        // int rtpPacketCount = 39;
        // int rtpPacketLength = 180;
        // int totalOctets = (rtpEventPacketLength * rtpEventPacketCount) + (rtpPacketCount * rtpPacketLength);
        // int totalPackets = rtpEventPacketCount + rtpPacketCount;
        long rtpStreamDuration = 900;
        InetSocketAddress localAddress = new InetSocketAddress("127.0.0.1", 64000);

        String filepath = "dtmf-oob-one-hash.cap.gz";
        PcapPacketEncoder packetEncoder = new PcapPacketEncoder();
        AsyncPcapChannelHandler channelInitializer = new AsyncPcapChannelHandler(packetEncoder);
        bootstrap.handler(channelInitializer);
        NettyNetworkChannelGlobalContext context = new NettyNetworkChannelGlobalContext(networkManager);
        channel = new AsyncPcapChannel(context);
        player = new PcapPlayer(channel, scheduler);

        FutureCallback<Void> openCallback = mock(FutureCallback.class);
        FutureCallback<Void> bindCallback = mock(FutureCallback.class);
        FutureCallback<Void> connectCallback = mock(FutureCallback.class);

        rtpChannel.bind(false, false);
        rtpChannel.connect(localAddress);
        SocketAddress remoteAddress = rtpChannel.getLocalAddress();
        rtpChannel.setFormatMap(AVProfile.audio);
        rtpChannel.updateMode(ConnectionMode.RECV_ONLY);

        channel.open(openCallback);
        verify(openCallback, timeout(100)).onSuccess(null);
        channel.bind(localAddress, bindCallback);
        verify(bindCallback, timeout(100)).onSuccess(null);
        channel.connect(remoteAddress, connectCallback);
        verify(connectCallback, timeout(100)).onSuccess(null);

        this.dtmfDetector = new DetectorImpl("dtmf-detector", 0, 40, 0, this.mediaScheduler);
        this.inbandDetectorComponent = new AudioComponent(8);
        this.inbandDetectorComponent.addOutput(this.dtmfDetector.getAudioOutput());
        this.inbandDetectorComponent.updateMode(true, true);
        this.mixer.addComponent(this.inbandDetectorComponent);

        this.oobDetectorComponent = new OOBComponent(9);
        this.oobDetectorComponent.addOutput(this.dtmfDetector.getOOBOutput());
        this.oobDetectorComponent.updateMode(true, true);
        this.oobMixer.addComponent(this.oobDetectorComponent);

        final DtmfListener dtmfListener = new DtmfListener();
        this.dtmfDetector.addListener(dtmfListener);

        // when
        this.mixer.start();
        this.oobMixer.start();
        this.dtmfDetector.activate();
        Thread.sleep(1000);

        URL pcap = DtmfRfc2833Test.class.getResource(filepath);
        player.play(pcap);

        // then
        Assert.assertTrue(player.isPlaying());
        Thread.sleep(rtpStreamDuration * 2);
        Assert.assertFalse(player.isPlaying());
        // Assert.assertEquals(totalPackets, player.countPacketsSent());
        // Assert.assertEquals(totalOctets, player.countOctetsSent());

        this.dtmfDetector.flushBuffer();
        Assert.assertEquals(1, dtmfListener.countTones());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testDetectHashThenHashFromPcap() throws Exception {
        // given
        // int rtpEventPacketCount = 72;
        // int rtpEventPacketLength = 24;
        // int rtpPacketCount = 429;
        // int rtpPacketLength = 180;
        // int totalOctets = (rtpEventPacketLength * rtpEventPacketCount) + (rtpPacketCount * rtpPacketLength);
        // int totalPackets = rtpEventPacketCount + rtpPacketCount;
        long rtpStreamDuration = 9000;
        InetSocketAddress localAddress = new InetSocketAddress("127.0.0.1", 64000);

        String filepath = "dtmf-oob-two-hash.cap.gz";
        PcapPacketEncoder packetEncoder = new PcapPacketEncoder();
        AsyncPcapChannelHandler channelInitializer = new AsyncPcapChannelHandler(packetEncoder);
        bootstrap.handler(channelInitializer);
        NettyNetworkChannelGlobalContext context = new NettyNetworkChannelGlobalContext(networkManager);
        channel = new AsyncPcapChannel(context);
        player = new PcapPlayer(channel, scheduler);

        FutureCallback<Void> openCallback = mock(FutureCallback.class);
        FutureCallback<Void> bindCallback = mock(FutureCallback.class);
        FutureCallback<Void> connectCallback = mock(FutureCallback.class);

        rtpChannel.bind(false, false);
        rtpChannel.connect(localAddress);
        SocketAddress remoteAddress = rtpChannel.getLocalAddress();
        rtpChannel.setFormatMap(AVProfile.audio);
        rtpChannel.updateMode(ConnectionMode.RECV_ONLY);

        channel.open(openCallback);
        verify(openCallback, timeout(100)).onSuccess(null);
        channel.bind(localAddress, bindCallback);
        verify(bindCallback, timeout(100)).onSuccess(null);
        channel.connect(remoteAddress, connectCallback);
        verify(connectCallback, timeout(100)).onSuccess(null);

        this.dtmfDetector = new DetectorImpl("dtmf-detector", 0, 40, 0, this.mediaScheduler);
        this.inbandDetectorComponent = new AudioComponent(8);
        this.inbandDetectorComponent.addOutput(this.dtmfDetector.getAudioOutput());
        this.inbandDetectorComponent.updateMode(true, true);
        this.mixer.addComponent(this.inbandDetectorComponent);

        this.oobDetectorComponent = new OOBComponent(9);
        this.oobDetectorComponent.addOutput(this.dtmfDetector.getOOBOutput());
        this.oobDetectorComponent.updateMode(true, true);
        this.oobMixer.addComponent(this.oobDetectorComponent);

        final DtmfListener dtmfListener = new DtmfListener();
        this.dtmfDetector.addListener(dtmfListener);

        // when
        this.mixer.start();
        this.oobMixer.start();
        this.dtmfDetector.activate();
        Thread.sleep(1000);

        URL pcap = DtmfRfc2833Test.class.getResource(filepath);
        player.play(pcap);

        // then
        Assert.assertTrue(player.isPlaying());
        Thread.sleep(rtpStreamDuration * 2);
        Assert.assertFalse(player.isPlaying());
        // Assert.assertEquals(totalPackets, player.countPacketsSent());
        // Assert.assertEquals(totalOctets, player.countOctetsSent());

        this.dtmfDetector.flushBuffer();
        Assert.assertEquals(2, dtmfListener.countTones());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testGigasetN510IpProRfc2833() throws Exception {
        // given
        // int rtpEventPacketCount = 70;
        // int rtpEventPacketLength = 24;
        // int rtpPacketCount = 2494;
        // int rtpPacketLength = 180;
        // int totalOctets = (rtpEventPacketLength * rtpEventPacketCount) + (rtpPacketCount * rtpPacketLength);
        // int totalPackets = rtpEventPacketCount + rtpPacketCount;
        long rtpStreamDuration = 50000;
        InetSocketAddress localAddress = new InetSocketAddress("127.0.0.1", 64000);

        String filepath = "gigaset-n510-ip-pro-rfc2833.pcap";
        PcapPacketEncoder packetEncoder = new PcapPacketEncoder();
        AsyncPcapChannelHandler channelInitializer = new AsyncPcapChannelHandler(packetEncoder);
        bootstrap.handler(channelInitializer);
        NettyNetworkChannelGlobalContext context = new NettyNetworkChannelGlobalContext(networkManager);
        channel = new AsyncPcapChannel(context);
        player = new PcapPlayer(channel, scheduler);

        FutureCallback<Void> openCallback = mock(FutureCallback.class);
        FutureCallback<Void> bindCallback = mock(FutureCallback.class);
        FutureCallback<Void> connectCallback = mock(FutureCallback.class);

        rtpChannel.bind(false, false);
        rtpChannel.connect(localAddress);
        SocketAddress remoteAddress = rtpChannel.getLocalAddress();
        rtpChannel.setFormatMap(AVProfile.audio);
        rtpChannel.updateMode(ConnectionMode.RECV_ONLY);

        channel.open(openCallback);
        verify(openCallback, timeout(100)).onSuccess(null);
        channel.bind(localAddress, bindCallback);
        verify(bindCallback, timeout(100)).onSuccess(null);
        channel.connect(remoteAddress, connectCallback);
        verify(connectCallback, timeout(100)).onSuccess(null);

        this.dtmfDetector = new DetectorImpl("dtmf-detector", 0, 100, 100, this.mediaScheduler);
        this.inbandDetectorComponent = new AudioComponent(8);
        this.inbandDetectorComponent.addOutput(this.dtmfDetector.getAudioOutput());
        this.inbandDetectorComponent.updateMode(true, true);
        this.mixer.addComponent(this.inbandDetectorComponent);

        this.oobDetectorComponent = new OOBComponent(9);
        this.oobDetectorComponent.addOutput(this.dtmfDetector.getOOBOutput());
        this.oobDetectorComponent.updateMode(true, true);
        this.oobMixer.addComponent(this.oobDetectorComponent);

        final DtmfListener dtmfListener = new DtmfListener();
        this.dtmfDetector.addListener(dtmfListener);

        // when
        this.mixer.start();
        this.oobMixer.start();
        this.dtmfDetector.activate();
        Thread.sleep(1000);

        URL pcap = DtmfRfc2833Test.class.getResource(filepath);
        player.play(pcap);

        // then
        Assert.assertTrue(player.isPlaying());
        Thread.sleep(rtpStreamDuration + 10000);
        Assert.assertFalse(player.isPlaying());
        // Assert.assertEquals(totalPackets, player.countPacketsSent());
        // Assert.assertEquals(totalOctets, player.countOctetsSent());

        this.dtmfDetector.flushBuffer();
        Assert.assertEquals(10, dtmfListener.countTones());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("2", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("2", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testCiscoSpa525G2InboundAudioForZendesk34432() throws Exception {
        // given
        long rtpStreamDuration = 11000;
        InetSocketAddress localAddress = new InetSocketAddress("127.0.0.1", 64000);

        String filepath = "cisco-spa-525G2-zendesk34432.pcap";
        PcapPacketEncoder packetEncoder = new PcapPacketEncoder();
        AsyncPcapChannelHandler channelInitializer = new AsyncPcapChannelHandler(packetEncoder);
        bootstrap.handler(channelInitializer);
        NettyNetworkChannelGlobalContext context = new NettyNetworkChannelGlobalContext(networkManager);
        channel = new AsyncPcapChannel(context);
        player = new PcapPlayer(channel, scheduler);

        FutureCallback<Void> openCallback = mock(FutureCallback.class);
        FutureCallback<Void> bindCallback = mock(FutureCallback.class);
        FutureCallback<Void> connectCallback = mock(FutureCallback.class);

        rtpChannel.bind(false, false);
        rtpChannel.connect(localAddress);
        SocketAddress remoteAddress = rtpChannel.getLocalAddress();
        rtpChannel.setFormatMap(AVProfile.audio);
        rtpChannel.updateMode(ConnectionMode.RECV_ONLY);

        channel.open(openCallback);
        verify(openCallback, timeout(100)).onSuccess(null);
        channel.bind(localAddress, bindCallback);
        verify(bindCallback, timeout(100)).onSuccess(null);
        channel.connect(remoteAddress, connectCallback);
        verify(connectCallback, timeout(100)).onSuccess(null);

        this.dtmfDetector = new DetectorImpl("dtmf-detector", -30, 100, 300, this.mediaScheduler);
        this.inbandDetectorComponent = new AudioComponent(8);
        this.inbandDetectorComponent.addOutput(this.dtmfDetector.getAudioOutput());
        this.inbandDetectorComponent.updateMode(true, true);
        this.mixer.addComponent(this.inbandDetectorComponent);

        this.oobDetectorComponent = new OOBComponent(9);
        this.oobDetectorComponent.addOutput(this.dtmfDetector.getOOBOutput());
        this.oobDetectorComponent.updateMode(true, true);
        this.oobMixer.addComponent(this.oobDetectorComponent);

        final DtmfListener dtmfListener = new DtmfListener();
        this.dtmfDetector.addListener(dtmfListener);

        // when
        this.mixer.start();
        this.oobMixer.start();
        this.dtmfDetector.activate();
        Thread.sleep(1000);

        URL pcap = DtmfRfc2833Test.class.getResource(filepath);
        player.play(pcap);

        // then
        Assert.assertTrue(player.isPlaying());
        Thread.sleep(rtpStreamDuration + 10000);
        Assert.assertFalse(player.isPlaying());

        this.dtmfDetector.flushBuffer();
        Assert.assertEquals(10, dtmfListener.countTones());
        Assert.assertEquals("6", dtmfListener.pollTone().getTone());
        Assert.assertEquals("6", dtmfListener.pollTone().getTone());
        Assert.assertEquals("8", dtmfListener.pollTone().getTone());
        Assert.assertEquals("8", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
        Assert.assertEquals("6", dtmfListener.pollTone().getTone());
        Assert.assertEquals("6", dtmfListener.pollTone().getTone());
        Assert.assertEquals("8", dtmfListener.pollTone().getTone());
        Assert.assertEquals("8", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testZendesk34401Rfc2833() throws Exception {
        // given
        // int rtpEventPacketCount = 70;
        // int rtpEventPacketLength = 24;
        // int rtpPacketCount = 2494;
        // int rtpPacketLength = 180;
        // int totalOctets = (rtpEventPacketLength * rtpEventPacketCount) + (rtpPacketCount * rtpPacketLength);
        // int totalPackets = rtpEventPacketCount + rtpPacketCount;
        long rtpStreamDuration = 3000;
        InetSocketAddress localAddress = new InetSocketAddress("127.0.0.1", 64000);

        String filepath = "zendesk-34401-rfc2833.pcap";
        PcapPacketEncoder packetEncoder = new PcapPacketEncoder();
        AsyncPcapChannelHandler channelInitializer = new AsyncPcapChannelHandler(packetEncoder);
        bootstrap.handler(channelInitializer);
        NettyNetworkChannelGlobalContext context = new NettyNetworkChannelGlobalContext(networkManager);
        channel = new AsyncPcapChannel(context);
        player = new PcapPlayer(channel, scheduler);

        FutureCallback<Void> openCallback = mock(FutureCallback.class);
        FutureCallback<Void> bindCallback = mock(FutureCallback.class);
        FutureCallback<Void> connectCallback = mock(FutureCallback.class);

        rtpChannel.bind(false, false);
        rtpChannel.connect(localAddress);
        SocketAddress remoteAddress = rtpChannel.getLocalAddress();
        rtpChannel.setFormatMap(AVProfile.audio);
        rtpChannel.updateMode(ConnectionMode.RECV_ONLY);

        channel.open(openCallback);
        verify(openCallback, timeout(100)).onSuccess(null);
        channel.bind(localAddress, bindCallback);
        verify(bindCallback, timeout(100)).onSuccess(null);
        channel.connect(remoteAddress, connectCallback);
        verify(connectCallback, timeout(100)).onSuccess(null);

        this.dtmfDetector = new DetectorImpl("dtmf-detector", 0, 100, 200, this.mediaScheduler);
        this.inbandDetectorComponent = new AudioComponent(8);
        this.inbandDetectorComponent.addOutput(this.dtmfDetector.getAudioOutput());
        this.inbandDetectorComponent.updateMode(true, true);
        this.mixer.addComponent(this.inbandDetectorComponent);

        this.oobDetectorComponent = new OOBComponent(9);
        this.oobDetectorComponent.addOutput(this.dtmfDetector.getOOBOutput());
        this.oobDetectorComponent.updateMode(true, true);
        this.oobMixer.addComponent(this.oobDetectorComponent);

        final DtmfListener dtmfListener = new DtmfListener();
        this.dtmfDetector.addListener(dtmfListener);

        // when
        this.mixer.start();
        this.oobMixer.start();
        this.dtmfDetector.activate();
        Thread.sleep(1000);

        URL pcap = DtmfRfc2833Test.class.getResource(filepath);
        player.play(pcap);

        // then
        Assert.assertTrue(player.isPlaying());
        Thread.sleep(rtpStreamDuration + 1000);
        Assert.assertFalse(player.isPlaying());
        // Assert.assertEquals(totalPackets, player.countPacketsSent());
        // Assert.assertEquals(totalOctets, player.countOctetsSent());

        this.dtmfDetector.flushBuffer();
        Assert.assertEquals(5, dtmfListener.countTones());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("2", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("1", dtmfListener.pollTone().getTone());
        Assert.assertEquals("#", dtmfListener.pollTone().getTone());
    }

    private class DtmfListener implements DtmfDetectorListener {

        private final Queue<DtmfEvent> tones;

        public DtmfListener() {
            this.tones = new ConcurrentLinkedQueue<>();
        }

        public int countTones() {
            return this.tones.size();
        }

        public DtmfEvent pollTone() {
            return tones.poll();
        }

        @Override
        public void process(DtmfEvent event) {
            this.tones.offer(event);

        }

    }

}

{'repo_name': 'RestComm/media-core', 'stars': '132', 'repo_language': 'Java', 'file_name': 'FormatsTest.java', 'mime_type': 'text/x-java', 'hash': -8715812266112676792, 'source_dataset': 'data'}


// This file can be replaced during build by using the `fileReplacements` array.
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const environment = {
  production: false
};

/*
 * In development mode, for easier debugging, you can ignore zone related error
 * stack frames such as `zone.run`/`zoneDelegate.invokeTask` by importing the
 * below file. Don't forget to comment it out in production mode
 * because it will have a performance impact when errors are thrown
 */
// import 'zone.js/dist/zone-error';  // Included with Angular CLI.

{'repo_name': 'theycallmemac/odin', 'stars': '128', 'repo_language': 'Go', 'file_name': 'main.go', 'mime_type': 'text/x-c', 'hash': -8730946926552161159, 'source_dataset': 'data'}


//
//  OALAudioTrack.h
//  ObjectAL
//
//  Created by Karl Stenerud on 10-08-21.
//
//  Copyright (c) 2009 Karl Stenerud. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall remain in place
// in this source code.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Attribution is not required, but appreciated :)
//

#import "ccMacros.h"

#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
#import <AVFoundation/AVFoundation.h>
#elif __CC_PLATFORM_ANDROID
#import <AndroidKit/AndroidMediaPlayer.h>
#import <AndroidKit/AndroidMediaPlayerOnCompletionListener.h>
#endif
#import "OALAction.h"
#import "OALAudioTrackNotifications.h"
#import "OALSuspendHandler.h"

/**
 * Plays an audio track via AVAudioPlayer.
 * Unlike AVAudioPlayer, however, it can be re-used to play another file.
 * Interruptions can be handled by OALAudioSupport (enabled by default).
 */
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
@interface OALAudioTrack : NSObject <AVAudioPlayerDelegate,OALSuspendManager>
#elif __CC_PLATFORM_ANDROID
BRIDGE_CLASS("com.spritebuilder.OALAudioTrack")
@interface OALAudioTrack : JavaObject <AndroidMediaPlayerOnCompletionListener,OALSuspendManager>
#endif
{
    /** If true, this track is recording metering data */
	bool meteringEnabled;
	bool interrupted;
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
	AVAudioPlayer* player;
#elif __CC_PLATFORM_ANDROID
    AndroidMediaPlayer *player;
#endif
	NSURL* currentlyLoadedUrl;
	bool preloaded;
	bool autoPreload;
	bool paused;
	bool muted;
#if __CC_PLATFORM_ANDROID
    bool suspended;
#endif
	float gain;
	float pan;
	NSInteger numberOfLoops;
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
	id<AVAudioPlayerDelegate> delegate; // Weak reference
#else
    id delegate;
#endif

	/** When the simulator is running (and the playback fix is in use),
	 * player will be copied to here, and then player set to nil.
	 * This prevents other code from inadvertently raising the volume
	 * and starting playback.
	 */
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
	AVAudioPlayer* simulatorPlayerRef;
#endif

	/** Operation queue for running asynchronous operations.
	 * Note: Only one asynchronous operation is allowed at a time.
	 */
	NSOperationQueue* operationQueue;

	/** If true, the audio player is currently playing.
	 * We need to maintain our own value because AVAudioPlayer will
	 * sometimes say it's not playing when it actually is.
	 */
	bool playing;
	NSTimeInterval currentTime;

	/** The current action being applied to gain. */
	OALAction* gainAction;

	/** The current action being applied to pan. */
	OALAction* panAction;

	/** Handles suspending and interrupting for this object. */
	OALSuspendHandler* suspendHandler;
}

#pragma mark Properties

/** The URL of the currently loaded audio data. */
@property(nonatomic,readonly,retain) NSURL* currentlyLoadedUrl;

/** Optional object that will receive notifications for decoding errors,
 * audio interruptions (such as an incoming phone call), and playback completion.

 * Note: OALAudioTrack keeps a WEAK reference to delegate, so make sure you clear it
 * when your object is going to be deallocated.
 */
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
@property(nonatomic,readwrite,assign) id<AVAudioPlayerDelegate> delegate;
#elif __CC_PLATFORM_ANDROID
@property(nonatomic,readwrite,assign) id delegate;
#endif

/** The gain (volume) for playback (0.0 - 1.0, where 1.0 = no attenuation). */
@property(nonatomic,readwrite,assign) float gain;

/** The volume (alias to gain) for playback (0.0 - 1.0, where 1.0 = no attenuation). */
@property(nonatomic,readwrite,assign) float volume;

/** Pan value (-1.0 = far left, 1.0 = far right).
 * Note: This will have no effect on iOS versions prior to 4.0.
 */
@property(nonatomic,readwrite,assign) float pan;

/** If true, audio track is muted */
@property(nonatomic,readwrite,assign) bool muted;

/** If true, automatically preload again when playback stops */
@property(nonatomic,readwrite,assign) bool autoPreload;

/** If true, audio track is in preloaded state */
@property(nonatomic,readonly,assign) bool preloaded;

/** The number of times to loop playback (-1 = forever).
 * Note: This value will be ignored, and get changed when you call the various playXX methods.
 * Only "play" will use the current value of "numberOfLoops".
 */
@property(nonatomic,readwrite,assign) NSInteger numberOfLoops;

/** If true, pause playback. */
@property(nonatomic,readwrite,assign) bool paused;

/** Access to the underlying AVAudioPlayer object.
 * WARNING: Be VERY careful when accessing this, as some methods could cause
 * it to fall out of sync with OALAudioTrack (particularly play/pause/stop methods).
 */
#if __CC_PLATFORM_IOS || __CC_PLATFORM_MAC
@property(nonatomic,readonly,retain) AVAudioPlayer* player;
#elif __CC_PLATFORM_ANDROID
@property(nonatomic,readonly,retain) AndroidMediaPlayer* player;
#endif

/** If true, background music is currently playing. */
@property(nonatomic,readonly,assign) bool playing;

/** The current playback position in seconds from the start of the sound.
 * You can set this to change the playback position, whether it is currently playing or not.
 */
@property(nonatomic,readwrite,assign) NSTimeInterval currentTime;

/** The value of this property increases monotonically while an audio player is playing or paused.

 *
 * If more than one audio player is connected to the audio output device, device time continues
 * incrementing as long as at least one of the players is playing or paused.

 *
 * If the audio output device has no connected audio players that are either playing or paused,
 * device time reverts to 0.

 *
 * Use this property to indicate “now” when calling the playAtTime: instance method. By configuring
 * multiple audio players to play at a specified offset from deviceCurrentTime, you can perform
 * precise synchronization—as described in the discussion for that method.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 */
@property(nonatomic,readonly,assign) NSTimeInterval deviceCurrentTime;

/** The duration, in seconds, of the currently loaded sound. */
@property(nonatomic,readonly,assign) NSTimeInterval duration;

/** The number of channels in the currently loaded sound. */
@property(nonatomic,readonly,assign) NSUInteger numberOfChannels;

#pragma mark Object Management

/** Create a new audio track.
 *
 * @return A new audio track.
 */
+ (id) track;

#pragma mark Playback

/** Preload the contents of a URL for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param url The URL containing the sound data.
 * @return TRUE if the operation was successful.
 */
- (bool) preloadUrl:(NSURL*) url;

/** Preload the contents of a URL for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param url The URL containing the sound data.
 * @param seekTime The position in the file to start playing at.
 * @return TRUE if the operation was successful.
 */
- (bool) preloadUrl:(NSURL*) url seekTime:(NSTimeInterval)seekTime;

/** Preload the contents of a file for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param path The file containing the sound data.
 * @return TRUE if the operation was successful.
 */
- (bool) preloadFile:(NSString*) path;

/** Preload the contents of a file for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param path The file containing the sound data.
 * @param seekTime The position in the file to start playing at.
 * @return TRUE if the operation was successful.
 */
- (bool) preloadFile:(NSString*) path seekTime:(NSTimeInterval)seekTime;

/** Asynchronously preload the contents of a URL for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param url The URL containing the sound data.
 * @param target the target to inform when preparation is complete.
 * @param selector the selector to call when preparation is complete.
 * @return TRUE if the operation was successfully queued.
 */
- (bool) preloadUrlAsync:(NSURL*) url target:(id) target selector:(SEL) selector;

/** Asynchronously preload the contents of a URL for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param url The URL containing the sound data.
 * @param seekTime The position in the file to start playing at.
 * @param target the target to inform when preparation is complete.
 * @param selector the selector to call when preparation is complete.
 * @return TRUE if the operation was successfully queued.
 */
- (bool) preloadUrlAsync:(NSURL*) url seekTime:(NSTimeInterval)seekTime target:(id) target selector:(SEL) selector;

/** Asynchronously preload the contents of a file for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param path The file containing the sound data.
 * @param target the target to inform when preparation is complete.
 * @param selector the selector to call when preparation is complete.
 * @return TRUE if the operation was successfully queued.
 */
- (bool) preloadFileAsync:(NSString*) path target:(id) target selector:(SEL) selector;

/** Asynchronously preload the contents of a file for playback.
 * Once the audio data is preloaded, you can call "play" to play it.

 *
 * @param path The file containing the sound data.
 * @param seekTime The position in the file to start playing at.
 * @param target the target to inform when preparation is complete.
 * @param selector the selector to call when preparation is complete.
 * @return TRUE if the operation was successfully queued.
 */
- (bool) preloadFileAsync:(NSString*) path seekTime:(NSTimeInterval)seekTime target:(id) target selector:(SEL) selector;

/** Play the contents of a URL once.
 *
 * @param url The URL containing the sound data.
 * @return TRUE if the operation was successful.
 */
- (bool) playUrl:(NSURL*) url;

/** Play the contents of a URL and loop the specified number of times.
 *
 * @param url The URL containing the sound data.
 * @param loops The number of times to loop playback (-1 = forever)
 * @return TRUE if the operation was successful.
 */
- (bool) playUrl:(NSURL*) url loops:(NSInteger) loops;

/** Play the contents of a file once.
 *
 * @param path The file containing the sound data.
 * @return TRUE if the operation was successful.
 */
- (bool) playFile:(NSString*) path;

/** Play the contents of a file and loop the specified number of times.
 *
 * @param path The file containing the sound data.
 * @param loops The number of times to loop playback (-1 = forever)
 * @return TRUE if the operation was successful.
 */
- (bool) playFile:(NSString*) path loops:(NSInteger) loops;

/** Play the contents of a URL asynchronously once.
 *
 * @param url The URL containing the sound data.
 * @param target the target to inform when playing has started.
 * @param selector the selector to call when playing has started.
 */
- (void) playUrlAsync:(NSURL*) url target:(id) target selector:(SEL) selector;

/** Play the contents of a URL asynchronously and loop the specified number of times.
 *
 * @param url The URL containing the sound data.
 * @param loops The number of times to loop playback (-1 = forever)
 * @param target the target to inform when playing has started.
 * @param selector the selector to call when playing has started.
 */
- (void) playUrlAsync:(NSURL*) url
				loops:(NSInteger) loops
			   target:(id) target
			 selector:(SEL) selector;

/** Play the contents of a file asynchronously once.
 *
 * @param path The file containing the sound data.
 * @param target the target to inform when playing has started.
 * @param selector the selector to call when playing has started.
 */
- (void) playFileAsync:(NSString*) path target:(id) target selector:(SEL) selector;

/** Play the contents of a file asynchronously and loop the specified number of times.
 *
 * @param path The file containing the sound data.
 * @param loops The number of times to loop playback (-1 = forever)
 * @param target the target to inform when playing has started.
 * @param selector the selector to call when playing has started.
 */
- (void) playFileAsync:(NSString*) path
				 loops:(NSInteger) loops
				target:(id) target
			  selector:(SEL) selector;

/** Play the currently loaded audio track.
 *
 * @return TRUE if the operation was successful.
 */
- (bool) play;

/** Plays a sound asynchronously, starting at a specified point in the audio output device’s timeline.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 *
 * @param time The time (device time) to start playing at.
 * @return YES if the playback was successfully scheduled.
 */
- (bool) playAtTime:(NSTimeInterval) time;

/** Plays the currently preloaded track asynchronously when the specified track completes.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 *
 * @param track The track to play after
 * @return YES if the playback was successfully scheduled.
 */
- (bool) playAfterTrack:(OALAudioTrack*) track;

/** Plays the currently preloaded track asynchronously when the specified track completes.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 *
 * @param track The track to play after
 * @param timeAdjust fine-tune value added to the time start offset.
 * @return YES if the playback was successfully scheduled.
 */
- (bool) playAfterTrack:(OALAudioTrack*) track timeAdjust:(NSTimeInterval) timeAdjust;

/** Stop playing and stop all operations.
 */
- (void) stop;

/** Fade to the specified gain value.
 *
 * @param gain The gain to fade to.
 * @param duration The duration of the fade operation in seconds.
 * @param target The target to notify when the fade completes (can be nil).
 * @param selector The selector to call when the fade completes.  The selector must accept
 * a single parameter, which will be the object that performed the fade.
 */
- (void) fadeTo:(float) gain
	   duration:(float) duration
		 target:(id) target
	   selector:(SEL) selector;

/** Stop the currently running fade operation, if any.
 */
- (void) stopFade;

/** Pan to the specified pan value.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 *
 * @param pan The value to pan to.
 * @param duration The duration of the pan operation in seconds.
 * @param target The target to notify when the pan completes (can be nil).
 * @param selector The selector to call when the pan completes.  The selector must accept
 * a single parameter, which will be the object that performed the pan.
 */
- (void) panTo:(float) pan
	   duration:(float) duration
		 target:(id) target
	   selector:(SEL) selector;

/** Stop the currently running pan operation, if any.
 *
 * Note: This will have no effect on iOS versions prior to 4.0.
 */
- (void) stopPan;

/** Stop any internal fade or pan actions. */
- (void) stopActions;

/** Unload and clear all audio data, stop playing, and stop all operations.
 */
- (void) clear;

#if __CC_PLATFORM_ANDROID
- (void) onCompletion:(AndroidMediaPlayer *)mp;
#endif

#pragma mark Metering

/** If true, metering is enabled. */
@property (nonatomic,readwrite,assign) bool meteringEnabled;

/** Updates the metering system to give current values.
 * You must call this method before calling averagePowerForChannel or peakPowerForChannel in
 * order to get current values.
 */
- (void) updateMeters;

/** Gives the average power for a given channel, in decibels, for the sound being played.
 * 0 dB indicates maximum power (full scale).

 * -160 dB indicates minimum power (near silence).

 * If the signal provided to the audio player exceeds full scale, then the value may be > 0.

 *
 * Note: The value returned is in reference to when updateMeters was last called.
 * You must call updateMeters again before calling this method to get a current value.
 *
 * @param channelNumber The channel to get the value from.  For mono or left, use 0.  For right,
 *        use 1.
 * @return the average power for the channel.
 */
- (float) averagePowerForChannel:(NSUInteger)channelNumber;

/** Gives the peak power for a given channel, in decibels, for the sound being played.
 * 0 dB indicates maximum power (full scale).

 * -160 dB indicates minimum power (near silence).

 * If the signal provided to the audio player exceeds full scale, then the value may be > 0.

 *
 * Note: The value returned is in reference to when updateMeters was last called.
 * You must call updateMeters again before calling this method to get a current value.
 *
 * @param channelNumber The channel to get the value from.  For mono or left, use 0.  For right,
 *        use 1.
 * @return the average power for the channel.
 */
- (float) peakPowerForChannel:(NSUInteger)channelNumber;

@end

{'repo_name': 'LearnCocos2D/LearnCocos2D', 'stars': '204', 'repo_language': 'Objective-C', 'file_name': 'ZAttributedStringPrivate.h', 'mime_type': 'text/x-objective-c', 'hash': 2380750195489013102, 'source_dataset': 'data'}


// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

package windows_test

import (
	"fmt"
	"internal/syscall/windows"
	"os"
	"os/exec"
	"syscall"
	"testing"
	"unsafe"
)

func TestRunAtLowIntegrity(t *testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
		wil, err := getProcessIntegrityLevel()
		if err != nil {
			fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
			os.Exit(9)
			return
		}
		fmt.Printf("%s", wil)
		os.Exit(0)
		return
	}

	cmd := exec.Command(os.Args[0], "-test.run=TestRunAtLowIntegrity", "--")
	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}

	token, err := getIntegrityLevelToken(sidWilLow)
	if err != nil {
		t.Fatal(err)
	}
	defer token.Close()

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Token: token,
	}

	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatal(err)
	}

	if string(out) != sidWilLow {
		t.Fatalf("Child process did not run as low integrity level: %s", string(out))
	}
}

const (
	sidWilLow = `S-1-16-4096`
)

func getProcessIntegrityLevel() (string, error) {
	procToken, err := syscall.OpenCurrentProcessToken()
	if err != nil {
		return "", err
	}
	defer procToken.Close()

	p, err := tokenGetInfo(procToken, syscall.TokenIntegrityLevel, 64)
	if err != nil {
		return "", err
	}

	tml := (*windows.TOKEN_MANDATORY_LABEL)(p)

	sid := (*syscall.SID)(unsafe.Pointer(tml.Label.Sid))

	return sid.String()
}

func tokenGetInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) {
	n := uint32(initSize)
	for {
		b := make([]byte, n)
		e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n)
		if e == nil {
			return unsafe.Pointer(&b[0]), nil
		}
		if e != syscall.ERROR_INSUFFICIENT_BUFFER {
			return nil, e
		}
		if n <= uint32(len(b)) {
			return nil, e
		}
	}
}

func getIntegrityLevelToken(wns string) (syscall.Token, error) {
	var procToken, token syscall.Token

	proc, err := syscall.GetCurrentProcess()
	if err != nil {
		return 0, err
	}
	defer syscall.CloseHandle(proc)

	err = syscall.OpenProcessToken(proc,
		syscall.TOKEN_DUPLICATE|
			syscall.TOKEN_ADJUST_DEFAULT|
			syscall.TOKEN_QUERY|
			syscall.TOKEN_ASSIGN_PRIMARY,
		&procToken)
	if err != nil {
		return 0, err
	}
	defer procToken.Close()

	sid, err := syscall.StringToSid(wns)
	if err != nil {
		return 0, err
	}

	tml := &windows.TOKEN_MANDATORY_LABEL{}
	tml.Label.Attributes = windows.SE_GROUP_INTEGRITY
	tml.Label.Sid = sid

	err = windows.DuplicateTokenEx(procToken, 0, nil, windows.SecurityImpersonation,
		windows.TokenPrimary, &token)
	if err != nil {
		return 0, err
	}

	err = windows.SetTokenInformation(token,
		syscall.TokenIntegrityLevel,
		uintptr(unsafe.Pointer(tml)),
		tml.Size())
	if err != nil {
		token.Close()
		return 0, err
	}
	return token, nil
}

{'repo_name': 'gcc-mirror/gcc', 'stars': '3986', 'repo_language': 'C', 'file_name': 'epiphany.opt', 'mime_type': 'text/plain', 'hash': 5419129668184257933, 'source_dataset': 'data'}


# Civetweb API Reference

### `mg_websocket_write( conn, opcode, data, data_len );`

### Parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
|**`conn`**|`struct mg_connection *`|Connection on which the data must be written|
|**`opcode`**|`int`|Opcode|
|**`data`**|`const char *`|Data to be written to the client|
|**`data_len`**|`size_t`|Length of the data|

### Return Value

| Type | Description |
| :--- | :--- |
|`int`|Number of bytes written or an error code|

### Description

The function `mg_websocket_write()` sends data to a websocket client wrapped in a websocket frame. The function issues calls to [`mg_lock_connection()`](mg_lock_connection.md) and [`mg_unlock_connection()`](mg_unlock_connection.md) to ensure that the transmission is not interrupted. Data corruption can otherwise happen if the application is proactively communicating and responding to a request simultaneously.

The function is available only when Civetweb is compiled with the `-DUSE_WEBSOCKET` option.

The function returns the number of bytes written, **0** when the connection has been closed and **-1** if an error occurred.

### See Also

* [`mg_lock_connection();`](mg_lock_connection.md)
* [`mg_printf();`](mg_printf.md)
* [`mg_unlock_connection();`](mg_unlock_connection.md)
* [`mg_websocket_client_write();`](mg_websocket_client_write.md)
* [`mg_write();`](mg_write.md)

{'repo_name': 'google/filament', 'stars': '9465', 'repo_language': 'C++', 'file_name': 'iOS.cmake', 'mime_type': 'text/plain', 'hash': 5857152721205984774, 'source_dataset': 'data'}


# Hexo-theme-obsidian

v1.x | ᴅᴇsɪɢɴᴇᴅ & ᴄᴏᴅᴇᴅ ʙʏ ᴛʀɪᴅɪᴀᴍᴏɴᴅ

> 一款暗色的 Hexo 主题, 拥有响应式布局, 简约而优雅.

![Latest Release Version](https://img.shields.io/github/v/release/TriDiamond/hexo-theme-obsidian)
![Latest Release Date](https://img.shields.io/github/release-date/TriDiamond/hexo-theme-obsidian)
![License](https://img.shields.io/github/license/TriDiamond/hexo-theme-obsidian)
[![Join the chat at https://gitter.im/TriDiamond/hexo-theme-obsidian](https://badges.gitter.im/TriDiamond/hexo-theme-obsidian.svg)](https://gitter.im/TriDiamond/hexo-theme-obsidian?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

**[预览](http://tridiamond.me)** | **[更变日志](https://github.com/TriDiamond/hexo-theme-obsidian/blob/master/CHANGELOG_CN.md)**

🇺🇸 **[English Doc](https://github.com/TriDiamond/hexo-theme-obsidian/blob/master/README.md)** |
**[ChangeLog](https://github.com/TriDiamond/hexo-theme-obsidian/blob/master/CHANGELOG.md)**

![screenshot](https://res.cloudinary.com/tridiamond/image/upload/v1573323147/blog/A-Obsidian-full_ubmo0d.png)

更多主题展示

## 分类页

![screenshot](https://res.cloudinary.com/tridiamond/image/upload/v1573148012/blog/A-Obsidian-categories_mgdti7.png)

## 多级分类

![screenshot](https://res.cloudinary.com/tridiamond/image/upload/v1573148016/blog/A-Obsidian-categories-level_xtxty9.png)

## 归档页

![screenshot](https://res.cloudinary.com/tridiamond/image/upload/v1573323148/blog/A-Obsidian-archives_ffpwf9.png)

## 文章页

![screenshot](https://res.cloudinary.com/tridiamond/image/upload/v1573148016/blog/A-Obsidian-articles_wlsu2v.png)

## 安装

```bash
$ git clone https://github.com/TriDiamond/hexo-theme-obsidian.git obsidian
```

## 使用

### 启用主题

打开 `Hexo` 配置文件 `_config.yml`, 设置主题为 `obsidian`

```yaml
---
theme: obsidian
```

### 安装主题需要的 NPM 依赖

首先打开你的终端，并且 `cd` 到主题 `themes/obsidian` 目录

```shell
cd themes/obsidian
```

然后执行 `npm` 命令，安装所有主题需要的依赖包

```shell
npm install
```

### 主题配置

打开 `/themes/obsidian/_config.yml` 文件可以改变主题配置

详细配置文件，点击展开

```yaml
#! ---------------------------------------------------------------
#! 版本`v1.3.5`开始代码高亮已经用`codemirror`替换了`highlight.js`，
#! 但是Hexo默认的highlight配置还是需要关闭的。
#! ！！所以务必把Hexo默认的highlight配置改为`enable: false` ！！
#! ---------------------------------------------------------------
#! highlight:
#!  enable: false
#!  line_number: true
#!  auto_detect: true
#!  tab_replace:
#! ---------------------------------------------------------------

# ---------------------------------------------------------------
# 主题默认设置
# ---------------------------------------------------------------

# 菜单设置 | 格式 = 菜单名: 菜单url
menu:
  PAGE: /page

# 分类页和标签页自定义标题配置
page_titles:
  categories: 'Categories'
  tags: 'Tags'
  archives: 'Archived'

# 是否启用目录
TOC: true

# 首页封面使用的封面图， 不配置默认使用cover配置的图片
welcome_cover: /img/cover.jpg

# 文章默认封面图
cover: /img/welcome-cover.jpg

# 文章内的默认头像
avatar: https://s2.ax1x.com/2019/09/19/nLtSiD.png

# 关闭默认滚动条
scrollbar: true

# 网站的关键词，都好分割，用于SEO优化
keywords: TriDiamond Obsidian

# 网站口号
descriptionOne: 'Think like an artist, develop like an artisan'
descriptionTwo: '艺术家思维去思考问题，工匠创造精神去开发'

# 如果使用google analytics, 请填写ID
google_analytics:

# 网页图标
favicon: /img/favicon.png

# rss文件
rss: atom.xml

# ---------------------------------------------------------------
# 文章音乐设置
# ---------------------------------------------------------------

# 自动播放音乐
autoplay: false

# 默认mp3文件
mp3:
  - statics/chengdu.mp3

# ---------------------------------------------------------------
# 主题插件
# ---------------------------------------------------------------

# Gitalk 评论插件
# 查看 https://github.com/gitalk/gitalk
gitalk:
  autoExpand: false
  clientID: ''
  clientSecret: ''
  repo: ''
  owner: ''
  admin: ['']
  # Ensure uniqueness and length less than 50
  id: location.pathname
  # Facebook-like distraction

# Valine 评论插件 (推荐使用!)
# 查看 https://valine.js.org/quickstart.html
valine:
  enable: true
  app_id:
  app_key:
  notify: false
  verify: false
  avatar: 'mp'
  placeholder: 'Leave your throughs behind~'
  visitor: true

# 文章字数和阅读时间统计插件
# see https://github.com/theme-next/hexo-symbols-count-time
symbols_count_time:
  enable: true
  wordCount: true
  readCount: true
  awl: 4
  wpm: 275
  suffix: mins.

# html截取插件（用于首页截取内容）
# see https://github.com/TriDiamond/hexo-html-truncate
html_truncate:
  enable: true
  # 文章保留多少个字符
  postLength: 250
  # 封面文章保留多少个字符
  coverLength: 100
  # 省略符号
  ellipsis: '...'
  # 需要过滤的html标签
  excludes: ['img']
  # 截取时保留空白空格字符
  keepWhitespaces: true
  # 截取到最后的时候保留完成的字（只对英文有用）
  reserveLastWord: true

# Busuanzi 浏览量统计插件
# see http://ibruce.info/2015/04/04/busuanzi/
busuanzi:
  enable: true

# Sharejs 分享
# see https://github.com/overtrue/share.js/
sharejs:
  enable: true
  disabled: 'facebook,douban,linkedin,diandian,tencent,google'

# 使用了codemirror替换了highlight.js，代码高亮更加完善，也更接近IDE的高亮样式
# 默认已经填入了一些语言的mode支持，如果你需要其他语言的支持，请查看codemirror官网的mode
# modes文档请看: https://codemirror.net/mode/
# codemirror官网： https://codemirror.net/
# 默认支持了：JS, HTML, CSS, PHP, JAVA, C, C#, C++, SHELL, PYTHON.
codemirror:
  modes: ['javascript', 'css', 'xml', 'htmlmixed', 'clike', 'php', 'shell', 'python']

# 启用 mathjax 支持
mathjax: true
```

### 评论插件

评论插件可以选择使用 `Valine` 或者 `Gitalk`

- 如果你是使用 `Valine`, 你需要关闭 `busuanzi`, 因为 Valine 自带有文章浏览量统计.
- 如果你是使用 `Gitalk`, 你可以打开 `busuanzi` 文章详情页就会显示文章浏览量统计.

### 代码块样式

> 版本`v1.3.5`开始代码高亮已经用`codemirror`替换了`highlight.js`，
> 但是 Hexo 默认的 highlight 配置还是需要关闭的。
> ！！所以无比把 Hexo 默认的 highlight 配置改为`enable: flase` ！！

在博客根目录的`_config.yml`修改

> ⚠ 注意不是主题里面的`_config.yml`，在主题里面加这个是无效的哦

```yaml
---
highlight:
  enable: false
  line_number: true
  auto_detect: true
  tab_replace:
```

Codemirror 代码高亮配置

```yaml
# 使用了codemirror替换了highlight.js，代码高亮更加完善，也更接近IDE的高亮样式
# 默认已经填入了一些语言的mode支持，如果你需要其他语言的支持，请查看codemirror官网的mode
# modes文档请看: https://codemirror.net/mode/
# codemirror官网： https://codemirror.net/
# 默认支持了：JS, HTML, CSS, PHP, JAVA, C, C#, C++, SHELL, PYTHON.
codemirror:
  modes: ['javascript', 'css', 'xml', 'htmlmixed', 'clike', 'php', 'shell', 'python']
```

修改了默认 highlight 配置后需要重新生成文件

```bash
hexo clean && hexo g
```

### 文章展示字符数控制

文章里面的参数`preview`控制在首页展示时保留的字符数

```markdown
title: My awesome title
date: 2019-07-14 18:38:45
categories: - Category1 - Category2
tags: - Tag1 - Tag2
mp3: http://domain.com/awesome.mp3
cover: http://domain.com/awesome.jpg
preview: 300
```

### 文章模版

文章模版设置

```markdown
title: My awesome title
date: 2019-07-14 18:38:45
categories: - 分类 1 - 分类 2
tags: - 标签 1 - 标签 2
mp3: http://domain.com/awesome.mp3
cover: http://domain.com/awesome.jpg
```

### 创建分类页

运行 Hexo 命令

```bash
hexo new page categories
```

分类模版

```yaml
title: categories
date: 2019-07-14 12:39:04
type: 'categories'
```

> 主题会自动生成分类内容，模版里面留空不用改动就可以了。

### 创建标签页

运行 Hexo 命令

```bash
hexo new page tags
```

标签模版

```yaml
title: tags
date: 2014-12-22 12:39:04
type: 'tags'
```

> 主题会自动生成标签内容，模版里面留空不用改动就可以了。

### MathJax 支持

默认是启用 MathJax 支持的, 如果需要关闭改变主题配置为 `false`。

```yaml
# 启用 mathjax 支持
mathjax: true
```

## 更新主题

> 更新前请先备份主题里的 `_config.yml` 文件

```bash
cd themes/osidian
git pull
```

## 使用搜索功能

### 安装说明

NPM 安装

```bash
$ npm install hexo-generator-search --save
```

在你的根目录配置 `_config.yml` 里面添加 hexo-generator-search 的配置

```yaml
search:
  path: search.xml
  field: post
  content: true
```

重新生成静态文件

```bash
hexo clean && hexo g
```

## 相关

做了一个 [`Typro`](https://typora.io/) 主题 [`Obsidian`](https://github.com/TriDiamond/typro-theme-obsidian) 专门给写博客的你们.

## 反馈

> 大家记得先看一下[ISSUE](https://github.com/TriDiamond/hexo-theme-obsidian/issues)里面有没有你的问题，已经解答了的。
> 很有可能你的问题已经被问过了，或者可以在 Issue 里面就找到答案了！谢谢配合！

可以通过以下方式反馈问题：

- [创建新 issue!](https://github.com/TriDiamond/hexo-theme-obsidian/issues/new)
- 加入 QQ 群 `909955326`
- [加入 Telegram 群](https://t.me/joinchat/R2m4eho2lbcHLR7nDvxd6A)

{'repo_name': 'TriDiamond/hexo-theme-obsidian', 'stars': '343', 'repo_language': 'JavaScript', 'file_name': 'it.yml', 'mime_type': 'text/plain', 'hash': -6559814482837217247, 'source_dataset': 'data'}


package test.tck.msgflow.callflows.prack;

public class TcpPrackTest extends UdpPrackTest {
    boolean myFlag;

    public void setUp() throws Exception {
        super.testedImplFlag = !myFlag;
        myFlag = !super.testedImplFlag;
        super.transport = "tcp";
        super.setUp();
    }
}

{'repo_name': 'usnistgov/jsip', 'stars': '161', 'repo_language': 'Java', 'file_name': 'jain-sip-ri-1.2.pom', 'mime_type': 'text/plain', 'hash': -3225406765130635161, 'source_dataset': 'data'}