SADisplay::~SADisplay () { visual_object_unref (VISUAL_OBJECT (m_impl->screen)); }
static int fixate_with_partial_data_request (VisRingBuffer *ringbuffer, VisBuffer *data, int offset, int nbytes, int *buffercorr) { VisListEntry *le = NULL; VisRingBufferEntry *entry; int curposition = 0; int curoffset = 0; int startat = 0; *buffercorr = 0; while ((entry = visual_list_next (ringbuffer->entries, &le)) != NULL) { int bsize = 0; startat++; if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_BUFFER) { if ((bsize = visual_buffer_get_size (entry->buffer)) > 0) curoffset += bsize; /* This buffer partially falls within the offset */ if (curoffset > offset) { visual_buffer_put_data (data, (visual_buffer_get_data (entry->buffer) + visual_buffer_get_size (entry->buffer)) - (curoffset - offset), curoffset - offset, 0); *buffercorr = curoffset - offset; break; } } else if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_FUNCTION) { if (entry->sizefunc != NULL) { curoffset += entry->sizefunc (ringbuffer, entry); /* This buffer partially falls within the offset */ if (curoffset > offset) { VisBuffer *tempbuf = entry->datafunc (ringbuffer, entry); visual_buffer_put_data (data, (visual_buffer_get_data (tempbuf) + visual_buffer_get_size (tempbuf)) - (curoffset - offset), curoffset - offset, 0); visual_object_unref (VISUAL_OBJECT (tempbuf)); *buffercorr = curoffset - offset; break; } } else { VisBuffer *tempbuf = entry->datafunc (ringbuffer, entry); if ((bsize = visual_buffer_get_size (tempbuf)) > 0) curoffset += bsize; /* This buffer partially falls within the offset */ if (curoffset > offset) { visual_buffer_put_data (data, (visual_buffer_get_data (tempbuf) + visual_buffer_get_size (tempbuf)) - (curoffset - offset), curoffset - offset, 0); *buffercorr = curoffset - offset; break; } visual_object_unref (VISUAL_OBJECT (tempbuf)); } } } return startat; }
static void render_frame (GstVisualGL * visual) { const guint16 *data; VisBuffer *lbuf, *rbuf; guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES]; guint i; gcahr *name; /* Read VISUAL_SAMPLES samples per channel */ data = (const guint16 *) gst_adapter_peek (visual->adapter, VISUAL_SAMPLES * visual->bps); lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL); rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL); if (visual->channels == 2) { for (i = 0; i < VISUAL_SAMPLES; i++) { ldata[i] = *data++; rdata[i] = *data++; } } else { for (i = 0; i < VISUAL_SAMPLES; i++) { ldata[i] = *data; rdata[i] = *data++; } } visual_audio_samplepool_input_channel (visual->audio->samplepool, lbuf, visual->libvisual_rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_LEFT); visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf, visual->libvisual_rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_RIGHT); visual_object_unref (VISUAL_OBJECT (lbuf)); visual_object_unref (VISUAL_OBJECT (rbuf)); visual_audio_analyze (visual->audio); /* apply the matrices that the actor set up */ glPushAttrib (GL_ALL_ATTRIB_BITS); glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadMatrixd (visual->actor_projection_matrix); glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadMatrixd (visual->actor_modelview_matrix); /* This line try to hacks compatiblity with libprojectM * If libprojectM version <= 2.0.0 then we have to unbind our current * fbo to see something. But it's incorrect and we cannot use fbo chainning (append other glfilters * after libvisual_gl_projectM will not work) * To have full compatibility, libprojectM needs to take care of our fbo. * Indeed libprojectM has to unbind it before the first rendering pass * and then rebind it before the final pass. It's done from 2.0.1 */ name = gst_element_get_name (GST_ELEMENT (visual)); if (g_ascii_strncasecmp (name, "visualglprojectm", 16) == 0 && !HAVE_PROJECTM_TAKING_CARE_OF_EXTERNAL_FBO) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); g_free (name); actor_negotiate (visual->display, visual); if (visual->is_enabled_gl_depth_test) { glEnable (GL_DEPTH_TEST); glDepthFunc (visual->gl_depth_func); } if (visual->is_enabled_gl_blend) { glEnable (GL_BLEND); glBlendFunc (visual->gl_blend_src_alpha, GL_ZERO); } visual_actor_run (visual->actor, visual->audio); check_gl_matrix (); glMatrixMode (GL_PROJECTION); glPopMatrix (); glMatrixMode (GL_MODELVIEW); glPopMatrix (); glPopAttrib (); glDisable (GL_DEPTH_TEST); glDisable (GL_BLEND); /*glDisable (GL_LIGHT0); glDisable (GL_LIGHTING); glDisable (GL_POLYGON_OFFSET_FILL); glDisable (GL_COLOR_MATERIAL); glDisable (GL_CULL_FACE); */ GST_DEBUG_OBJECT (visual, "rendered one frame"); }
int visual_ringbuffer_get_data_offset (VisRingBuffer *ringbuffer, VisBuffer *data, int offset, int nbytes) { VisListEntry *le = NULL; VisRingBufferEntry *entry; int curposition = 0; int curoffset = 0; int positioncorr = 0; int startat = 0; int buffercorr = 0; visual_log_return_val_if_fail (ringbuffer != NULL, -VISUAL_ERROR_RINGBUFFER_NULL); visual_log_return_val_if_fail (data != NULL, -VISUAL_ERROR_BUFFER_NULL); /* Fixate possible partial buffer */ if (offset > 0) startat = fixate_with_partial_data_request (ringbuffer, data, offset, nbytes, &buffercorr); curposition = buffercorr; /* Buffer fixated with partial segment, request the other segments */ while (curposition < nbytes) { int lindex = 0; le = NULL; /* return immediately if there are no elements in the list */ if(visual_list_count(ringbuffer->entries) == 0) return VISUAL_OK; while ((entry = visual_list_next (ringbuffer->entries, &le)) != NULL) { VisBuffer *tempbuf; lindex++; /* Skip to the right offset buffer fragment */ if (lindex <= startat) continue; if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_BUFFER) { tempbuf = entry->buffer; } else if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_FUNCTION) { /* Will bail out through visual_error_raise(), this is fatal, let's not try to * recover, it's a very obvious bug in the software */ if (entry->datafunc == NULL) { visual_log (VISUAL_LOG_ERROR, _("No VisRingBufferDataFunc data provider function set on " "type VISUAL_RINGBUFFER_ENTRY_TYPE_FUNCTION")); return -VISUAL_ERROR_IMPOSSIBLE; } tempbuf = entry->datafunc (ringbuffer, entry); } if (curposition + visual_buffer_get_size (tempbuf) > nbytes) { VisBuffer buf; visual_buffer_init (&buf, visual_buffer_get_data (tempbuf), nbytes - curposition, NULL); visual_buffer_put (data, &buf, curposition); if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_FUNCTION) visual_object_unref (VISUAL_OBJECT (tempbuf)); return VISUAL_OK; } visual_buffer_put (data, tempbuf, curposition); curposition += visual_buffer_get_size (tempbuf); if (entry->type == VISUAL_RINGBUFFER_ENTRY_TYPE_FUNCTION) visual_object_unref (VISUAL_OBJECT (tempbuf)); /* Filled without room for partial buffer addition */ if (curposition == nbytes) return VISUAL_OK; } startat = 0; } return VISUAL_OK; }
int inp_alsa_init (VisPluginData *plugin) { snd_pcm_hw_params_t *hwparams = NULL; alsaPrivate *priv; unsigned int rate = inp_alsa_var_samplerate; unsigned int exact_rate; unsigned int tmp; int dir; int err; #if ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); #endif visual_return_val_if_fail(plugin != NULL, -1); priv = visual_mem_new0 (alsaPrivate, 1); visual_return_val_if_fail(priv != NULL, -1); visual_object_set_private (VISUAL_OBJECT (plugin), priv); if ((err = snd_pcm_open(&priv->chandle, visual_strdup(inp_alsa_var_cdevice), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { visual_log(VISUAL_LOG_ERROR, _("Record open error: %s"), snd_strerror(err)); return -1; } snd_pcm_hw_params_malloc(&hwparams); visual_return_val_if_fail(hwparams != NULL, -1); if (snd_pcm_hw_params_any(priv->chandle, hwparams) < 0) { visual_log(VISUAL_LOG_ERROR, _("Cannot configure this PCM device")); snd_pcm_hw_params_free(hwparams); return(-1); } if (snd_pcm_hw_params_set_access(priv->chandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { visual_log(VISUAL_LOG_ERROR, _("Error setting access")); snd_pcm_hw_params_free(hwparams); return(-1); } #if VISUAL_LITTLE_ENDIAN == 1 if (snd_pcm_hw_params_set_format(priv->chandle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) { #else if (snd_pcm_hw_params_set_format(priv->chandle, hwparams, SND_PCM_FORMAT_S16_BE) < 0) { #endif visual_log(VISUAL_LOG_ERROR, _("Error setting format")); snd_pcm_hw_params_free(hwparams); return(-1); } exact_rate = rate; if (snd_pcm_hw_params_set_rate_near(priv->chandle, hwparams, &exact_rate, &dir) < 0) { visual_log(VISUAL_LOG_ERROR, _("Error setting rate")); snd_pcm_hw_params_free(hwparams); return(-1); } if (exact_rate != rate) { visual_log(VISUAL_LOG_INFO, _("The rate %d Hz is not supported by your " \ "hardware.\n" \ "==> Using %d Hz instead"), rate, exact_rate); } rate = exact_rate; if (snd_pcm_hw_params_set_channels(priv->chandle, hwparams, inp_alsa_var_channels) < 0) { visual_log(VISUAL_LOG_ERROR, _("Error setting channels")); snd_pcm_hw_params_free(hwparams); return(-1); } /* Setup a large buffer */ tmp = 1000000; if (snd_pcm_hw_params_set_period_time_near(priv->chandle, hwparams, &tmp, &dir) < 0){ visual_log(VISUAL_LOG_ERROR, _("Error setting period time")); snd_pcm_hw_params_free(hwparams); return(-1); } tmp = 1000000*4; if (snd_pcm_hw_params_set_buffer_time_near(priv->chandle, hwparams, &tmp, &dir) < 0){ visual_log(VISUAL_LOG_ERROR, _("Error setting buffer time")); snd_pcm_hw_params_free(hwparams); return(-1); } if (snd_pcm_hw_params(priv->chandle, hwparams) < 0) { visual_log(VISUAL_LOG_ERROR, _("Error setting HW params")); snd_pcm_hw_params_free(hwparams); return(-1); } if (snd_pcm_prepare(priv->chandle) < 0) { visual_log(VISUAL_LOG_ERROR, _("Failed to prepare interface")); snd_pcm_hw_params_free(hwparams); return(-1); } snd_pcm_hw_params_free(hwparams); priv->loaded = 1; return 0; } int inp_alsa_cleanup (VisPluginData *plugin) { alsaPrivate *priv = NULL; visual_return_val_if_fail(plugin != NULL, -1); priv = visual_object_get_private (VISUAL_OBJECT (plugin)); visual_return_val_if_fail(priv != NULL, -1); if (priv->loaded == 1) snd_pcm_close(priv->chandle); visual_mem_free (priv); return 0; }
static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer) { GstBuffer *outbuf = NULL; guint i; GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); GstFlowReturn ret = GST_FLOW_OK; guint avail; GST_DEBUG_OBJECT (visual, "chain function called"); /* If we don't have an output format yet, preallocate a buffer to try and * set one */ if (GST_PAD_CAPS (visual->srcpad) == NULL) { ret = get_buffer (visual, &outbuf); if (ret != GST_FLOW_OK) { gst_buffer_unref (buffer); goto beach; } } /* resync on DISCONT */ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { gst_adapter_clear (visual->adapter); } GST_DEBUG_OBJECT (visual, "Input buffer has %d samples, time=%" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buffer) / visual->bps, GST_BUFFER_TIMESTAMP (buffer)); gst_adapter_push (visual->adapter, buffer); while (TRUE) { gboolean need_skip; const guint16 *data; guint64 dist, timestamp; GST_DEBUG_OBJECT (visual, "processing buffer"); avail = gst_adapter_available (visual->adapter); GST_DEBUG_OBJECT (visual, "avail now %u", avail); /* we need at least VISUAL_SAMPLES samples */ if (avail < VISUAL_SAMPLES * visual->bps) break; /* we need at least enough samples to make one frame */ if (avail < visual->spf * visual->bps) break; /* get timestamp of the current adapter byte */ timestamp = gst_adapter_prev_timestamp (visual->adapter, &dist); if (GST_CLOCK_TIME_IS_VALID (timestamp)) { /* convert bytes to time */ dist /= visual->bps; timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, visual->rate); } if (timestamp != -1) { gint64 qostime; /* QoS is done on running time */ qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME, timestamp); qostime += visual->duration; GST_OBJECT_LOCK (visual); /* check for QoS, don't compute buffers that are known to be late */ need_skip = visual->earliest_time != -1 && qostime <= visual->earliest_time; GST_OBJECT_UNLOCK (visual); if (need_skip) { GST_WARNING_OBJECT (visual, "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT, GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time)); goto skip; } } /* Read VISUAL_SAMPLES samples per channel */ data = (const guint16 *) gst_adapter_peek (visual->adapter, VISUAL_SAMPLES * visual->bps); #if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000 { VisBuffer *lbuf, *rbuf; guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES]; VisAudioSampleRateType rate; lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL); rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL); if (visual->channels == 2) { for (i = 0; i < VISUAL_SAMPLES; i++) { ldata[i] = *data++; rdata[i] = *data++; } } else { for (i = 0; i < VISUAL_SAMPLES; i++) { ldata[i] = *data; rdata[i] = *data++; } } switch (visual->rate) { case 8000: rate = VISUAL_AUDIO_SAMPLE_RATE_8000; break; case 11250: rate = VISUAL_AUDIO_SAMPLE_RATE_11250; break; case 22500: rate = VISUAL_AUDIO_SAMPLE_RATE_22500; break; case 32000: rate = VISUAL_AUDIO_SAMPLE_RATE_32000; break; case 44100: rate = VISUAL_AUDIO_SAMPLE_RATE_44100; break; case 48000: rate = VISUAL_AUDIO_SAMPLE_RATE_48000; break; case 96000: rate = VISUAL_AUDIO_SAMPLE_RATE_96000; break; default: visual_object_unref (VISUAL_OBJECT (lbuf)); visual_object_unref (VISUAL_OBJECT (rbuf)); GST_ERROR_OBJECT (visual, "unsupported rate %d", visual->rate); ret = GST_FLOW_ERROR; goto beach; break; } visual_audio_samplepool_input_channel (visual->audio->samplepool, lbuf, rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, (char *) VISUAL_AUDIO_CHANNEL_LEFT); visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf, rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, (char *) VISUAL_AUDIO_CHANNEL_RIGHT); visual_object_unref (VISUAL_OBJECT (lbuf)); visual_object_unref (VISUAL_OBJECT (rbuf)); } #else if (visual->channels == 2) { for (i = 0; i < VISUAL_SAMPLES; i++) { visual->audio->plugpcm[0][i] = *data++; visual->audio->plugpcm[1][i] = *data++; } } else { for (i = 0; i < VISUAL_SAMPLES; i++) { visual->audio->plugpcm[0][i] = *data; visual->audio->plugpcm[1][i] = *data++; } } #endif /* alloc a buffer if we don't have one yet, this happens * when we pushed a buffer in this while loop before */ if (outbuf == NULL) { ret = get_buffer (visual, &outbuf); if (ret != GST_FLOW_OK) { goto beach; } } visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf)); visual_audio_analyze (visual->audio); visual_actor_run (visual->actor, visual->audio); visual_video_set_buffer (visual->video, NULL); GST_DEBUG_OBJECT (visual, "rendered one frame"); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = visual->duration; ret = gst_pad_push (visual->srcpad, outbuf); outbuf = NULL; skip: GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input", visual->spf); /* Flush out the number of samples per frame */ gst_adapter_flush (visual->adapter, visual->spf * visual->bps); /* quit the loop if something was wrong */ if (ret != GST_FLOW_OK) break; } beach: if (outbuf != NULL) gst_buffer_unref (outbuf); gst_object_unref (visual); return ret; }
static void set_parameter_lv(void * data, const char * name, const bg_parameter_value_t * val) { int supported; lv_priv_t * priv; int index; int i_tmp; uint8_t r, g, b; char * tmp_string; VisParamEntry * param; VisListEntry * list_entry; VisColor * color; const bg_parameter_info_t * info; if(!name) return; priv = (lv_priv_t*)data; info = bg_parameter_find(priv->parameters, name); if(!info) return; /* This would crash if multi_parameters were supported */ index = info - priv->parameters; tmp_string = gavl_strdup(name); param = visual_param_entry_new(tmp_string); free(tmp_string); /* Menus have to be treated specially */ if(info->type == BG_PARAMETER_STRINGLIST) { if(!priv->widgets[index]) return; /* Get the selected index */ supported = 0; list_entry = NULL; while(visual_list_next(&VISUAL_UI_CHOICE(priv->widgets[index])->choices.choices, &list_entry)) { if(!strcmp(((VisUIChoiceEntry*)(list_entry->data))->name, val->val_str)) { visual_param_entry_set_from_param(param, ((VisUIChoiceEntry*)(list_entry->data))->value); supported = 1; break; } } } else { supported = 1; switch(priv->params[index]->type) { case VISUAL_PARAM_ENTRY_TYPE_NULL: /**< No parameter. */ supported = 0; break; case VISUAL_PARAM_ENTRY_TYPE_STRING: /**< String parameter. */ if(val->val_str) visual_param_entry_set_string(param, val->val_str); else supported = 0; break; case VISUAL_PARAM_ENTRY_TYPE_INTEGER: /**< Integer parameter. */ visual_param_entry_set_integer(param, val->val_i); break; case VISUAL_PARAM_ENTRY_TYPE_FLOAT: /**< Floating point parameter. */ visual_param_entry_set_float(param, val->val_f); break; case VISUAL_PARAM_ENTRY_TYPE_DOUBLE: /**< Double floating point parameter. */ visual_param_entry_set_double(param, val->val_f); break; case VISUAL_PARAM_ENTRY_TYPE_COLOR: /**< VisColor parameter. */ i_tmp = (int)(val->val_color[0] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; r = i_tmp; i_tmp = (int)(val->val_color[1] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; g = i_tmp; i_tmp = (int)(val->val_color[2] * 255.0 + 0.5); if(i_tmp < 0) i_tmp = 0; if(i_tmp > 255) i_tmp = 255; b = i_tmp; color = visual_color_new(); visual_color_set(color, r, g, b); visual_param_entry_set_color_by_color(param, color); visual_object_unref(VISUAL_OBJECT(color)); break; case VISUAL_PARAM_ENTRY_TYPE_PALETTE: /**< VisPalette parameter. */ case VISUAL_PARAM_ENTRY_TYPE_OBJECT: /**< VisObject parameter. */ case VISUAL_PARAM_ENTRY_TYPE_END: /**< List end, and used as terminator for VisParamEntry lists. */ supported = 0; break; } } if(supported) { visual_event_queue_add_param(visual_plugin_get_eventqueue(visual_actor_get_plugin(priv->actor)), param); } else visual_object_unref(VISUAL_OBJECT(param)); }
bg_plugin_info_t * bg_lv_get_info(const char * filename) { int i; VisVideoAttributeOptions *vidoptions; bg_x11_window_t * win; bg_plugin_info_t * ret; VisPluginRef * ref; VisList * list; VisActor * actor; VisPluginInfo * info; char * tmp_string; const char * actor_name = NULL; check_init(); list = visual_plugin_get_registry(); /* Find out if there is a plugin matching the filename */ while((actor_name = visual_actor_get_next_by_name(actor_name))) { ref = visual_plugin_find(list, actor_name); if(ref && !strcmp(ref->file, filename)) break; } if(!actor_name) return NULL; actor = visual_actor_new(actor_name); if(!actor) return NULL; ret = calloc(1, sizeof(*ret)); info = visual_plugin_get_info(visual_actor_get_plugin(actor)); ret->name = bg_sprintf("vis_lv_%s", actor_name); ret->long_name = gavl_strdup(info->name); ret->type = BG_PLUGIN_VISUALIZATION; ret->api = BG_PLUGIN_API_LV; ret->description = bg_sprintf(TR("libvisual plugin")); ret->module_filename = gavl_strdup(filename); /* Optional info */ if(info->author && *info->author) { tmp_string = bg_sprintf(TR("\nAuthor: %s"), info->author); ret->description = gavl_strcat(ret->description, tmp_string); free(tmp_string); } if(info->version && *info->version) { tmp_string = bg_sprintf(TR("\nVersion: %s"), info->version); ret->description = gavl_strcat(ret->description, tmp_string); free(tmp_string); } if(info->about && *info->about) { tmp_string = bg_sprintf(TR("\nAbout: %s"), info->about); ret->description = gavl_strcat(ret->description, tmp_string); free(tmp_string); } if(info->help && *info->help) { tmp_string = bg_sprintf(TR("\nHelp: %s"), info->help); ret->description = gavl_strcat(ret->description, tmp_string); free(tmp_string); } if(info->license && *info->license) { tmp_string = bg_sprintf(TR("\nLicense: %s"), info->license); ret->description = gavl_strcat(ret->description, tmp_string); free(tmp_string); } /* Check out if it's an OpenGL plugin */ if(visual_actor_get_supported_depth(actor) & VISUAL_VIDEO_DEPTH_GL) { ret->flags |= BG_PLUGIN_VISUALIZE_GL; win = bg_x11_window_create(NULL); /* Create an OpenGL context. For this, we need the OpenGL attributes */ vidoptions = visual_actor_get_video_attribute_options(actor); for(i = 0; i < VISUAL_GL_ATTRIBUTE_LAST; i++) { if((vidoptions->gl_attributes[i].mutated) && (bg_attributes[i] >= 0)) { bg_x11_window_set_gl_attribute(win, bg_attributes[i], vidoptions->gl_attributes[i].value); } } /* Set bogus dimensions, will be corrected by the size_callback */ bg_x11_window_set_size(win, 640, 480); bg_x11_window_realize(win); if(!bg_x11_window_start_gl(win)) { ret->flags |= BG_PLUGIN_UNSUPPORTED; } else bg_x11_window_set_gl(win); } else { ret->flags |= BG_PLUGIN_VISUALIZE_FRAME; win = NULL; } ret->priority = 1; /* Must realize the actor to get the parameters */ if(!(ret->flags & BG_PLUGIN_UNSUPPORTED)) { visual_actor_realize(actor); ret->parameters = create_parameters(actor, NULL, NULL); visual_object_unref(VISUAL_OBJECT(actor)); } if(win) { bg_x11_window_unset_gl(win); bg_x11_window_stop_gl(win); bg_x11_window_destroy(win); } return ret; }