nautilus-adapter-progressive-load-strategy.c 10.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/*
 * Nautilus
 *
 * Copyright (C) 2000 Eazel, Inc.
 *
 * Nautilus is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * Nautilus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; see the file COPYING.  If not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Maciej Stachowiak <mjs@eazel.com>
 */


/* nautilus-adapter-progressive-load-strategy.c - 
 */


#include <config.h>

#include "nautilus-adapter-progressive-load-strategy.h"

#include <gtk/gtkobject.h>
#include <libnautilus-extensions/nautilus-gtk-macros.h>
#include <libgnomevfs/gnome-vfs.h>
#include <bonobo/Bonobo.h>

#include <stdio.h>

42
43
44
45
46

typedef void (*StopLoadingCallback) (NautilusAdapterProgressiveLoadStrategy *strategy,
				     void *user_data);


47
48
struct NautilusAdapterProgressiveLoadStrategyDetails {
	Bonobo_ProgressiveDataSink  progressive_data_sink;
Maciej Stachowiak's avatar
Maciej Stachowiak committed
49
	gboolean                    stop;
50
51
52
53
	gboolean                    loading;
	gboolean                    no_report_stop;
	StopLoadingCallback         callback;
	void                       *user_data;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
};


static void nautilus_adapter_progressive_load_strategy_initialize_class (NautilusAdapterProgressiveLoadStrategyClass *klass);
static void nautilus_adapter_progressive_load_strategy_initialize       (NautilusAdapterProgressiveLoadStrategy      *strategy);
static void nautilus_adapter_progressive_load_strategy_destroy          (GtkObject                              *object);

static void nautilus_adapter_progressive_load_strategy_load_location (NautilusAdapterLoadStrategy *strategy,
								 const char                  *uri);

static void nautilus_adapter_progressive_load_strategy_stop_loading  (NautilusAdapterLoadStrategy *strategy);


NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusAdapterProgressiveLoadStrategy, nautilus_adapter_progressive_load_strategy, NAUTILUS_TYPE_ADAPTER_LOAD_STRATEGY)


static void
nautilus_adapter_progressive_load_strategy_initialize_class (NautilusAdapterProgressiveLoadStrategyClass *klass)
{
	GtkObjectClass                   *object_class;
	NautilusAdapterLoadStrategyClass *adapter_load_strategy_class;

	object_class = GTK_OBJECT_CLASS (klass);

	object_class->destroy = nautilus_adapter_progressive_load_strategy_destroy;

	adapter_load_strategy_class = NAUTILUS_ADAPTER_LOAD_STRATEGY_CLASS (klass);

	adapter_load_strategy_class->load_location = nautilus_adapter_progressive_load_strategy_load_location;
	adapter_load_strategy_class->stop_loading = nautilus_adapter_progressive_load_strategy_stop_loading;
}

static void
nautilus_adapter_progressive_load_strategy_initialize (NautilusAdapterProgressiveLoadStrategy *strategy)
{
	strategy->details = g_new0 (NautilusAdapterProgressiveLoadStrategyDetails, 1);
}

static void
nautilus_adapter_progressive_load_strategy_destroy (GtkObject *object)
{
	NautilusAdapterProgressiveLoadStrategy *strategy;
	CORBA_Environment ev;

Maciej Stachowiak's avatar
Maciej Stachowiak committed
98
99
	CORBA_exception_init (&ev);

100
101
	strategy = NAUTILUS_ADAPTER_PROGRESSIVE_LOAD_STRATEGY (object);

102
103
104
105
	if (strategy->details->progressive_data_sink != CORBA_OBJECT_NIL) {
		bonobo_object_release_unref (strategy->details->progressive_data_sink, &ev);
	}

Maciej Stachowiak's avatar
Maciej Stachowiak committed
106
107
	CORBA_exception_free (&ev);

108
109
	g_free (strategy->details);

110
	NAUTILUS_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
111
112
113
}

NautilusAdapterLoadStrategy *
Maciej Stachowiak's avatar
Maciej Stachowiak committed
114
nautilus_adapter_progressive_load_strategy_new (Bonobo_ProgressiveDataSink  progressive_data_sink)
115
116
{
	NautilusAdapterProgressiveLoadStrategy *strategy;
Maciej Stachowiak's avatar
Maciej Stachowiak committed
117
118
119
	CORBA_Environment ev;

	CORBA_exception_init (&ev);
120

121
122
123
	strategy = NAUTILUS_ADAPTER_PROGRESSIVE_LOAD_STRATEGY (gtk_object_new (NAUTILUS_TYPE_ADAPTER_PROGRESSIVE_LOAD_STRATEGY, NULL));
	gtk_object_ref (GTK_OBJECT (strategy));
	gtk_object_sink (GTK_OBJECT (strategy));
124
125

	strategy->details->progressive_data_sink = progressive_data_sink;
Maciej Stachowiak's avatar
Maciej Stachowiak committed
126
127

	CORBA_exception_free (&ev);
128
129
130
131

	return NAUTILUS_ADAPTER_LOAD_STRATEGY (strategy);
}

Maciej Stachowiak's avatar
Maciej Stachowiak committed
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

static void
call_when_stopped (NautilusAdapterProgressiveLoadStrategy *strategy,
		   StopLoadingCallback                     callback, 
		   void                                   *user_data)
{
	strategy->details->callback = callback;
	strategy->details->user_data = user_data;
}


static void
load_and_free_uri (NautilusAdapterProgressiveLoadStrategy *strategy,
		   gpointer                                data)
{
	char *uri;

	uri = (char *) data;
	nautilus_adapter_progressive_load_strategy_load_location 
		(NAUTILUS_ADAPTER_LOAD_STRATEGY (strategy), uri);
	g_free (uri);

}

static void
declare_done_loading (NautilusAdapterProgressiveLoadStrategy *strategy)
{
	StopLoadingCallback cb;
	void *data;

	strategy->details->loading = FALSE;

	if (strategy->details->callback != NULL) {
		cb = strategy->details->callback;
		strategy->details->callback = NULL;
		data = strategy->details->user_data;
		strategy->details->user_data = NULL;
		
		(*cb) (strategy, data);
	}
}


Maciej Stachowiak's avatar
Maciej Stachowiak committed
176
177
178
179
static void
stop_loading (NautilusAdapterProgressiveLoadStrategy *strategy,
	      GnomeVFSHandle *handle,
	      Bonobo_ProgressiveDataSink_iobuf *iobuf,
180
	      gboolean           failed,
Maciej Stachowiak's avatar
Maciej Stachowiak committed
181
182
183
	      CORBA_Environment *ev) 
{
	Bonobo_ProgressiveDataSink_end (strategy->details->progressive_data_sink, ev); 
184
185
186
187
188
189
190
	if (! strategy->details->no_report_stop) {
		if (failed) {
			nautilus_adapter_load_strategy_report_load_failed (NAUTILUS_ADAPTER_LOAD_STRATEGY (strategy));
		} else {
			nautilus_adapter_load_strategy_report_load_complete (NAUTILUS_ADAPTER_LOAD_STRATEGY (strategy));
		}
	}
Maciej Stachowiak's avatar
Maciej Stachowiak committed
191
192
193
194
	gtk_object_unref (GTK_OBJECT (strategy));
	gnome_vfs_close (handle);
	CORBA_free (iobuf);
	CORBA_exception_free (ev);
195
	declare_done_loading (strategy);
Maciej Stachowiak's avatar
Maciej Stachowiak committed
196
197
198
199
}



200
201
202
203
#define STOP_LOADING                                                 \
        do {                                                         \
	         stop_loading (strategy, handle, iobuf, TRUE, &ev);  \
		 return;                                             \
Maciej Stachowiak's avatar
Maciej Stachowiak committed
204
205
        } while (0)

206
207
208
209
210
211
212
#define CHECK_IF_STOPPED                                              \
        do {                                                          \
	        if (strategy->details->stop) {                        \
	         stop_loading (strategy, handle, iobuf, FALSE, &ev);  \
		 return;                                              \
                }                                                     \
        } while (0)
Maciej Stachowiak's avatar
Maciej Stachowiak committed
213
214


215
#define LOAD_CHUNK 32768
216
217
218
219
220
221

static void
nautilus_adapter_progressive_load_strategy_load_location (NautilusAdapterLoadStrategy *abstract_strategy,
							  const char                  *uri)
{
	NautilusAdapterProgressiveLoadStrategy *strategy;
222
	GnomeVFSFileInfo *file_info;
223
224
225
226
227
228
	GnomeVFSHandle   *handle;
	GnomeVFSResult    result;
	GnomeVFSFileSize  bytes_read;
	Bonobo_ProgressiveDataSink_iobuf *iobuf;
	CORBA_octet *data;
	CORBA_Environment ev;
229
	GnomeVFSFileSize size;
230
231
232

	strategy = NAUTILUS_ADAPTER_PROGRESSIVE_LOAD_STRATEGY (abstract_strategy);

233
234
235
236
237
238
239
240
241
242
243
	if (strategy->details->loading == TRUE) {
		strategy->details->no_report_stop = TRUE;
		nautilus_adapter_progressive_load_strategy_stop_loading  (abstract_strategy);

		call_when_stopped (strategy, load_and_free_uri, g_strdup (uri));

		return;
	}

	strategy->details->no_report_stop = FALSE;

Maciej Stachowiak's avatar
Maciej Stachowiak committed
244
245
	gtk_object_ref (GTK_OBJECT (strategy));

246
247
248
249
	strategy->details->loading = TRUE;
	strategy->details->stop = FALSE;


250
251
	CORBA_exception_init (&ev);

Maciej Stachowiak's avatar
Maciej Stachowiak committed
252
253
254
255
	/* FIXME bugzilla.eazel.com 3455: this code is stupid and
           loads the component in a way that blocks the nautilus
           adapter component, which is pointless/stupid; it should be
           async. */
256
257

	if (gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ) != GNOME_VFS_OK) {
Maciej Stachowiak's avatar
Maciej Stachowiak committed
258
259
		nautilus_adapter_load_strategy_report_load_failed (abstract_strategy);
		gtk_object_unref (GTK_OBJECT (strategy));
260
		CORBA_exception_free (&ev);
261
		declare_done_loading (strategy);
262
263
264
265
266
267
268
269
		return;
	}

	iobuf = Bonobo_ProgressiveDataSink_iobuf__alloc ();
	CORBA_sequence_set_release (iobuf, TRUE);
	data = CORBA_sequence_CORBA_octet_allocbuf (LOAD_CHUNK);
	iobuf->_buffer = data;

Maciej Stachowiak's avatar
Maciej Stachowiak committed
270
271
272
	nautilus_adapter_load_strategy_report_load_underway (abstract_strategy);

	if (strategy->details->stop) {
273
		nautilus_adapter_load_strategy_report_load_complete (abstract_strategy);
Maciej Stachowiak's avatar
Maciej Stachowiak committed
274
275
		gtk_object_unref (GTK_OBJECT (strategy));
		CORBA_exception_free (&ev);
276
		declare_done_loading (strategy);
Maciej Stachowiak's avatar
Maciej Stachowiak committed
277
278
		return;
	}
279
280
281

	Bonobo_ProgressiveDataSink_start (strategy->details->progressive_data_sink, &ev);

Maciej Stachowiak's avatar
Maciej Stachowiak committed
282
283
	CHECK_IF_STOPPED;

284
285
286
287
288
289
290
	file_info = gnome_vfs_file_info_new ();
	result = gnome_vfs_get_file_info_from_handle (handle, file_info, GNOME_VFS_FILE_INFO_DEFAULT);
	size = 0;
	if (result == GNOME_VFS_OK && (file_info->valid_fields | GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
		size = file_info->size;
	}
	gnome_vfs_file_info_unref (file_info);
291

292
	if (size > 0) {
293
		Bonobo_ProgressiveDataSink_setSize (strategy->details->progressive_data_sink, 
294
						    (long) size, &ev);
Maciej Stachowiak's avatar
Maciej Stachowiak committed
295
		CHECK_IF_STOPPED;
296
297
298
299
300
301
302
303
	}
		
	do {
		result = gnome_vfs_read (handle, data, LOAD_CHUNK, &bytes_read);

		if (result == GNOME_VFS_OK) {
			iobuf->_length = bytes_read;

304
			Bonobo_ProgressiveDataSink_addData (strategy->details->progressive_data_sink, iobuf, &ev);
305
			
Maciej Stachowiak's avatar
Maciej Stachowiak committed
306
307
			CHECK_IF_STOPPED;
			
308
			if (ev._major != CORBA_NO_EXCEPTION) {
Maciej Stachowiak's avatar
Maciej Stachowiak committed
309
				STOP_LOADING;
310
311
312
			}
		} else if (result == GNOME_VFS_ERROR_EOF) {
			if (ev._major == CORBA_NO_EXCEPTION) {
Maciej Stachowiak's avatar
Maciej Stachowiak committed
313
314
315
316
317
318
				Bonobo_ProgressiveDataSink_end (strategy->details->progressive_data_sink, &ev);
				nautilus_adapter_load_strategy_report_load_complete (abstract_strategy);
				gtk_object_unref (GTK_OBJECT (strategy));
				gnome_vfs_close (handle);
				CORBA_free (iobuf);
				CORBA_exception_free (&ev);
319
				declare_done_loading (strategy);
Maciej Stachowiak's avatar
Maciej Stachowiak committed
320
				return;
321
			} else {
Maciej Stachowiak's avatar
Maciej Stachowiak committed
322
				STOP_LOADING;
323
324
			}
		} else {
Maciej Stachowiak's avatar
Maciej Stachowiak committed
325
			STOP_LOADING;
326
		}
Maciej Stachowiak's avatar
Maciej Stachowiak committed
327
	} while (TRUE);
328
329
330
}

static void
Maciej Stachowiak's avatar
Maciej Stachowiak committed
331
nautilus_adapter_progressive_load_strategy_stop_loading  (NautilusAdapterLoadStrategy *abstract_strategy)
332
{
Maciej Stachowiak's avatar
Maciej Stachowiak committed
333
	NautilusAdapterProgressiveLoadStrategy *strategy;
334

Maciej Stachowiak's avatar
Maciej Stachowiak committed
335
	strategy = NAUTILUS_ADAPTER_PROGRESSIVE_LOAD_STRATEGY (abstract_strategy);
336

Maciej Stachowiak's avatar
Maciej Stachowiak committed
337
	strategy->details->stop = TRUE;
338
339
}

340