Example #1
0
bool Movement::push_out()
{
    if (!back_col && collisions.empty())
        return true;
    int src_x = old_x;
    int src_y = old_y;
    int dst_x = instance->x;
    int dst_y = instance->y;

    int x = (dst_x+src_x)/2;
    int y = (dst_y+src_y)/2;
    int old_x, old_y;

    while (true) {
        if (test_position(x, y)) {
            dst_x = old_x = x;
            dst_y = old_y = y;
            x = (src_x+dst_x)/2;
            y = (src_y+dst_y)/2;
            if (x != old_x || y!=old_y)
                continue;
            if (src_x != dst_x || src_y != dst_y) {
                if (!test_position(src_x, src_y)) {
                    instance->set_position(src_x, src_y);
                    return true;
                }
            }
            instance->set_position(x, y);
            return false;
        } else {
            src_x = old_x = x;
            src_y = old_y = y;
            x = (src_x+dst_x)/2;
            y = (src_y+dst_y)/2;
            if (x != old_x || y != old_y)
                continue;
            if (src_x != dst_x || src_y != dst_y) {
                if (!test_position(dst_x, dst_y)) {
                    x = dst_x;
                    y = dst_y;
                }
            }
            instance->set_position(x, y);
            return true;
        }
    }
    return false;
}
Example #2
0
void BallMovement::bounce(bool collision)
{
    fix_position();

    float angle = rad(instance->direction * 11.25f);
    float found_a = -1.0f;
    for (float a = 0.0f; a < (CHOW_PI*2.0f); a += (CHOW_PI*2.0f) / 16.0f) {
        float x_move = 10.0f * cos(angle + a);
        float y_move = -10.0f * sin(angle + a);

        int x = instance->x + x_move;
        int y = instance->y + y_move;

        if (!test_position(x, y)) {
            found_a = a;
            break;
        }
    }

    if (found_a == -1.0f) {
        instance->set_direction((instance->direction + 16) % 32, false);
        return;
    }

    angle += found_a * 2.0f;
    if (angle > 2.0 * CHOW_PI)
        angle -= 2.0 * CHOW_PI;

    instance->set_direction(deg(angle) / 11.25f, false);
}
Example #3
0
static int	ft_resolve(t_tetri *tetri, char map[50][50], int letter, int size)
{
	int		i;

	if (!tetri)
		return (1);
	tetri->x = 0;
	while (tetri->x < size)
	{
		tetri->y = 0;
		while (tetri->y < size)
		{
			if (test_position(tetri, map, size))
			{
				ft_valid_pos(tetri, map, letter, size);
				if (ft_resolve(tetri->next, map, letter + 1, size))
					return (1);
				i = 0;
				ft_delete(map, letter, size);
			}
			tetri->y++;
		}
		tetri->x++;
	}
	return (0);
}
Example #4
0
static void
scroll_both_realize (ScrollFixture *fixture,
		     GtkTreePath   *path,
		     gboolean       use_align,
		     gdouble        row_align)
{
	GtkTreePath *end;

	gtk_widget_show_all (fixture->window);

	/* Scroll to end */
	end = gtk_tree_path_new_from_indices (999, -1);

	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view), end,
				  NULL, FALSE);
	gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fixture->tree_view),
				      end, NULL,
				      use_align, row_align, 0.0);
	gtk_tree_path_free (end);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	/* Scroll to final position */
	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view), path,
				  NULL, FALSE);
	gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fixture->tree_view),
				      path, NULL,
				      use_align, row_align, 0.0);

        ensure_layout ();
	test_position (GTK_TREE_VIEW (fixture->tree_view), path,
		       use_align, row_align);
}
Example #5
0
int main(int argc, char **argv)
{
    int rval = 0;
    printf("Testing read functions ... ");
    rval = test_read();
    if (rval != 0) {
        fprintf(stderr, "FAILED!\n");
        return (-1);
    } else {
        printf("passed!\n");
    }

    printf("Testing skip functions ... ");
    rval = test_skip();
    if (rval != 0) {
        fprintf(stderr, "FAILED!\n");
        return (-1);
    } else {
        printf("passed!\n");
    }

    printf("Testing position functions ... ");
    rval = test_position();
    if (rval != 0) {
        fprintf(stderr, "FAILED!\n");
        return (-1);
    } else {
        printf("passed!\n");
    }
 
    return (0);
}
Example #6
0
static void
scroll_new_row (ScrollFixture *fixture,
		gconstpointer  test_data)
{
	GtkTreeIter scroll_iter;
	GtkTreePath *scroll_path;
	GtkTreeModel *model;
	GList *renderers;
	GtkTreeViewColumn *column;
	GtkWidget *editable;

	/* The aim of this test is creating a new row at several places,
	 * and immediately put the cursor on it.  TreeView should correctly
	 * scroll to the row and show the editable widget.
	 *
	 * See #81627.
	 */

	g_test_bug ("81627");

	gtk_widget_show_all (fixture->window);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	/* Create the new row and scroll to it */
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (fixture->tree_view));
	create_new_row (GTK_LIST_STORE (model), GPOINTER_TO_INT (test_data),
			&scroll_iter);

	/* Set up a signal handler to acquire the editable widget */
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (fixture->tree_view), 0);
	renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));

	g_signal_connect (G_OBJECT (renderers->data), "editing-started",
			  G_CALLBACK (scroll_new_row_editing_started),
			  &editable);

	/* Now set the cursor on the path and start editing */
	scroll_path = gtk_tree_model_get_path (model, &scroll_iter);
	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view),
				  scroll_path,
				  column,
				  TRUE);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	/* Test position */
	test_position (GTK_TREE_VIEW (fixture->tree_view), scroll_path,
		       FALSE, 0.0);
	test_editable_position (fixture->tree_view, editable, scroll_path);

	gtk_tree_path_free (scroll_path);
}
Example #7
0
static int childprocess_unittest(void)
{
   resourceusage_t   usage = resourceusage_FREE;
   display_t         disp  = display_FREE;
   window_t          win   = window_FREE;
   window_evh_t      evhandler = window_evh_INIT_NULL;
   EGLContext        eglcontext = EGL_NO_CONTEXT;

   // prepare
   TEST(0 == initdefault_display(&disp))
   TEST(0 == init_test_window(&win, &eglcontext, &disp, &evhandler));

   if (test_transparentalpha(&disp))   goto ONERR;

   TEST(0 == init_resourceusage(&usage));

   if (test_initfree(&disp))           goto ONERR;

   acceptleak_helper(&usage);
   TEST(0 == same_resourceusage(&usage));
   TEST(0 == free_resourceusage(&usage));

   WAITFOR(&disp, false);
   size_t    logsize;
   uint8_t * logbuffer;
   GETBUFFER_ERRLOG(&logbuffer, &logsize);
   for (unsigned i = 0; i <= 2; ++i) {
      TEST(0 == init_resourceusage(&usage));

      if (test_showhide(&win, &disp))     goto ONERR;
      if (test_position(&win, &disp))     goto ONERR;
      if (test_resize(&win, &disp))       goto ONERR;

      WAITFOR(&disp, false);
      if (0 == same_resourceusage(&usage)) break;
      TEST(0 == free_resourceusage(&usage));
      TRUNCATEBUFFER_ERRLOG(logsize);
   }
   TEST(0 == same_resourceusage(&usage));
   TEST(0 == free_resourceusage(&usage));

   // unprepare
   TEST(0 == free_window(&win));
   TEST(0 == free_display(&disp));

   return 0;
ONERR:
   (void) free_resourceusage(&usage);
   (void) free_window(&win);
   (void) free_display(&disp);
   return EINVAL;
}
Example #8
0
int main(void)
{
	long long seed = time(NULL);
	printf("(seed=%llu)\n", seed);
	srand(seed);

	test_get_set();
	test_position();
	test_ensemble_position();
	test_plateau();
	test_chaines();
	test_coup();

	return EXIT_SUCCESS;
}
Example #9
0
static void
scroll (ScrollFixture *fixture,
	GtkTreePath   *path,
	gboolean       use_align,
	gdouble        row_align)
{
	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view), path,
				  NULL, FALSE);
	gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fixture->tree_view),
				      path, NULL,
				      use_align, row_align, 0.0);

	gtk_widget_show_all (fixture->window);

        ensure_layout ();
	test_position (GTK_TREE_VIEW (fixture->tree_view), path,
		       use_align, row_align);
}
Example #10
0
static void
scroll (ScrollFixture *fixture,
	GtkTreePath   *path,
	gboolean       use_align,
	gdouble        row_align)
{
	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view), path,
				  NULL, FALSE);
	gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (fixture->tree_view),
				      path, NULL,
				      use_align, row_align, 0.0);

	gtk_widget_show_all (fixture->window);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	test_position (GTK_TREE_VIEW (fixture->tree_view), path,
		       use_align, row_align);
}
Example #11
0
bool Movement::fix_position()
{
    if (push_out())
        return true;

    int table_index = (instance->direction/4) * 16;

    for (int i = 0; i < 8; i++) {
        int x = instance->x + fix_pos_table[table_index]*2;
        int y = instance->y + fix_pos_table[table_index+1]*2;
        table_index += 2;
        if (test_position(x, y))
            continue;
        instance->set_position(x, y);
        return true;
    }

    instance->set_position(old_x, old_y);
    return false;
}
Example #12
0
void test_procedure()
{
    if (!uci.engine_initialized)
        init_engine(position);

    assert(test_bitscan());
	assert(test_bittwiddles());
    assert(test_fen());
    assert(test_genmove());
    assert(test_make_unmake());
    assert(test_hash());
    assert(test_eval());
    assert(test_capture_gen());
    assert(test_check_gen());
    assert(test_alt_move_gen());
    assert(test_see());
    assert(test_position());
	assert(test_hash_table());
	assert(test_ep_capture());
	assert(test_book());
    test_search();
}
Example #13
0
void EightDirections::stop(bool collision)
{
    // set_speed(0);
    if (!collision) {
        return;
    }

    // float angle = rad(instance->direction * 11.25);

    // int x, y;
    // float angle2;

    // for (float a = rad(90); a <= rad(180); a += rad(90) / 8.0f) {
    //     const float d = 8.0f;
    //     angle2 = angle + a;
    //     x = instance->x + cos(angle2) * d;
    //     y = instance->y - sin(angle2) * d;
    //     if (!test_position(x, y)) {
    //         instance->set_position(x, y);
    //         return;
    //     }
    //     angle2 = angle - a;
    //     x = instance->x + cos(angle2) * d;
    //     y = instance->y - sin(angle2) * d;
    //     if (!test_position(x, y)) {
    //         instance->set_position(x, y);
    //         return;
    //     }
    // }

    // int dir1 = instance->direction + 6;
    // int dir2 = instance->direction - 6;

    // int x, y;
    // float add_x, add_y;

    // get_dir(dir1, add_x, add_y);
    // add_x *= last_move;
    // add_y *= last_move;
    // x = old_x + add_x;
    // y = old_y + add_y;
    // if (!test_position(x, y)) {
    //     instance->set_position(x, y);
    //     return;
    // }

    // get_dir(dir2, add_x, add_y);
    // add_x *= last_move;
    // add_y *= last_move;
    // x = old_x + add_x;
    // y = old_y + add_y;
    // if (!test_position(x, y)) {
    //     instance->set_position(x, y);
    //     return;
    // }

    if (!test_position(old_x, instance->y)) {
        instance->set_position(old_x, instance->y);
        return;
    }

    if (!test_position(instance->x, old_y)) {
        instance->set_position(instance->x, old_y);
        return;
    }

    fix_position();
}
Example #14
0
bool Movement::test_offset(float x, float y)
{
    return test_position(int(instance->x + x), int(instance->y + y));
}
Example #15
0
void BallMovement::bounce(bool collision)
{
    if (stop_speed != 0)
        return;
#ifdef CHOWDREN_IS_AVGN
    fix_position();

    int direction = instance->direction;

    float angle = rad(direction * 11.25f);

    float found_a = -1.0f;
    for (float a = 0.0f; a < (CHOW_PI*2.0f); a += (CHOW_PI*2.0f) / 16.0f) {
        float x_move = 10.0f * cos(angle + a);
        float y_move = -10.0f * sin(angle + a);

        int x = instance->x + x_move;
        int y = instance->y + y_move;

        if (!test_position(x, y)) {
            found_a = a;
            break;
        }
    }

    if (found_a == -1.0f) {
        instance->set_direction((instance->direction + 16) % 32, false);
        return;
    }

    angle += found_a * 2.0f;
    if (angle > 2.0 * CHOW_PI)
        angle -= 2.0 * CHOW_PI;

    instance->set_direction(deg(angle) / 11.25f, false);

    if (back_col)
        instance->flags &= ~REPEAT_BACK_COLLISION;
    else
        instance->collision_flags = 0;
#else
    add_x = add_y = 0;

    if (collision) {
        if (back_col)
            has_back_col = true;
        push_out();
    }

    int x = instance->x;
    int y = instance->y;
    x -= 8;
    y -= 8;
    int rebond = 0;
    if (test_position(x, y))
        rebond |= 0x01;
    x += 16;
    if (test_position(x, y))
        rebond |= 0x02;
    y += 16;
    if (test_position(x, y))
        rebond |= 0x04;
    x -= 16;
    if (test_position(x, y))
        rebond |= 0x08;
    int value = rebond_list[rebond * 32 + instance->direction];
    if (test_direction(value, 8)) {
        int angles = 4;
        int angles2 = angles;
        bool is_free = false;
        while (true) {
            value -= angles;
            value &= 31;
            if (!test_direction(value, 8)) {
                is_free = true;
                break;
            }
            value += 2 * angles;
            value &= 31;
            if (!test_direction(value, 8)) {
                is_free = true;
                break;
            }
            value -= angles;
            value &= 31;
            angles += angles2;
            if (angles <= 16)
                break;
        }
        if (!is_free)
            value = randrange(32);
    }

    int rnd = randrange(100);
    if (rnd < randomizer) {
        rnd >>= 2;
        if (rnd < 25) {
            rnd -= 12;
            rnd &= 31;
            if (!test_direction(rnd, 8))
                value = rnd;
        }
    }
Example #16
0
static void test_midiStream(UINT udev, HWND hwnd)
{
    HMIDISTRM hm;
    MMRESULT rc, rc2;
    MIDIHDR mhdr;
    union {
        MIDIPROPTEMPO tempo;
        MIDIPROPTIMEDIV tdiv;
    } midiprop;

    if (hwnd)
        rc = midiStreamOpen(&hm, &udev, 1, (DWORD_PTR)hwnd, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    else
        rc = midiStreamOpen(&hm, &udev, 1, (DWORD_PTR)callback_func, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION);
    if (rc == MMSYSERR_NOTSUPPORTED)
    {
        skip( "MIDI stream not supported\n" );
        return;
    }
    ok(!rc, "midiStreamOpen(dev=%d) rc=%s\n", udev, mmsys_error(rc));
    if (rc) return;

    test_notification(hwnd, "midiStreamOpen", MOM_OPEN, 0);

    midiprop.tempo.cbStruct = sizeof(midiprop.tempo);
    rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET|MIDIPROP_TEMPO);
    ok(!rc, "midiStreamProperty TEMPO rc=%s\n", mmsys_error(rc));
    ok(midiprop.tempo.dwTempo==500000, "default stream tempo %u microsec per quarter note\n", midiprop.tempo.dwTempo);

    midiprop.tdiv.cbStruct = sizeof(midiprop.tdiv);
    rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET|MIDIPROP_TIMEDIV);
    ok(!rc, "midiStreamProperty TIMEDIV rc=%s\n", mmsys_error(rc));
    todo_wine ok(24==LOWORD(midiprop.tdiv.dwTimeDiv), "default stream time division %u\n", midiprop.tdiv.dwTimeDiv);

    memset(&mhdr, 0, sizeof(mhdr));
    mhdr.dwFlags = 0;
    mhdr.dwUser   = 0x56FA552C;
    mhdr.dwOffset = 1234567890;
    mhdr.dwBufferLength = sizeof(strmEvents);
    mhdr.dwBytesRecorded = mhdr.dwBufferLength;
    mhdr.lpData = (LPSTR)&strmEvents[0];
    if (mhdr.lpData) {
        rc = midiOutLongMsg((HMIDIOUT)hm, &mhdr, sizeof(mhdr));
        ok(rc==MIDIERR_UNPREPARED, "midiOutLongMsg unprepared rc=%s\n", mmsys_error(rc));
        test_notification(hwnd, "midiOutLong unprepared", 0, WHATEVER);

        rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset)-1);
        ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare tiny rc=%s\n", mmsys_error(rc));
        rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutPrepare old size rc=%s\n", mmsys_error(rc));
        ok(mhdr.dwFlags & MHDR_PREPARED, "MHDR.dwFlags when prepared %x\n", mhdr.dwFlags);

        /* The device is still in paused mode and should queue the message. */
        rc = midiStreamOut(hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiStreamOut old size rc=%s\n", mmsys_error(rc));
        rc2 = rc;
        trace("MIDIHDR flags=%x when submitted\n", mhdr.dwFlags);
        /* w9X/me does not set MHDR_ISSTRM when StreamOut exits,
         * but it will be set on all systems after the job is finished. */

        Sleep(90);
        /* Wine <1.1.39 started playing immediately */
        test_notification(hwnd, "midiStream still paused", 0, WHATEVER);

    /* MSDN asks to use midiStreamRestart prior to midiStreamOut()
     * because the starting state is 'pause', but some apps seem to
     * work with the inverse order: queue everything, then play.
     */

        rc = midiStreamRestart(hm);
        ok(!rc, "midiStreamRestart rc=%s\n", mmsys_error(rc));

        if (!rc2) while(mhdr.dwFlags & MHDR_INQUEUE) {
            trace("async MIDI still queued\n");
            Sleep(100);
        } /* Checking INQUEUE is not the recommended way to wait for the end of a job, but we're testing. */
        /* MHDR_ISSTRM is not necessarily set when midiStreamOut returns
         * rather than when the queue is eventually processed. */
        ok(mhdr.dwFlags & MHDR_ISSTRM, "MHDR.dwFlags %x no ISSTRM when out of queue\n", mhdr.dwFlags);
        if (!rc2) while(!(mhdr.dwFlags & MHDR_DONE)) {
            /* Never to be seen except perhaps on multicore */
            trace("async MIDI still not done\n");
            Sleep(100);
        }
        ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags %x not DONE when out of queue\n", mhdr.dwFlags);
        test_notification(hwnd, "midiStream callback", MOM_POSITIONCB, (DWORD_PTR)&mhdr);
        test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr);

        /* Native fills dwOffset regardless of the cbMidiHdr size argument to midiStreamOut */
        ok(1234567890!=mhdr.dwOffset, "play left MIDIHDR.dwOffset at %u\n", mhdr.dwOffset);

        rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
        rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutUnprepare #2 rc=%s\n", mmsys_error(rc));

        trace("MIDIHDR stream flags=%x when finished\n", mhdr.dwFlags);
        ok(mhdr.dwFlags & MHDR_DONE, "MHDR.dwFlags when done %x\n", mhdr.dwFlags);

        test_position(hm, TIME_MS,      TIME_MS);
        test_position(hm, TIME_TICKS,   TIME_TICKS);
        todo_wine test_position(hm, TIME_MIDI,    TIME_MIDI);
        test_position(hm, TIME_SMPTE,   TIME_MS);
        test_position(hm, TIME_SAMPLES, TIME_MS);
        test_position(hm, TIME_BYTES,   TIME_MS);

        Sleep(400); /* Hear note */

        midiprop.tempo.cbStruct = sizeof(midiprop.tempo);
        rc = midiStreamProperty(hm, (void*)&midiprop, MIDIPROP_GET|MIDIPROP_TEMPO);
        ok(!rc, "midiStreamProperty TEMPO rc=%s\n", mmsys_error(rc));
        ok(0x0493E0==midiprop.tempo.dwTempo, "stream set tempo %u\n", midiprop.tdiv.dwTimeDiv);

        rc = midiStreamRestart(hm);
        ok(!rc, "midiStreamRestart #2 rc=%s\n", mmsys_error(rc));

        mhdr.dwFlags |= MHDR_ISSTRM;
        /* Preset flags (e.g. MHDR_ISSTRM) do not disturb. */
        rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutPrepare used flags %x rc=%s\n", mhdr.dwFlags, mmsys_error(rc));
        rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, offsetof(MIDIHDR,dwOffset));
        ok(!rc, "midiOutUnprepare used flags %x rc=%s\n", mhdr.dwFlags, mmsys_error(rc));

        rc = midiStreamRestart(hm);
        ok(!rc, "midiStreamRestart #3 rc=%s\n", mmsys_error(rc));
    }
    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);
    ok(0==((MIDISHORTEVENT*)&strmEvents)[0].dwStreamID, "dwStreamID set to %x\n", ((LPMIDIEVENT)&strmEvents[0])->dwStreamID);

    /* dwBytesRecorded controls how much is played, not dwBufferLength
     * allowing to immediately forward packets from midiIn to midiOut */
    mhdr.dwOffset = 1234123123;
    mhdr.dwBufferLength = sizeof(strmNops);
    trace("buffer: %u\n", mhdr.dwBufferLength);
    mhdr.dwBytesRecorded = 0;
    mhdr.lpData = (LPSTR)&strmNops[0];
    strmNops[0].dwEvent |= MEVT_F_CALLBACK;
    strmNops[1].dwEvent |= MEVT_F_CALLBACK;

    rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr));
    ok(!rc, "midiOutPrepare rc=%s\n", mmsys_error(rc));

    rc = playStream(hm, &mhdr);
    ok(!rc, "midiStreamOut 0 bytes recorded rc=%s\n", mmsys_error(rc));

    test_notification(hwnd, "midiStreamOut", MOM_DONE, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "0 bytes recorded", 0, WHATEVER);

    /* FIXME: check dwOffset within callback
     * instead of the unspecified value afterwards */
    ok(1234123123==mhdr.dwOffset || broken(0==mhdr.dwOffset), "play 0 set MIDIHDR.dwOffset to %u\n", mhdr.dwOffset);
    /* w2k and later only set dwOffset when processing MEVT_T_CALLBACK,
     * while w9X/me/nt always sets it.  Have Wine behave like w2k because the
     * dwOffset slot does not exist in the small size MIDIHDR. */

    mhdr.dwOffset = 1234123123;
    mhdr.dwBytesRecorded = 1*sizeof(MIDISHORTEVENT);

    rc = playStream(hm, &mhdr);
    ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));

    test_notification(hwnd, "1 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "1 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "1 of 2 events", 0, WHATEVER);
    ok(0==mhdr.dwOffset, "MIDIHDR.dwOffset 1/2 changed to %u\n", mhdr.dwOffset);

    mhdr.dwOffset = 1234123123;
    mhdr.dwBytesRecorded = 2*sizeof(MIDISHORTEVENT);

    rc = playStream(hm, &mhdr);
    ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));

    test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "2 of 2 events", MOM_POSITIONCB, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "2 of 2 events", 0, WHATEVER);
    ok(sizeof(MIDISHORTEVENT)==mhdr.dwOffset, "MIDIHDR.dwOffset 2/2 changed to %u\n", mhdr.dwOffset);
    ok(mhdr.dwBytesRecorded == 2*sizeof(MIDISHORTEVENT), "dwBytesRecorded changed to %u\n", mhdr.dwBytesRecorded);

    strmNops[0].dwEvent &= ~MEVT_F_CALLBACK;
    strmNops[1].dwEvent &= ~MEVT_F_CALLBACK;
    mhdr.dwOffset = 1234123123;
    rc = playStream(hm, &mhdr);
    ok(!rc, "midiStreamOut 1 event out of 2 rc=%s\n", mmsys_error(rc));

    test_notification(hwnd, "0 CB in 2 events", MOM_DONE, (DWORD_PTR)&mhdr);
    test_notification(hwnd, "0 CB in 2 events", 0, WHATEVER);
    /* w9X/me/nt set dwOffset to the position played last */
    ok(1234123123==mhdr.dwOffset || broken(sizeof(MIDISHORTEVENT)==mhdr.dwOffset), "MIDIHDR.dwOffset nocb changed to %u\n", mhdr.dwOffset);

    mhdr.dwBytesRecorded = mhdr.dwBufferLength-1;
    rc = playStream(hm, &mhdr);
    ok(rc==MMSYSERR_INVALPARAM,"midiStreamOut dwBytesRecorded modulo MIDIEVENT rc=%s\n", mmsys_error(rc));
    if (!rc) {
         test_notification(hwnd, "2 of 2 events", MOM_DONE, (DWORD_PTR)&mhdr);
    }

    mhdr.dwBytesRecorded = mhdr.dwBufferLength+1;
    rc = playStream(hm, &mhdr);
    ok(rc==MMSYSERR_INVALPARAM,"midiStreamOut dwBufferLength<dwBytesRecorded rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "past MIDIHDR tests", 0, WHATEVER);

    rc = midiStreamStop(hm);
    ok(!rc, "midiStreamStop rc=%s\n", mmsys_error(rc));
    ok(mhdr.dwUser==0x56FA552C, "MIDIHDR.dwUser changed to %lx\n", mhdr.dwUser);

    rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr));
    ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));
    ok(0==strmNops[0].dwStreamID, "dwStreamID[0] set to %x\n", strmNops[0].dwStreamID);
    ok(0==strmNops[1].dwStreamID, "dwStreamID[1] set to %x\n", strmNops[1].dwStreamID);

    mhdr.dwBufferLength = 70000; /* > 64KB! */
    mhdr.lpData = HeapAlloc(GetProcessHeap(), 0 , mhdr.dwBufferLength);
    ok(mhdr.lpData!=NULL, "No %d bytes of memory!\n", mhdr.dwBufferLength);
    if (mhdr.lpData) {
        mhdr.dwFlags = 0;
        /* PrepareHeader detects the too large buffer is for a stream. */
        rc = midiOutPrepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr));
        todo_wine ok(rc==MMSYSERR_INVALPARAM, "midiOutPrepare stream too large rc=%s\n", mmsys_error(rc));

        rc = midiOutUnprepareHeader((HMIDIOUT)hm, &mhdr, sizeof(mhdr));
        ok(!rc, "midiOutUnprepare rc=%s\n", mmsys_error(rc));

        HeapFree(GetProcessHeap(), 0, mhdr.lpData);
    }

    rc = midiStreamClose(hm);
    ok(!rc, "midiStreamClose rc=%s\n", mmsys_error(rc));
    test_notification(hwnd, "midiStreamClose", MOM_CLOSE, 0);
    test_notification(hwnd, "midiStream over", 0, WHATEVER);

    rc = midiStreamOpen(&hm, &udev, 1, 0, (DWORD_PTR)MYCBINST, CALLBACK_FUNCTION);
    ok(!rc /*w2k*/|| rc==MMSYSERR_INVALPARAM/*w98*/, "midiStreamOpen NULL function rc=%s\n", mmsys_error(rc));
    if (!rc) {
        trace("Device %d accepts NULL CALLBACK_FUNCTION\n", udev);
        rc = midiStreamClose(hm);
        ok(!rc, "midiStreamClose rc=%s\n", mmsys_error(rc));
    }

    rc = midiStreamOpen(&hm, &udev, 1, (DWORD_PTR)0xDEADBEEF, (DWORD_PTR)MYCBINST, CALLBACK_WINDOW);
    ok(rc==MMSYSERR_INVALPARAM, "midiStreamOpen bad window rc=%s\n", mmsys_error(rc));
    if (!rc) {
        rc = midiStreamClose(hm);
        ok(!rc, "midiStreamClose rc=%s\n", mmsys_error(rc));
    }
}
/* Pipeline Callbacks */
static gboolean
probe_cb (InsanityGstTest * ptest, GstPad * pad, GstMiniObject * object,
    gpointer userdata)
{
  InsanityTest *test = INSANITY_TEST (ptest);

  global_last_probe = g_get_monotonic_time ();

  DECODER_TEST_LOCK ();
  if (GST_IS_BUFFER (object)) {
    GstBuffer *buf;
    GstClockTime ts;

    buf = GST_BUFFER (object);
    ts = GST_BUFFER_PTS (buf);

    /* First check clipping */
    if (glob_testing_parser == FALSE && GST_CLOCK_TIME_IS_VALID (ts) &&
        glob_waiting_segment == FALSE) {
      GstClockTime ts_end, cstart, cstop;

      /* Check if buffer is completely outside the segment */
      ts_end = ts;
      if (GST_BUFFER_DURATION_IS_VALID (buf))
        ts_end += GST_BUFFER_DURATION (buf);

      /* Check if buffer is completely outside the segment */
      ts_end = ts;
      if (!gst_segment_clip (&glob_last_segment,
              glob_last_segment.format, ts, ts_end, &cstart, &cstop)) {
        char *msg = g_strdup_printf ("Got timestamp %" GST_TIME_FORMAT " -- %"
            GST_TIME_FORMAT ", outside configured segment (%" GST_TIME_FORMAT
            " -- %" GST_TIME_FORMAT "), method %s",
            GST_TIME_ARGS (ts), GST_TIME_ARGS (ts_end),
            GST_TIME_ARGS (glob_last_segment.start),
            GST_TIME_ARGS (glob_last_segment.stop),
            test_get_name (glob_in_progress));
        insanity_test_validate_checklist_item (INSANITY_TEST (ptest),
            "segment-clipping", FALSE, msg);
        g_free (msg);
        glob_bad_segment_clipping = TRUE;
      }
    }

    switch (glob_in_progress) {
      case TEST_NONE:
        if (glob_waiting_first_segment == TRUE)
          insanity_test_validate_checklist_item (test, "first-segment",
              FALSE, "Got a buffer before the first segment");

        /* Got the first buffer, starting testing dance */
        next_test (test);
        break;
      case TEST_POSITION:
        test_position (test, buf);
        break;
      case TEST_FAST_FORWARD:
      case TEST_BACKWARD_PLAYBACK:
      case TEST_FAST_BACKWARD:
      {
        gint64 stime_ts;

        if (GST_CLOCK_TIME_IS_VALID (ts) == FALSE ||
            glob_waiting_segment == TRUE) {
          break;
        }

        stime_ts = gst_segment_to_stream_time (&glob_last_segment,
            glob_last_segment.format, ts);

        if (GST_CLOCK_TIME_IS_VALID (glob_seek_first_buf_ts) == FALSE) {
          GstClockTime expected_ts =
              gst_segment_to_stream_time (&glob_last_segment,
              glob_last_segment.format,
              glob_seek_rate <
              0 ? glob_seek_stop_ts : glob_seek_segment_seektime);

          GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (stime_ts, expected_ts));

          if (diff > SEEK_THRESHOLD) {
            gchar *valmsg =
                g_strdup_printf ("Received buffer timestamp %" GST_TIME_FORMAT
                " Seeek wanted %" GST_TIME_FORMAT "",
                GST_TIME_ARGS (stime_ts),
                GST_TIME_ARGS (expected_ts));

            validate_current_test (test, FALSE, valmsg);
            next_test (test);

            g_free (valmsg);
          } else
            glob_seek_first_buf_ts = stime_ts;

        } else {
          GstClockTimeDiff diff =
              GST_CLOCK_DIFF (stime_ts, glob_seek_first_buf_ts);

          if (diff < 0)
            diff = -diff;

          if (diff >= glob_playback_duration * GST_SECOND) {
            validate_current_test (test, TRUE, NULL);
            next_test (test);
          }
        }
        break;
      }
      default:
        break;
    }

  } else if (GST_IS_EVENT (object)) {
    GstEvent *event = GST_EVENT (object);
    guint seqnum = gst_event_get_seqnum (event);

    if (G_LIKELY (glob_seqnum_found == FALSE) && seqnum == glob_seqnum)
      glob_seqnum_found = TRUE;

    if (glob_seqnum_found == TRUE && seqnum != glob_seqnum) {
      gchar *message = g_strdup_printf ("Current seqnum %i != "
          "received %i", glob_seqnum, seqnum);

      insanity_test_validate_checklist_item (test, "seqnum-management",
          FALSE, message);

      glob_wrong_seqnum = TRUE;
      g_free (message);
    }

    switch (GST_EVENT_TYPE (event)) {
      case GST_EVENT_SEGMENT:
      {
        gst_event_copy_segment (event, &glob_last_segment);

        if (glob_waiting_segment == FALSE)
          /* Cache the segment as it will be our reference but don't look
           * further */
          goto done;

        glob_last_segment_start_time = glob_last_segment.start;
        if (glob_waiting_first_segment == TRUE) {
          insanity_test_validate_checklist_item (test, "first-segment", TRUE,
              NULL);

          glob_waiting_first_segment = FALSE;
        } else if (glob_in_progress >= TEST_FAST_FORWARD &&
            glob_in_progress <= TEST_FAST_BACKWARD) {
          GstClockTimeDiff diff;
          gboolean valid_stop = TRUE;
          GstClockTimeDiff wdiff, rdiff;

          rdiff =
              ABS (GST_CLOCK_DIFF (glob_last_segment.stop,
                  glob_last_segment.start)) * ABS (glob_last_segment.rate *
              glob_last_segment.applied_rate);
          wdiff =
              ABS (GST_CLOCK_DIFF (glob_seek_stop_ts,
                  glob_seek_segment_seektime));

          diff =
              GST_CLOCK_DIFF (glob_last_segment.position,
              glob_seek_segment_seektime);
          if (diff < 0)
            diff = -diff;

          /* Now compare with the expected segment */
          if ((glob_last_segment.rate * glob_last_segment.applied_rate) ==
              glob_seek_rate && diff <= SEEK_THRESHOLD && valid_stop) {
            glob_seek_got_segment = TRUE;
          } else {
            GstClockTime stopdiff = ABS (GST_CLOCK_DIFF (rdiff, wdiff));

            gchar *validate_msg =
                g_strdup_printf ("Wrong segment received, Rate %f expected "
                "%f, start time diff %" GST_TIME_FORMAT " stop diff %"
                GST_TIME_FORMAT,
                (glob_last_segment.rate * glob_last_segment.applied_rate),
                glob_seek_rate,
                GST_TIME_ARGS (diff), GST_TIME_ARGS (stopdiff));

            validate_current_test (test, FALSE, validate_msg);
            next_test (test);
            g_free (validate_msg);
          }
        }

        glob_waiting_segment = FALSE;
        break;
      }
      default:
        break;
    }
  }

done:
  DECODER_TEST_UNLOCK ();
  return TRUE;
}