Example #1
0
G_MODULE_EXPORT gint
test_text_main (gint    argc,
                gchar **argv)
{
  ClutterActor *stage;
  ClutterActor *text, *text2;
  ClutterColor  text_color = { 0x33, 0xff, 0x33, 0xff };
  ClutterColor  cursor_color = { 0xff, 0x33, 0x33, 0xff };
  ClutterTextBuffer *buffer;

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Editing");
  clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  buffer = clutter_text_buffer_new_with_text ("ยท", -1);

  text = clutter_text_new_with_buffer (buffer);
  clutter_text_set_font_name (CLUTTER_TEXT (text), FONT);
  clutter_text_set_color (CLUTTER_TEXT (text), &text_color);

  clutter_container_add (CLUTTER_CONTAINER (stage), text, NULL);
  clutter_actor_set_position (text, 40, 30);
  clutter_actor_set_width (text, 1024);
  clutter_text_set_line_wrap (CLUTTER_TEXT (text), TRUE);

  clutter_actor_set_reactive (text, TRUE);
  clutter_stage_set_key_focus (CLUTTER_STAGE (stage), text);

  clutter_text_set_editable (CLUTTER_TEXT (text), TRUE);
  clutter_text_set_selectable (CLUTTER_TEXT (text), TRUE);
  clutter_text_set_cursor_color (CLUTTER_TEXT (text), &cursor_color);
  clutter_text_set_selected_text_color (CLUTTER_TEXT (text), CLUTTER_COLOR_Blue);

  text2 = clutter_text_new_with_buffer (buffer);
  clutter_text_set_color (CLUTTER_TEXT (text2), &text_color);
  clutter_container_add (CLUTTER_CONTAINER (stage), text2, NULL);
  clutter_actor_set_position (text2, 40, 300);
  clutter_actor_set_width (text2, 1024);
  clutter_text_set_line_wrap (CLUTTER_TEXT (text2), TRUE);

  clutter_actor_set_reactive (text2, TRUE);
  clutter_text_set_editable (CLUTTER_TEXT (text2), TRUE);
  clutter_text_set_selectable (CLUTTER_TEXT (text2), TRUE);
  clutter_text_set_cursor_color (CLUTTER_TEXT (text2), &cursor_color);
  clutter_text_set_selected_text_color (CLUTTER_TEXT (text2), CLUTTER_COLOR_Green);

  if (argv[1])
    {
      GError *error = NULL;
      gchar *utf8;

      g_file_get_contents (argv[1], &utf8, NULL, &error);
      if (error)
        {
          utf8 = g_strconcat ("Unable to open '", argv[1], "':\n",
                              error->message,
                              NULL);
          g_error_free (error);
        }

      clutter_text_set_text (CLUTTER_TEXT (text), utf8);
    }
  else
    clutter_text_set_text (CLUTTER_TEXT (text), runes);

  clutter_actor_set_size (stage, 1024, 768);
  clutter_actor_show (stage);

  clutter_main ();

  return EXIT_SUCCESS;
}
Animation::Animation(ClutterActor *stage, TCLControl *tcl) {
    printf("Building animation tools...\n");

    //====================
    // On screen display:

    // Build the Actor that will display what's going to the lights:
    lightDisplay = clutter_actor_new();

    // Build the color delegate for the lightDisplay's content/texture:
    colors = clutter_image_new();

    // Error object for GDK/Clutter calls that need them
    error = NULL;

    // Load image data from some other data source...:
    // guchar *data =
    // GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(data);

    // Load image data from a file:
//    const char *img_path = "./wut.png";
//    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_size (img_path, WIDTH, HEIGHT, &error);

    // Build the color buffer we'll store the actual colors in:
    pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, WIDTH, HEIGHT);
    pixels = gdk_pixbuf_get_pixels(pixbuf); // Grab it's pixels...
    rowstride = gdk_pixbuf_get_rowstride(pixbuf); // figure out the width of the buffer...

    // And put some RED into the buffer to start off with
    for (int x = 0; x < WIDTH; x++) {
        for (int y = 0; y < HEIGHT; y++) {

            // Find the ADDRESS of each pixel in the pixbuf via the raw char buffer we built...
            // and bind it to a pointer to a char...
            unsigned char *pixel = &pixels[y * rowstride + x * 3];

            // And directly update that memory location with a new color
            // This AUTOMATICALLY updates the color of the pixbuf!
            // It's just hitting the memory directly!
            pixel[0] = 255;//red
            pixel[1] = 0x0;//green
            pixel[2] = 0x0;//blue
        }
    }
    // Dump the colors from the color buffer into the ClutterContent delegate!
    if (pixbuf != NULL) {
        clutter_image_set_data(CLUTTER_IMAGE(colors),
                            gdk_pixbuf_get_pixels (pixbuf),
                            COGL_PIXEL_FORMAT_RGB_888,
                            gdk_pixbuf_get_width (pixbuf),
                            gdk_pixbuf_get_height (pixbuf),
                            gdk_pixbuf_get_rowstride (pixbuf),
                            &error);
    }

    // Tell the lightDisplay that it's content should be whatever we've dumped in the content delegate:
    clutter_actor_set_content(lightDisplay, colors);

    // Define the size of the On Screen Display:
    clutter_actor_set_x_expand(lightDisplay, TRUE);
    clutter_actor_set_y_expand(lightDisplay, TRUE);
    clutter_actor_set_position(lightDisplay, 0, WIDTH*(osd_scale+7)+WIDTH);
    clutter_actor_set_size(lightDisplay, WIDTH, HEIGHT);
    clutter_actor_set_scale(lightDisplay, osd_scale, osd_scale+7);
    clutter_actor_set_rotation_angle(lightDisplay, CLUTTER_Z_AXIS, -90);

    // Actually add that actor to the stage!
    clutter_actor_add_child(stage, lightDisplay);

    // Allow for UI events on this crazy thing!
    clutter_actor_set_reactive(lightDisplay, TRUE);

    // Wire up the event listener on this lightDisplay actor.
    TouchData *touch_data;
    touch_data = g_slice_new(TouchData); // reserve memory for it...
    touch_data->lightDisplay = lightDisplay; // Place the button actor itself inside the struct
    touch_data->tcl = tcl; // TCLControl *tcl is just a POINTER here (unlike in main.cpp)
    touch_data->animationNumber = &currentAnimation;

    // Actually wire up the events and set up the data structs that the events need to operate:
    g_signal_connect(lightDisplay, "touch-event", G_CALLBACK(handleTouchEvents), touch_data);
    g_signal_connect(lightDisplay, "button-press-event", G_CALLBACK(handleTouchEvents), touch_data);
    g_signal_connect(lightDisplay, "motion-event", G_CALLBACK(handleTouchEvents), touch_data);
    g_signal_connect(lightDisplay, "button-release-event", G_CALLBACK(handleTouchEvents), touch_data);

    // Set sane default values for the initial touch location
    input_y = 0;
    input_x = 0;

    // End On screen display
    //=============================
    // Shader setup and wirings:

    // Build the Actor that the shader will dump to directly:
    shaderOutput = clutter_actor_new();
    clutter_actor_set_position(shaderOutput, 0, 0);
    clutter_actor_set_size(shaderOutput, WIDTH-1, HEIGHT);
    clutter_actor_set_rotation_angle(shaderOutput, CLUTTER_Z_AXIS, -90);
    clutter_actor_set_rotation_angle(shaderOutput, CLUTTER_Y_AXIS, 180);
    clutter_actor_add_child(stage, shaderOutput);

    // Allocate the memory for the shader output buffer:
    // Figure out how big our buffer needs to be. *4 because four bytes per pixel (r, g, b, a) in shader land
    int shaderBufferSize = WIDTH * HEIGHT * 4;
    shaderBuffer = (guint8 *) malloc(shaderBufferSize); // malloc the buffer!!

    // Double check that we built the buffer correctly.
    if (shaderBuffer == NULL) {
        printf("OOPS! malloc error!\n");
    } else {
//        printf("We malloc'd %i bytes for your shaderBuffer. It points at: %p\n", shaderBufferSize, shaderBuffer);
//        printf(" The Rowstride on the shaderBuffer is %i\n", rowstride);
    }


    // init shader TEXTURES!
    // Populate the noiseImage:
//    const char *textureFile = "images/text_noise.png";
//    audiopixbuf = gdk_pixbuf_new_from_file (textureFile, NULL);


    // Init the audioImage that will store the FFT output for attaching to the actor
    error = NULL;
    audioImage = clutter_image_new ();
    audiopixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, WIDTH, HEIGHT );
    audioPixels = gdk_pixbuf_get_pixels(audiopixbuf); // Grab it's pixels...
    audioRowstride = gdk_pixbuf_get_rowstride(audiopixbuf); // figure out the width of the buffer...

    // Populate the audioImage with no data so we have a fresh start:
    for (int x = 0; x < WIDTH; x++) {
        for (int y = 0; y < HEIGHT; y++) {

            // Find the ADDRESS of each pixel in the pixbuf via the raw char buffer we built...
            // and bind it to a pointer to a char...
            unsigned char *pixel = &audioPixels[y * audioRowstride + x * 3];

            // And directly update that memory location with a new color
            // This AUTOMATICALLY updates the color of the pixbuf!
            // It's just hitting the memory directly!
            pixel[0] = getrand(0,255);//((int)(samples[x]*max)) & 0xff;   // low bits...
            pixel[1] = getrand(0,255);//((int)(samples[x]*max)) & 0xff00; // high bits.
            pixel[2] = getrand(0,255);     // some random value could be used for noise...
        }
    }

    // Actually load our color onto the actor
    clutter_image_set_data (CLUTTER_IMAGE (audioImage),
                            gdk_pixbuf_get_pixels (audiopixbuf),
                            COGL_PIXEL_FORMAT_RGB_888,
                            gdk_pixbuf_get_width (audiopixbuf),
                            gdk_pixbuf_get_height (audiopixbuf),
                            gdk_pixbuf_get_rowstride (audiopixbuf),
                            &error);
//    g_object_unref (audiopixbuf); // we want to reuse this... don't dereference that memory yet...
    clutter_actor_set_content (shaderOutput, audioImage);
    //clutter_actor_set_content_gravity (shaderOutput, CLUTTER_CONTENT_GRAVITY_TOP_RIGHT);

//    audioTexture[0] = 0.25;
//    srand(time(NULL));
//    for (i=0; i<noiseTextureSize; i++) {
//        noiseTexture[i] = getrandf();
//    }

    // Make sure we don't have a current shader so we don't break the update loop:
    shaderLoaded = false;
    currentSpeed = 100;




    // Once we have all that set up, we still need to START THE ACTUAL ANIMATION!!
    // To do that, we'll need to use the event chain/callback system we have been using so far.
    // Get ready to hand this display chunk in to the animation event:
    AnimationData *data;
    data = g_slice_new(AnimationData); // reserve memory for it...
    data->tcl = tcl; // tcl is an pointer to the main TCLControl object.
    data->animationNumber = &currentAnimation;
    data->animationObject = this;

    // The clutter timeline object takes a "duration" in milliseconds...
    timeline = clutter_timeline_new(1);
    g_signal_connect(timeline, "new-frame", G_CALLBACK(handleNewFrame), data);

    // which will just continue repeating:
    clutter_timeline_set_repeat_count(timeline, -1);

    // This actually starts the timeline animation!
    clutter_timeline_start(timeline);

    // Generate the list of known shaders:
    buildShaderList();

    // Load the first shader so we do not get a black screen:
    currentShader = 0; // Set the inital shader to load (usually, first in the directory)
    updateCurrentShader();

}