diff -u hv/cinelerra/adeviceprefs.C hvirtual-1.1.8/cinelerra/adeviceprefs.C
--- hv/cinelerra/adeviceprefs.C	2003-11-08 01:29:49.000000000 +0100
+++ hvirtual-1.1.8/cinelerra/adeviceprefs.C	2003-12-15 17:20:41.000000000 +0100
@@ -365,8 +365,8 @@
 			output_int = &out_config->alsa_out_channels;
 			break;
 	}
-	dialog->add_subwindow(channels_title = new BC_Title(x1, y, "Channels:", MEDIUMFONT, BLACK));
-	dialog->add_subwindow(alsa_channels = new ALSAChannels(x1, y1 + 20, output_int));
+	dialog->add_subwindow(channels_title = new BC_Title(x1, y, _("Channels:"), MEDIUMFONT, BLACK));
+	dialog->add_subwindow(alsa_channels = new ADeviceIntBox(x1, y1 + 20, output_int));
 	y1 += DEVICE_H;
 #endif
 
diff -u hv/cinelerra/assetedit.C hvirtual-1.1.8/cinelerra/assetedit.C
--- hv/cinelerra/assetedit.C	2003-10-17 07:17:44.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/assetedit.C	2003-12-23 13:24:26.000000000 +0100
@@ -177,7 +177,7 @@
 
 	add_subwindow(new BC_Title(x, y, _("File format:")));
 	x = x2;
-	File file;
+	File file(mwindow->preferences);
 	add_subwindow(new BC_Title(x, y, file.formattostr(mwindow->plugindb, asset->format), MEDIUMFONT, YELLOW));
 	x = x1;
 	y += 20;
diff -u hv/cinelerra/cache.C hvirtual-1.1.8/cinelerra/cache.C
--- hv/cinelerra/cache.C	2003-10-19 11:30:15.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/cache.C	2003-12-23 13:25:04.000000000 +0100
@@ -187,11 +187,11 @@
 	{
 		memory_usage = get_memory_usage();
 		
-		if(memory_usage > preferences->cache_size)
+		if(memory_usage > preferences->cache_items)
 		{
 			result = delete_oldest();
 		}
-	}while(memory_usage > preferences->cache_size && !result);
+	}while(memory_usage > preferences->cache_items && !result);
 
 	check_out_lock->unlock();
 }
@@ -290,7 +290,7 @@
 	this->cache = cache;
 	checked_out = 0;
 
-	file = new File;
+	file = new File(cache->preferences);
 	file->set_processors(cache->preferences->processors);
 	file->set_preload(cache->edl->session->playback_preload);
 
diff -u hv/cinelerra/file.C hvirtual-1.1.8/cinelerra/file.C
--- hv/cinelerra/file.C	2003-10-18 10:51:27.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/file.C	2003-12-23 15:39:11.000000000 +0100
@@ -1,3 +1,4 @@
+
 #include "asset.h"
 #include "byteorder.h"
 #include "edit.h"
@@ -16,22 +17,259 @@
 #include "filetiff.h"
 #include "filevorbis.h"
 #include "formatwindow.h"
+#include "language.h"
 #include "pluginserver.h"
 #include "resample.h"
 #include "stringfile.h"
 #include "vframe.h"
 
 
-#include <libintl.h>
-#define _(String) gettext(String)
-#define gettext_noop(String) String
-#define N_(String) gettext_noop (String)
+
+ FrameCache::FrameCache(int64_t cache_size) 
+ {
+ 	cache_enabled = 0;
+ 	this->cache_size = cache_size;
+	memory_used = 0;
+ 	timer.update();
+ }
+ 
+ FrameCache::~FrameCache() 
+ {
+	reset();
+ }
+ 
+ void FrameCache::reset() 
+ {	
+ 	change_lock.lock();
+ 	FrameCacheTree::iterator iterator = cache_tree.begin();
+ 	while (iterator != cache_tree.end()) {
+ 		delete iterator->second;
+ 		iterator++;
+	}
+ 	cache_tree.clear();
+ 	cache_tree_bytime.clear();
+	memory_used = 0;
+ 	change_lock.unlock();
+ }
+ 
+ void FrameCache::enable_cache() 
+ {	
+ 	cache_enabled = 1;
+ }
+ 
+ 
+ void FrameCache::disable_cache() 
+ {
+ 	cache_enabled = 0;
+ }
+ 
+ void FrameCache::unlock_cache()
+ { 
+ 	change_lock.unlock();
+ }
+ 
+ void FrameCache::lock_cache()
+ { 
+ 	change_lock.lock();
+ }
+ 
+ inline int FrameCache::compare_with_frame(FrameCacheElement *element, 
+ 					int frame_number, 
+ 					int frame_layer,
+ 					int frame_width,
+ 					int frame_height,
+ 					int frame_color_model)
+ {
+ 	if (	element->frame_number == frame_number && 
+		element->frame_layer == frame_layer && 
+ 		element->frame->get_w() == frame_width && 
+ 		element->frame->get_h() == frame_height && 
+ 		element->frame->get_color_model() == frame_color_model)
+ 			return 1; 
+ 		else
+ 			return 0;
+ }
+ 
+ FrameCacheTree::iterator FrameCache::find_element_byframe(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model)
+ {
+ 	FrameCacheTree::iterator iterator = cache_tree.find(frame_number);
+   	if(iterator != cache_tree.end()) {
+ 		do {
+ 			if (compare_with_frame(iterator->second, 
+ 						frame_number, 
+ 						frame_layer,
+ 						frame_width,
+ 						frame_height,
+ 						frame_color_model))
+ 			{
+ 				
+ 				return iterator;
+ 			}
+ 			iterator++;
+ 		} while (iterator->first == frame_number);
+ 	}
+ 	return cache_tree.end();
+ }
+ 
+ FrameCacheTree_ByTime::iterator FrameCache::find_element_bytime(long long frame_time_diff, long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model)
+ {
+ 	FrameCacheTree_ByTime::iterator iterator = cache_tree_bytime.find(frame_time_diff);
+   	if(iterator != cache_tree_bytime.end()) {
+ 		do {	
+ 			if (compare_with_frame(iterator->second, 
+ 						frame_number, 
+ 						frame_layer,
+ 						frame_width,
+ 						frame_height,
+ 						frame_color_model))
+ 			{
+ 				
+ 				return iterator;
+ 			}
+ 			iterator++;
+ 		} while (iterator->first == frame_time_diff);
+ 	}
+ 	return cache_tree_bytime.end();
+ }
+ 
+  
+ // implicitly locks the class, needs to be unlocked after the call
+ // this is the best behaviour, everything else just complicates things and
+ // causes races (because you don't know the state of cache_enabled during the call).
+VFrame *FrameCache::get_frame(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model, int force_cache)
+ {
+ 
+ 	change_lock.lock();
+ 	if (!cache_enabled && !force_cache) return 0;
+ //	printf("Looking for - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", frame_number, frame_layer, frame_width, frame_height, frame_color_model);
+ 	FrameCacheTree::iterator iterator= find_element_byframe(frame_number, 
+ 								frame_layer,
+ 								frame_width,
+ 								frame_height,
+ 								frame_color_model);
+ 	// update timestamp in other tree
+ 	if (iterator != cache_tree.end())
+ 	{
+ 		FrameCacheElement *cache_element = iterator->second;
+ 		FrameCacheTree_ByTime::iterator iterator_bytime;
+ 		// this tree node always exists
+ 		iterator_bytime = find_element_bytime(cache_element->time_diff,
+ 								frame_number, 
+ 								frame_layer,
+ 								frame_width,
+ 								frame_height,
+ 								frame_color_model);
+ 		if (cache_element != iterator_bytime->second)
+ 		{
+ 			printf("FrameCache: Something severely wrong in the cache engine!! this: %p\n", this);
+ 			dump();
+ 			return 0;
+ 		};
+ //		printf("Cache hit - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", frame_number, frame_layer, frame_width, frame_height, frame_color_model);
+ 		// delete & replace with new key
+ 		cache_tree_bytime.erase(iterator_bytime);
+ 		cache_element->time_diff = timer.get_difference();
+ 		cache_tree_bytime.insert(std::pair<long long, FrameCacheElement *> (cache_element->time_diff, cache_element)); 
+ 		return (cache_element->frame);
+ 	};
+ 	return 0;
+ } 
+
+void FrameCache::add_frame(long frame_number, int frame_layer, VFrame *frame, int do_not_copy_frame, int force_cache) 
+ {
+ 	
+ 	if (!cache_enabled && !force_cache) return;
+ 	change_lock.lock();
+ 	
+ //	printf("%p, adding frame:  %li, layer: %i, w: %i, h:%i cm:%i\n",this, frame_number, frame_layer, frame->get_w(),frame->get_h(), frame->get_color_model());
+ 	
+ 	FrameCacheElement *cache_element;
+
+	// what will be new size
+ 	int64_t new_memory_size = frame->get_data_size();
+
+	if (frame->get_w() == 720)
+		printf("balh\n");
+ 	// currently cache size can only grow, not shrink
+ 	while (memory_used + new_memory_size >= cache_size) 
+ 	{
+		// if we cannot fit the new image into cache, exit
+ 		if (memory_used == 0 && new_memory_size > cache_size) {
+			change_lock.unlock();
+			return;
+		}
+		// delete the element that wansn't accessed for the longest time
+ 		FrameCacheTree_ByTime::iterator iterator_bytime = cache_tree_bytime.begin();
+ 		cache_element = iterator_bytime->second;
+ 		FrameCacheTree::iterator iterator = find_element_byframe(cache_element->frame_number,
+ 									cache_element->frame_layer,
+ 									cache_element->frame->get_w(),
+ 									cache_element->frame->get_h(),
+ 									cache_element->frame->get_color_model());
+ //	printf("Deleting oldest frame: - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model());
+		memory_used -= cache_element->frame->get_data_size();
+ 		delete cache_element->frame;
+ 		cache_tree.erase(iterator);
+   		cache_tree_bytime.erase(iterator_bytime);
+		delete cache_element;
+	}
+	cache_element = new FrameCacheElement;
+ 	
+ 	if (do_not_copy_frame) 
+ 	{
+ 		cache_element->frame = frame;
+ 	} else
+ 	{
+ 		cache_element->frame = new VFrame(0,
+ 					frame->get_w(),
+ 					frame->get_h(),
+ 					frame->get_color_model());
+ 		cache_element->frame->copy_from(frame);
+ 	}
+	memory_used += cache_element->frame->get_data_size();
+ 	cache_element->frame_layer = frame_layer;
+ 	cache_element->frame_number = frame_number;
+ 	cache_element->time_diff = timer.get_difference();
+
+//	printf("Adding frame: - frame: %li, layer: %i, w: %i, h:%i, cm: %i\n", cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model());
+	
+//	printf("Memory used by cache: %p %lli\n", this, memory_used);
+ 
+ // insert the same data into both trees under different keys
+ 	
+ 	cache_tree.insert(std::pair<long, FrameCacheElement *> (cache_element->frame_number, cache_element));
+ 	cache_tree_bytime.insert(std::pair<long long, FrameCacheElement *> (cache_element->time_diff, cache_element)); 
+ 	change_lock.unlock();
+}
+ 
+ void FrameCache::dump() 
+{	
+ 	printf("Dump of frames' cache %p, cache_tree:\n", this);
+ 	{
+ 		FrameCacheTree::iterator iterator = cache_tree.begin();
+ 		while (iterator != cache_tree.end()) {
+ 			FrameCacheElement *cache_element = iterator->second;
+ 			printf("%p, frame: %li, layer: %i, w: %i, h:%i, cm: %i, time_diff: %i\n", cache_element, cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model(), cache_element->time_diff);
+ 			iterator++;
+ 		}
+ 	}
+ 	printf("cache_tree_bytime:\n", this);
+ 	{
+ 		FrameCacheTree_ByTime::iterator iterator = cache_tree_bytime.begin();
+ 		while (iterator != cache_tree_bytime.end()) {
+ 			FrameCacheElement *cache_element = iterator->second;
+ 			printf("%p, frame: %li, layer: %i, w: %i, h:%i, cm: %i, time_diff: %li\n", cache_element, cache_element->frame_number, cache_element->frame_layer, cache_element->frame->get_w(), cache_element->frame->get_h(), cache_element->frame->get_color_model(), cache_element->time_diff);
+ 			iterator++;
+ 		}
+ 	}
+ }
 
 
-File::File()
+File::File(Preferences *preferences)
 {
 	cpus = 1;
 	asset = new Asset;
+	frames_cache = new FrameCache(preferences->cache_size_per_item * 1024*1024);
 	reset_parameters();
 }
 
@@ -57,6 +295,7 @@
 	close_file();
 	reset_parameters();
 	delete asset;
+	delete frames_cache;
 }
 
 void File::reset_parameters()
@@ -76,6 +315,7 @@
 	normalized_sample = 0;
 	normalized_sample_rate = 0;
 	resample = 0;
+	frames_cache->reset();
 }
 
 
@@ -859,7 +1099,6 @@
 		result = return_frame;
 	}
 //printf("File::read_frame 6\n");
-
 	return result;
 }
 
@@ -897,43 +1136,69 @@
 					asset->height,
 					supported_colormodel);
 			}
-
+			
 //printf("File::read_frame 5 %d %d\n", 
 //	temp_frame->get_color_model(), 
 //	frame->get_color_model());
-			file->read_frame(temp_frame);
-			cmodel_transfer(frame->get_rows(), 
-				temp_frame->get_rows(),
-				0,
-				0,
-				0,
-				0,
-				0,
-				0,
-				0, 
-				0, 
-				temp_frame->get_w(), 
-				temp_frame->get_h(),
-				0, 
-				0, 
-				frame->get_w(), 
-				frame->get_h(),
-				temp_frame->get_color_model(), 
-				frame->get_color_model(),
-				0,
-				temp_frame->get_w(),
-				frame->get_w());
-//printf("File::read_frame 6\n");
+			VFrame *temp_frame2 = frames_cache->get_frame(current_frame, current_layer, asset->width, asset->height, supported_colormodel);
+			if (temp_frame2) 
+			{
+				delete temp_frame;
+				frame->copy_from(temp_frame2);
+				// cache is implicitly locked after a call to get_frame
+				frames_cache->unlock_cache();
+			} else
+			{
+				frames_cache->unlock_cache(); // cache is implicitly locked after a call to get_frame
+				file->read_frame(temp_frame);
+
+				cmodel_transfer(frame->get_rows(), 
+					temp_frame->get_rows(),
+					0,
+					0,
+					0,
+					0,
+					0,
+					0,
+					0, 
+					0, 
+					temp_frame->get_w(), 
+					temp_frame->get_h(),
+					0, 
+					0, 
+					frame->get_w(), 
+					frame->get_h(),
+					temp_frame->get_color_model(), 
+					frame->get_color_model(),
+					0,
+					temp_frame->get_w(),
+					frame->get_w());
+printf("File::read_frame 6\n");
+				frames_cache->add_frame(current_frame, current_layer, frame);
+				current_frame++;
+			}
 		}
 		else
 		{
 //printf("File::read_frame 7\n");
-			file->read_frame(frame);
+			VFrame *temp_frame2 = frames_cache->get_frame(current_frame, current_layer, asset->width, asset->height, frame->get_color_model());
+			if (temp_frame2) 
+			{
+				frame->copy_from(temp_frame2);
+				// cache is implicitly locked after a call to get_frame
+				frames_cache->unlock_cache();
+			} else
+			{
+				// cache is implicitly locked after a call to get_frame				
+				frames_cache->unlock_cache();
+				file->read_frame(frame);
+				frames_cache->add_frame(current_frame, current_layer, frame);
+				current_frame++;
+			}
 //printf("File::read_frame 8\n");
 		}
 
 //printf("File::read_frame 9\n");
-		current_frame++;
 //printf("File::read_frame 2 %d\n", supported_colormodel);
 		return 0;
 	}
diff -u hv/cinelerra/fileformat.C hvirtual-1.1.8/cinelerra/fileformat.C
--- hv/cinelerra/fileformat.C	2003-10-16 07:51:53.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/fileformat.C	2003-12-23 13:25:48.000000000 +0100
@@ -47,7 +47,7 @@
 int FileFormat::create_objects_(char *string2)
 {
 	FileSystem dir;
-	File file;
+	File file(mwindow->preferences);
 	char string[1024];
 	int x1 = 10, x2 = 180;
 	int x = x1, y = 10;
diff -u hv/cinelerra/file.h hvirtual-1.1.8/cinelerra/file.h
--- hv/cinelerra/file.h	2003-10-14 09:54:01.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/file.h	2003-12-23 14:19:31.000000000 +0100
@@ -16,15 +16,57 @@
 #include "resample.inc"
 #include "sema.h"
 #include "vframe.inc"
+#include "preferences.h"
 
-
+#include <map>
+#include "timer.h"
 // ======================================= include file types here
 
+
+class FrameCacheElement {
+public:
+	int frame_layer;
+	int frame_number;
+	long long time_diff;
+	VFrame *frame;
+};
+
+typedef std::multimap<int, FrameCacheElement*> FrameCacheTree;
+typedef std::multimap<long long, FrameCacheElement*> FrameCacheTree_ByTime;
+
+
+class FrameCache {
+public:
+	FrameCache(int64_t cache_size = 0);   // chache size is in bytes
+	~FrameCache();
+	VFrame *get_frame(long frame_number, int frame_layer, int frame_width, int frame_height, int color_model, int force_cache = 0); // implicit lock
+	void add_frame(long frame_number, int frame_layer, VFrame *frame, int do_not_copy_frame = 0, int force_cache = 0); 
+	void unlock_cache();
+	void lock_cache();
+	void reset();		
+	void disable_cache();
+	void enable_cache();
+	void dump();
+	
+private:
+	int compare_with_frame(FrameCacheElement *element, int frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
+	FrameCacheTree::iterator find_element_byframe(long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
+	FrameCacheTree_ByTime::iterator find_element_bytime(long long frame_time_diff, long frame_number, int frame_layer, int frame_width, int frame_height, int frame_color_model);
+	Mutex change_lock;
+	int cache_enabled;
+	int64_t cache_size;              // maximum cache size in bytes
+	int64_t memory_used;         // used memory in bytes
+	FrameCacheTree cache_tree;
+	FrameCacheTree_ByTime cache_tree_bytime;
+	Timer timer;
+};
+
+
 // generic file opened by user
 class File
 {
 public:
-	File();
+	File(Preferences *preferences);
 	~File();
 
 // Get attributes for various file formats.
@@ -185,6 +227,8 @@
 	int64_t normalized_sample;
 	int64_t normalized_sample_rate;
 
+	FrameCache *frames_cache;
+
 private:
 	void reset_parameters();
 
diff -u hv/cinelerra/formattools.C hvirtual-1.1.8/cinelerra/formattools.C
--- hv/cinelerra/formattools.C	2003-10-31 05:29:50.000000000 +0100
+++ hvirtual-1.1.8/cinelerra/formattools.C	2003-12-23 13:31:00.000000000 +0100
@@ -156,7 +156,7 @@
 		}
 
 //printf("FormatTools::create_objects 6\n");
-		aparams_thread = new FormatAThread(this);
+		aparams_thread = new FormatAThread(this, mwindow->preferences);
 	}
 
 //printf("FormatTools::create_objects 7\n");
@@ -185,7 +185,7 @@
 
 //printf("FormatTools::create_objects 10\n");
 		y += 10;
-		vparams_thread = new FormatVThread(this, lock_compressor);
+		vparams_thread = new FormatVThread(this, lock_compressor, mwindow->preferences);
 	}
 
 //printf("FormatTools::create_objects 11\n");
@@ -377,11 +377,11 @@
 }
 
 
-FormatAThread::FormatAThread(FormatTools *format)
+FormatAThread::FormatAThread(FormatTools *format, Preferences *preferences)
  : Thread()
 { 
 	this->format = format; 
-	file = new File;
+	file = new File(preferences);
 }
 
 FormatAThread::~FormatAThread() 
@@ -403,12 +403,13 @@
 
 
 FormatVThread::FormatVThread(FormatTools *format, 
-	int lock_compressor)
+	int lock_compressor, 
+	Preferences *preferences)
  : Thread()
 {
 	this->lock_compressor = lock_compressor;
 	this->format = format;
-	file = new File;
+	file = new File(preferences);
 }
 
 FormatVThread::~FormatVThread() 
diff -u hv/cinelerra/formattools.h hvirtual-1.1.8/cinelerra/formattools.h
--- hv/cinelerra/formattools.h	2003-10-14 09:54:01.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/formattools.h	2003-12-23 13:29:54.000000000 +0100
@@ -9,6 +9,7 @@
 #include "file.inc"
 #include "formatpopup.h"
 #include "mwindow.inc"
+#include "preferences.h"
 
 class FormatAParams;
 class FormatVParams;
@@ -140,7 +141,7 @@
 class FormatAThread : public Thread
 {
 public:
-	FormatAThread(FormatTools *format);
+	FormatAThread(FormatTools *format, Preferences *preferences);
 	~FormatAThread();
 	
 	void run();
@@ -152,7 +153,7 @@
 class FormatVThread : public Thread
 {
 public:
-	FormatVThread(FormatTools *format, int lock_compressor);
+	FormatVThread(FormatTools *format, int lock_compressor, Preferences *preferences);
 	~FormatVThread();
 	
 	void run();
diff -u hv/cinelerra/indexfile.C hvirtual-1.1.8/cinelerra/indexfile.C
--- hv/cinelerra/indexfile.C	2003-10-16 07:51:53.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/indexfile.C	2003-12-23 13:31:28.000000000 +0100
@@ -267,7 +267,7 @@
 	interrupt_flag = 0;
 
 // open the source file
-	File source;
+	File source(mwindow->preferences);
 	if(open_source(&source)) return 1;
 
 	asset->index_zoom = get_required_scale(&source);
diff -u hv/cinelerra/menueffects.C hvirtual-1.1.8/cinelerra/menueffects.C
--- hv/cinelerra/menueffects.C	2003-10-17 06:48:03.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/menueffects.C	2003-12-23 13:32:15.000000000 +0100
@@ -437,7 +437,7 @@
 		strcpy(asset->path, packet->path);
 
 		assets.append(asset);
-		File *file = new File;
+		File *file = new File(mwindow->preferences);
 
 // Open the output file after getting the information because the sample rate
 // is needed here.
diff -u hv/cinelerra/mwindow.C hvirtual-1.1.8/cinelerra/mwindow.C
--- hv/cinelerra/mwindow.C	2003-11-10 11:39:05.000000000 +0100
+++ hvirtual-1.1.8/cinelerra/mwindow.C	2003-12-23 13:33:00.000000000 +0100
@@ -740,7 +741,7 @@
 	for(int i = 0; i < filenames->total; i++)
 	{
 // Get type of file
-		File *new_file = new File;
+		File *new_file = new File(preferences);
 		Asset *new_asset = new Asset(filenames->values[i]);
 		EDL *new_edl = new EDL;
 		char string[BCTEXTLEN];
@@ -859,7 +860,7 @@
 				{
 // Recalculate length
 					delete new_file;
-					new_file = new File;
+					new_file = new File(preferences);
 					result = new_file->open_file(plugindb, new_asset, 1, 0, 0, 0);
 
 					if(load_mode != LOAD_RESOURCESONLY)
diff -u hv/cinelerra/packagerenderer.C hvirtual-1.1.8/cinelerra/packagerenderer.C
--- hv/cinelerra/packagerenderer.C	2003-11-04 09:21:16.000000000 +0100
+++ hvirtual-1.1.8/cinelerra/packagerenderer.C	2003-12-23 13:33:21.000000000 +0100
@@ -150,7 +150,7 @@
 	
 
 //printf("PackageRenderer::create_output 2\n");
-	file = new File;
+	file = new File(preferences);
 
 //printf("PackageRenderer::create_output 3\n");
 	file->set_processors(preferences->processors);
diff -u hv/cinelerra/performanceprefs.C hvirtual-1.1.8/cinelerra/performanceprefs.C
--- hv/cinelerra/performanceprefs.C	2003-10-25 09:37:15.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/performanceprefs.C	2003-12-23 12:51:00.000000000 +0100
@@ -48,8 +48,12 @@
 
 	y += 30;
 	add_subwindow(new BC_Title(x, y + 5, _("Cache items:"), MEDIUMFONT, BLACK));
-	sprintf(string, "%ld", pwindow->thread->preferences->cache_size);
-	add_subwindow(csize = new CICacheSize(x + 230, y, pwindow, string));
+	sprintf(string, "%ld", pwindow->thread->preferences->cache_items);
+	add_subwindow(citems = new CICacheItems(x + 230, y, pwindow, string));
+
+	add_subwindow(new BC_Title(x+ xmargin4, y + 5, _("Cache size per item (Mb):"), MEDIUMFONT, BLACK));
+	sprintf(string, "%ld", pwindow->thread->preferences->cache_size_per_item);
+	add_subwindow(cperitem = new CICachePerItem(x + 580, y, pwindow, string));
 	y += 30;
 	add_subwindow(new BC_Title(x, y + 5, _("Seconds to preroll renders:")));
 	PrefsRenderPreroll *preroll = new PrefsRenderPreroll(pwindow, 
@@ -306,18 +310,33 @@
 
 
 
-CICacheSize::CICacheSize(int x, int y, PreferencesWindow *pwindow, char *text)
+CICacheItems::CICacheItems(int x, int y, PreferencesWindow *pwindow, char *text)
+ : BC_TextBox(x, y, 100, 1, text)
+{ 
+	this->pwindow = pwindow; 
+}
+
+int CICacheItems::handle_event()
+{
+	int64_t result;
+
+	result = atol(get_text());
+	pwindow->thread->preferences->cache_items = result;
+	return 0;
+}
+
+CICachePerItem::CICachePerItem(int x, int y, PreferencesWindow *pwindow, char *text)
  : BC_TextBox(x, y, 100, 1, text)
 { 
 	this->pwindow = pwindow; 
 }
 
-int CICacheSize::handle_event()
+int CICachePerItem::handle_event()
 {
 	int64_t result;
 
 	result = atol(get_text());
-	pwindow->thread->preferences->cache_size = result;
+	pwindow->thread->preferences->cache_size_per_item = result;
 	return 0;
 }
 
diff -u hv/cinelerra/performanceprefs.h hvirtual-1.1.8/cinelerra/performanceprefs.h
--- hv/cinelerra/performanceprefs.h	2003-10-14 09:54:02.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/performanceprefs.h	2003-12-23 12:46:03.000000000 +0100
@@ -1,7 +1,8 @@
 #ifndef PERFORMANCEPREFS_H
 #define PERFORMANCEPREFS_H
 
-class CICacheSize;
+class CICacheItems;
+class CICachePerItem;
 
 #include "formattools.inc"
 #include "mwindow.inc"
@@ -25,7 +26,8 @@
 
 	int hot_node;
 
-	CICacheSize *csize;
+	CICacheItems *citems;
+	CICachePerItem *cperitem;
 
 	ArrayList<BC_ListBoxItem*> nodes[4];
 	PrefsRenderFarmEditNode *edit_node;
@@ -277,16 +279,19 @@
 
 
 
+class CICacheItems : public BC_TextBox
+{
+public:
+	CICacheItems(int x, int y, PreferencesWindow *pwindow, char *text);
+	int handle_event();
+	PreferencesWindow *pwindow;
+};
 
 
-
-
-
-
-class CICacheSize : public BC_TextBox
+class CICachePerItem : public BC_TextBox
 {
 public:
-	CICacheSize(int x, int y, PreferencesWindow *pwindow, char *text);
+	CICachePerItem(int x, int y, PreferencesWindow *pwindow, char *text);
 	int handle_event();
 	PreferencesWindow *pwindow;
 };
diff -u hv/cinelerra/preferences.C hvirtual-1.1.8/cinelerra/preferences.C
--- hv/cinelerra/preferences.C	2003-10-24 05:22:17.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/preferences.C	2003-12-23 12:58:50.000000000 +0100
@@ -35,7 +35,8 @@
 	sprintf(index_directory, BCASTDIR);
 	if(strlen(index_directory))
 		fs.complete_path(index_directory);
-	cache_size = 5;
+	cache_items = 5;
+	cache_size_per_item = 2;
 	index_size = 3000000;
 	index_count = 100;
 	use_thumbnails = 1;
@@ -117,7 +118,8 @@
 	strcpy(global_plugin_dir, that.global_plugin_dir);
 	strcpy(theme, that.theme);
 
-	cache_size = that.cache_size;
+	cache_items = that.cache_items;
+	cache_size_per_item = that.cache_size_per_item;
 	force_uniprocessor = that.force_uniprocessor;
 	processors = calculate_processors();
 	renderfarm_nodes.remove_all_objects();
@@ -160,7 +162,8 @@
 	}
 	
 	renderfarm_job_count = MAX(renderfarm_job_count, 1);
-	CLAMP(cache_size, 1, 100);
+	CLAMP(cache_items, 1, 100);
+	CLAMP(cache_size_per_item, 0, 128);
 
 	return *this;
 }
@@ -199,7 +202,8 @@
 	processors = calculate_processors();
 	use_brender = defaults->get("USE_BRENDER", use_brender);
 	brender_fragment = defaults->get("BRENDER_FRAGMENT", brender_fragment);
-	cache_size = defaults->get("CACHE_SIZE", cache_size);
+	cache_items = defaults->get("CACHE_SIZE", cache_items);
+	cache_size_per_item = defaults->get("CACHE_SIZE_PER_ITEM", cache_size_per_item);
 	local_rate = defaults->get("LOCAL_RATE", local_rate);
 	use_renderfarm = defaults->get("USE_RENDERFARM", use_renderfarm);
 	renderfarm_port = defaults->get("RENDERFARM_PORT", renderfarm_port);
@@ -243,7 +247,8 @@
 int Preferences::save_defaults(Defaults *defaults)
 {
 	char string[BCTEXTLEN];
-	defaults->update("CACHE_SIZE", cache_size);
+	defaults->update("CACHE_SIZE", cache_items);
+	defaults->update("CACHE_SIZE_PER_ITEM", cache_size_per_item);
 	defaults->update("INDEX_DIRECTORY", index_directory);
 	defaults->update("INDEX_SIZE", index_size);
 	defaults->update("INDEX_COUNT", index_count);
diff -u hv/cinelerra/preferences.h hvirtual-1.1.8/cinelerra/preferences.h
--- hv/cinelerra/preferences.h	2003-10-14 09:54:02.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/preferences.h	2003-12-23 12:34:38.000000000 +0100
@@ -63,7 +63,10 @@
 // Number of frames in a brender job.
 	int brender_fragment;
 // Number of items to store in cache
-	int64_t cache_size;
+	int64_t cache_items;
+// Number of megabytes for thumbnail cache - per item
+	int cache_size_per_item;
+
 	int use_renderfarm;
 	int renderfarm_port;
 // If the node starts with a / it's on the localhost using a path as the socket.
diff -u hv/cinelerra/record.C hvirtual-1.1.8/cinelerra/record.C
--- hv/cinelerra/record.C	2003-11-10 02:40:16.000000000 +0100
+++ hvirtual-1.1.8/cinelerra/record.C	2003-12-23 13:33:59.000000000 +0100
@@ -621,7 +621,7 @@
 		Batch *batch = get_current_batch();
 		delete_output_file();
 
-		file = new File;
+		file = new File(mwindow->preferences);
 		result = file->open_file(mwindow->plugindb, 
 			batch->get_current_asset(), 
 			0, 
diff -u hv/cinelerra/resourcepixmap.C hvirtual-1.1.8/cinelerra/resourcepixmap.C
--- hv/cinelerra/resourcepixmap.C	2003-10-16 07:52:28.000000000 +0200
+++ hvirtual-1.1.8/cinelerra/resourcepixmap.C	2003-12-23 15:58:58.000000000 +0100
@@ -740,15 +740,79 @@
 //project_frame, frame_w, refresh_x, refresh_w, x);
 	while(x < refresh_x + refresh_w)
 	{
+		int cache_hit; // so we know whether to relase a lock at the end or was it already
+		VFrame *final_picon_frame;
 		int64_t source_frame = project_frame + edit->startsource;
 		source->set_layer(edit->channel);
 		source->set_video_position(source_frame, 
 			mwindow->edl->session->frame_rate);
 //printf("ResourcePixmap::draw_video_resource 3 %p\n", source);
-		VFrame *src = source->read_frame(BC_RGB888);
+//		VFrame *src = source->read_frame(BC_RGB888);
 //printf("ResourcePixmap::draw_video_resource 4 %p\n", src);
-		if(src)
-			draw_vframe(src, 
+		if ((final_picon_frame = source->frames_cache->get_frame(source->current_frame,
+									source->current_layer,
+									picon_w,
+									picon_h,
+									BC_RGB888,
+									1)))      // force cache
+		{
+			cache_hit = 1;
+			
+		} else
+		{
+			source->frames_cache->unlock_cache(); // implicitly locked after a call to get_frame
+			cache_hit = 0;	
+			long now_current_frame = source->current_frame;
+ //			Timer a;
+ //			a.update();
+			VFrame *src = source->read_frame(BC_RGB888);
+			if (src) 
+			{
+				final_picon_frame = new VFrame (0, 
+							picon_w,
+							picon_h,
+							BC_RGB888);
+				cmodel_transfer(final_picon_frame->get_rows(), 
+					src->get_rows(),
+					final_picon_frame->get_y(),
+					final_picon_frame->get_u(),
+					final_picon_frame->get_v(),
+					src->get_y(),
+					src->get_u(),
+					src->get_v(),
+					0, 
+					0, 
+					src->get_w(), 
+					src->get_h(),
+					0, 
+					0, 
+					picon_w, 
+					picon_h,
+					src->get_color_model(), 
+					BC_RGB888,
+					0,
+					src->get_w(),
+					picon_w);
+	
+				source->frames_cache->add_frame(now_current_frame,
+								source->current_layer,
+								final_picon_frame,
+								1, // do not do a copy of frame, keep this one
+								1); // force the caching, even if cache is disabled
+ //				printf("Timer: %lli\n", a.get_difference());
+	
+			} else 
+			{
+				final_picon_frame = 0;
+			}
+		}
+		
+
+
+//		if(src)
+//			draw_vframe(src, 
+		if(final_picon_frame)
+			draw_vframe(final_picon_frame, 
 				x, 
 				y, 
 				picon_w, 
@@ -756,6 +820,9 @@
 				0, 
 				0);
 
+		if (cache_hit) {
+			source->frames_cache->unlock_cache(); // cache is implicitly locked after a call to get_frame
+		}
 		
 		
 		
