#include <stdlib.h>
+#include <string.h>
+
+#include <tdm_types.h>
#include <tbm_type.h>
#include <wayland-server.h>
#include <tizen-extension-server-protocol.h>
+
#include <libds/log.h>
+#include <libds/surface.h>
+#include "libds-tizen/video.h"
#include "shared/pixel_format.h"
#define TIZEN_VIDEO_VERSION 1
{
struct wl_global *global;
struct wl_list resources;
+ struct wl_list objects;
+
struct wl_array formats;
+ struct wl_array properties;
struct wl_listener display_destroy;
+ int32_t min_width, min_height;
+ int32_t max_width, max_height;
+ int32_t prefer_align;
+
+ struct {
+ struct wl_signal destroy;
+ struct wl_signal new_object;
+ } events;
+};
+
+struct ds_tizen_video_object
+{
+ struct wl_resource *resource;
+ struct ds_surface *surface;
+
+ struct wl_list link; // ds_tizen_video::objects
+
+ struct wl_listener surface_destroy;
+
struct {
struct wl_signal destroy;
+ struct wl_signal request_set_property;
+ struct wl_signal request_follow_topmost_visibility;
+ struct wl_signal request_unfollow_topmost_visibility;
+ struct wl_signal request_attribute_allowed;
+ struct wl_signal request_attribute_disallowed;
} events;
};
+struct video_property
+{
+ char name[TDM_NAME_LEN];
+ int32_t value;
+};
+
static void video_handle_display_destroy(struct wl_listener *listener,
void *data);
static void video_bind(struct wl_client *client, void *data, uint32_t version,
uint32_t id);
static void video_send_format(struct ds_tizen_video *video,
tbm_format format);
+static void video_send_size(struct ds_tizen_video *video);
+static void video_send_property(struct ds_tizen_video *video,
+ struct video_property *prop);
+static struct video_property *video_get_property(struct ds_tizen_video *video,
+ const char *name);
static void video_resource_send_formats(struct wl_resource *resource,
struct wl_array *formats);
+static struct ds_tizen_video_object *
+create_video_object(struct wl_client *client, uint32_t id, int version,
+ struct wl_resource *surface_resource);
+static void video_object_destroy(struct ds_tizen_video_object *object);
WL_EXPORT struct ds_tizen_video *
ds_tizen_video_create(struct wl_display *display)
}
wl_list_init(&video->resources);
+ wl_list_init(&video->objects);
+
wl_array_init(&video->formats);
+ wl_array_init(&video->properties);
wl_signal_init(&video->events.destroy);
+ wl_signal_init(&video->events.new_object);
video->display_destroy.notify = video_handle_display_destroy;
wl_display_add_destroy_listener(display, &video->display_destroy);
}
WL_EXPORT void
+ds_tizen_video_set_size_hint(struct ds_tizen_video *video,
+ int32_t min_width, int32_t min_height,
+ int32_t max_width, int32_t max_height, int32_t prefer_align)
+{
+ if (video->min_width == min_width && video->min_height == min_height &&
+ video->max_width == max_width && video->max_height == max_height &&
+ video->prefer_align == prefer_align)
+ return;
+
+ video->min_width = min_width;
+ video->min_height = min_height;
+ video->max_width = max_width;
+ video->max_height = max_height;
+ video->prefer_align = prefer_align;
+
+ video_send_size(video);
+}
+
+WL_EXPORT void
+ds_tizen_video_add_property(struct ds_tizen_video *video, const char *name,
+ int32_t value)
+{
+ struct video_property *prop;
+
+ prop = video_get_property(video, name);
+ if (!prop) {
+ prop = wl_array_add(&video->properties, sizeof *prop);
+ if (!prop) {
+ ds_err("Failed wl_array_add()");
+ return;
+ }
+
+ memset(prop, 0, sizeof(*prop));
+ strncpy(prop->name, name, sizeof(prop->name) - 1);
+ }
+ prop->value = value;
+
+ video_send_property(video, prop);
+}
+
+WL_EXPORT void
ds_tizen_video_add_destroy_listener(struct ds_tizen_video *video,
struct wl_listener *listener)
{
wl_signal_add(&video->events.destroy, listener);
}
+WL_EXPORT void
+ds_tizen_video_add_new_object_listener(struct ds_tizen_video *video,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&video->events.new_object, listener);
+}
+
+WL_EXPORT struct ds_surface *
+ds_tizen_video_object_get_surface(struct ds_tizen_video_object *object)
+{
+ return object->surface;
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_destroy_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_request_set_property_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.request_set_property, listener);
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_request_follow_topmost_visibility_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.request_follow_topmost_visibility, listener);
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_request_unfollow_topmost_visibility_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.request_unfollow_topmost_visibility,
+ listener);
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_request_attribute_allowed_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.request_attribute_allowed, listener);
+}
+
+WL_EXPORT void
+ds_tizen_video_object_add_request_attribute_disallowed_listener(
+ struct ds_tizen_video_object *object,
+ struct wl_listener *listener)
+{
+ wl_signal_add(&object->events.request_attribute_disallowed, listener);
+}
+
static void
video_handle_display_destroy(struct wl_listener *listener, void *data)
{
wl_signal_emit(&video->events.destroy, video);
wl_array_release(&video->formats);
+ wl_array_release(&video->properties);
wl_list_remove(&video->display_destroy.link);
wl_global_destroy(video->global);
video_handle_get_object(struct wl_client *client, struct wl_resource *resource,
uint32_t id, struct wl_resource *surface_resource)
{
+ struct ds_tizen_video *video;
+ struct ds_tizen_video_object *object;
+ struct video_property *prop;
+ int version;
+
+ video = wl_resource_get_user_data(resource);
+
+ version = wl_resource_get_version(resource);
+ object = create_video_object(client, id, version, surface_resource);
+ if (!object) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_list_insert(&video->objects, &object->link);
+ tizen_video_object_send_size(object->resource,
+ video->min_width, video->min_height,
+ video->max_width, video->max_height, video->prefer_align);
+
+ wl_array_for_each(prop, &video->properties) {
+ tizen_video_object_send_attribute(object->resource,
+ prop->name, prop->value);
+ }
+
+ wl_signal_emit(&video->events.new_object, object);
}
static void
struct wl_resource *resource, uint32_t id,
struct wl_resource *surface_resource)
{
-
+ // TODO
}
static void
}
static void
+video_send_size(struct ds_tizen_video *video)
+{
+ struct ds_tizen_video_object *object;
+
+ wl_list_for_each(object, &video->objects, link) {
+ tizen_video_object_send_size(object->resource,
+ video->min_width, video->min_height,
+ video->max_width, video->max_height, video->prefer_align);
+ }
+}
+
+static void
+video_send_property(struct ds_tizen_video *video, struct video_property *prop)
+{
+ struct ds_tizen_video_object *object;
+
+ wl_list_for_each(object, &video->objects, link) {
+ tizen_video_object_send_attribute(object->resource,
+ prop->name, prop->value);
+ }
+}
+
+static struct video_property *
+video_get_property(struct ds_tizen_video *video, const char *name)
+{
+ struct video_property *prop;
+
+ wl_array_for_each(prop, &video->properties) {
+ if (strcmp(prop->name, name) == 0)
+ return prop;
+ }
+
+ return NULL;
+}
+
+static void
video_resource_send_formats(struct wl_resource *resource,
struct wl_array *formats)
{
wl_array_for_each(p, formats)
tizen_video_send_format(resource, *p);
}
+
+static void
+video_object_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+video_object_handle_set_attribute(struct wl_client *client,
+ struct wl_resource *resource, const char *name, int32_t value)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (!object)
+ return;
+
+ struct ds_event_tizen_video_request_set_property event = {
+ .object = object,
+ .name = name,
+ .value = value,
+ };
+ wl_signal_emit(&object->events.request_set_property, &event);
+}
+
+static void
+video_object_handle_follow_topmost_visibility(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (!object)
+ return;
+
+ wl_signal_emit(&object->events.request_follow_topmost_visibility, object);
+}
+
+static void
+video_object_handle_unfollow_topmost_visibility(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (!object)
+ return;
+
+ wl_signal_emit(&object->events.request_unfollow_topmost_visibility, object);
+}
+
+static void
+video_object_handle_allowed_attribute(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (!object)
+ return;
+
+ wl_signal_emit(&object->events.request_attribute_allowed, object);
+}
+
+static void
+video_object_handle_disallowed_attribute(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (!object)
+ return;
+
+ wl_signal_emit(&object->events.request_attribute_disallowed, object);
+}
+
+static const struct tizen_video_object_interface video_object_impl = {
+ .destroy = video_object_handle_destroy,
+ .set_attribute = video_object_handle_set_attribute,
+ .follow_topmost_visibility = video_object_handle_follow_topmost_visibility,
+ .unfollow_topmost_visibility =
+ video_object_handle_unfollow_topmost_visibility,
+ .allowed_attribute = video_object_handle_allowed_attribute,
+ .disallowed_attribute = video_object_handle_disallowed_attribute,
+};
+
+static void
+video_object_handle_resource_destroy(struct wl_resource *resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_resource_get_user_data(resource);
+ if (object)
+ video_object_destroy(object);
+}
+
+static void
+video_object_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+ struct ds_tizen_video_object *object;
+
+ object = wl_container_of(listener, object, surface_destroy);
+ video_object_destroy(object);
+}
+
+static struct ds_tizen_video_object *
+create_video_object(struct wl_client *client, uint32_t id, int version,
+ struct wl_resource *surface_resource)
+{
+ struct ds_tizen_video_object *object;
+
+ object = calloc(1, sizeof *object);
+ if (!object)
+ return NULL;
+
+ object->resource = wl_resource_create(client,
+ &tizen_video_object_interface, version, id);
+ if (!object->resource) {
+ free(object);
+ return NULL;
+ }
+ wl_resource_set_implementation(object->resource, &video_object_impl,
+ object, video_object_handle_resource_destroy);
+
+ wl_signal_init(&object->events.destroy);
+ wl_signal_init(&object->events.request_set_property);
+ wl_signal_init(&object->events.request_follow_topmost_visibility);
+ wl_signal_init(&object->events.request_unfollow_topmost_visibility);
+ wl_signal_init(&object->events.request_attribute_allowed);
+ wl_signal_init(&object->events.request_attribute_disallowed);
+
+ object->surface = ds_surface_from_resource(surface_resource);
+
+ object->surface_destroy.notify = video_object_handle_surface_destroy;
+ ds_surface_add_destroy_listener(object->surface, &object->surface_destroy);
+
+ ds_inf("Create ds_tizen_video_object(%p)", object);
+
+ return object;
+}
+
+static void
+video_object_destroy(struct ds_tizen_video_object *object)
+{
+ ds_inf("Destroy ds_tizen_video_object(%p)", object);
+
+ wl_signal_emit(&object->events.destroy, object);
+
+ wl_resource_set_user_data(object->resource, NULL);
+
+ wl_list_remove(&object->surface_destroy.link);
+ wl_list_remove(&object->link);
+ free(object);
+}