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 = ¤tAnimation; // 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 = ¤tAnimation; 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(); }