124e576a595045ed9f309228c37f072bb31b5e06
[profile/ivi/weston.git] / clients / screenshot.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <glib.h>
31 #include <gdk-pixbuf/gdk-pixbuf.h>
32
33 #include "wayland-client.h"
34 #include "screenshooter-client-protocol.h"
35
36 /* The screenshooter is a good example of a custom object exposed by
37  * the compositor and serves as a test bed for implementing client
38  * side marshalling outside libwayland.so */
39
40 static struct wl_output *output;
41 static struct wl_shm *shm;
42 static struct screenshooter *screenshooter;
43 static int output_width, output_height;
44
45 static void
46 display_handle_geometry(void *data,
47                         struct wl_output *wl_output,
48                         int x,
49                         int y,
50                         int physical_width,
51                         int physical_height,
52                         int subpixel,
53                         const char *make,
54                         const char *model)
55 {
56 }
57
58 static void
59 display_handle_mode(void *data,
60                     struct wl_output *wl_output,
61                     uint32_t flags,
62                     int width,
63                     int height,
64                     int refresh)
65 {
66         output_width = width;
67         output_height = height;
68 }
69
70 static const struct wl_output_listener output_listener = {
71         display_handle_geometry,
72         display_handle_mode
73 };
74
75 static void
76 handle_global(struct wl_display *display, uint32_t id,
77               const char *interface, uint32_t version, void *data)
78 {
79         if (strcmp(interface, "wl_output") == 0) {
80                 output = wl_display_bind(display, id, &wl_output_interface);
81                 wl_output_add_listener(output, &output_listener, NULL);
82         } else if (strcmp(interface, "wl_shm") == 0) {
83                 shm = wl_display_bind(display, id, &wl_shm_interface);
84         } else if (strcmp(interface, "screenshooter") == 0) {
85                 screenshooter = wl_display_bind(display, id, &screenshooter_interface);
86         }
87 }
88
89 static struct wl_buffer *
90 create_shm_buffer(int width, int height, void **data_out)
91 {
92         char filename[] = "/tmp/wayland-shm-XXXXXX";
93         struct wl_buffer *buffer;
94         int fd, size, stride;
95         void *data;
96
97         fd = mkstemp(filename);
98         if (fd < 0) {
99                 fprintf(stderr, "open %s failed: %m\n", filename);
100                 return NULL;
101         }
102         stride = width * 4;
103         size = stride * height;
104         if (ftruncate(fd, size) < 0) {
105                 fprintf(stderr, "ftruncate failed: %m\n");
106                 close(fd);
107                 return NULL;
108         }
109
110         data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
111         unlink(filename);
112
113         if (data == MAP_FAILED) {
114                 fprintf(stderr, "mmap failed: %m\n");
115                 close(fd);
116                 return NULL;
117         }
118
119         buffer = wl_shm_create_buffer(shm, fd, width, height, stride,
120                                       WL_SHM_FORMAT_XRGB32);
121
122         close(fd);
123
124         *data_out = data;
125
126         return buffer;
127 }
128
129 static void
130 write_png(int width, int height, void *data)
131 {
132         GdkPixbuf *pixbuf, *normal;
133         GError *error = NULL;
134
135         g_type_init();
136         pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE,
137                                           8, width, height, width * 4, NULL,
138                                           NULL);
139
140         normal = gdk_pixbuf_flip(pixbuf, FALSE);
141         gdk_pixbuf_save(normal, "wayland-screenshot.png", "png", &error, NULL);
142         g_object_unref(normal);
143         g_object_unref(pixbuf);
144 }
145
146 int main(int argc, char *argv[])
147 {
148         struct wl_display *display;
149         struct wl_buffer *buffer;
150         void *data = NULL;
151
152         display = wl_display_connect(NULL);
153         if (display == NULL) {
154                 fprintf(stderr, "failed to create display: %m\n");
155                 return -1;
156         }
157
158         wl_display_add_global_listener(display, handle_global, &screenshooter);
159         wl_display_iterate(display, WL_DISPLAY_READABLE);
160         wl_display_roundtrip(display);
161         if (screenshooter == NULL) {
162                 fprintf(stderr, "display doesn't support screenshooter\n");
163                 return -1;
164         }
165
166         buffer = create_shm_buffer(output_width, output_height, &data);
167         screenshooter_shoot(screenshooter, output, buffer);
168         wl_display_roundtrip(display);
169
170         write_png(output_width, output_height, data);
171
172         return 0;
173 }