status_t
MovieEncoder::Encode()
{
	int32 framesLeft = fFileList->CountItems();
	int32 framesWritten = 0;
	
	if (framesLeft <= 0) {
		DisposeData();
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)B_ERROR);
		fMessenger.SendMessage(&message);
		return B_ERROR;
	}
	
	// Create movie
	char movieName[B_FILE_NAME_LENGTH];
	MakeUniqueName(fOutputFile.Path(), movieName, B_FILE_NAME_LENGTH);
	entry_ref movieRef;
	get_ref_for_path(movieName, &movieRef);
	
	media_file_format fileFormat;
	if (!GetMediaFileFormat(fFamily, fileFormat)) {
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)B_ERROR);
		fMessenger.SendMessage(&message);
		return B_ERROR;
	}
	
	BBitmap* bitmap = BTranslationUtils::GetBitmapFile(fFileList->ItemAt(0));
	BRect sourceFrame = bitmap->Bounds();
	delete bitmap;
		
	if (!fDestFrame.IsValid())
		fDestFrame = sourceFrame.OffsetToCopy(B_ORIGIN);
				
	BitmapMovie* movie = new BitmapMovie(fDestFrame.IntegerWidth() + 1,
					fDestFrame.IntegerHeight() + 1, fColorSpace);
				
	status_t error = movie->CreateFile(movieRef, fileFormat, fFormat, fCodecInfo);
	if (error < B_OK) {
		delete movie;
		DisposeData();
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)error);
		fMessenger.SendMessage(&message);		
		return error;
	}
		
	// Bitmap and view used to convert the source bitmap
	// to the correct size and depth	
	BBitmap* destBitmap = new BBitmap(fDestFrame, fColorSpace, true);
	BView* destDrawer = new BView(fDestFrame, "drawing view", B_FOLLOW_NONE, 0);
	if (destBitmap->Lock()) {
		destBitmap->AddChild(destDrawer);
		destBitmap->Unlock();
	}
	
	const uint32 keyFrameFrequency = 10;
	
	BMessage progressMessage(B_UPDATE_STATUS_BAR);
	progressMessage.AddFloat("delta", 1.0);
	bool keyFrame = true;		
	for (int32 i = 0; i < fFileList->CountItems(); i++) {
		if (framesWritten % keyFrameFrequency == 0)
			keyFrame = true;
		const char* fileName = fFileList->ItemAt(i);
		BBitmap* frame = BTranslationUtils::GetBitmapFile(fileName);
		if (frame == NULL)
			continue;
						
		// Draw scaled
		if (error == B_OK) {
			destBitmap->Lock();
			destDrawer->DrawBitmap(frame, frame->Bounds(), destDrawer->Bounds());
			destDrawer->Sync();
			destBitmap->Unlock();
		}
		
		delete frame;
			
		if (error == B_OK)
			error = movie->WriteFrame(destBitmap, keyFrame);
		
		if (error == B_OK) {
			framesWritten++;
			keyFrame = false;				
		} else {
			printf("%s\n", strerror(error));
			break;
		}
		
		if (fMessenger.IsValid())
			fMessenger.SendMessage(new BMessage(progressMessage));		
	}
	
	//printf("%ld frames written\n", framesWritten);
		
	delete movie;
	delete destBitmap;
	//delete cursor;
	
	DisposeData();
	
	BMessage message(kEncodingFinished);
	message.AddInt32("status", (int32)B_OK);
	fMessenger.SendMessage(&message);
		
	return B_OK;
}
status_t
MovieEncoder::Encode()
{	
	int32 framesLeft = fFileList->CountItems();
	int32 framesWritten = 0;
	
	if (framesLeft <= 0) {
		DisposeData();
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)B_ERROR);
		fMessenger.SendMessage(&message);
		return B_ERROR;
	}
	
	// Create movie
	char movieName[B_FILE_NAME_LENGTH];
	MakeUniqueName(fOutputFile.Path(), movieName, B_FILE_NAME_LENGTH);
	entry_ref movieRef;
	get_ref_for_path(movieName, &movieRef);
	
	BBitmap* bitmap = BTranslationUtils::GetBitmapFile(fFileList->ItemAt(0));
	BRect sourceFrame = bitmap->Bounds();
	delete bitmap;
		
	if (!fDestFrame.IsValid())
		fDestFrame = sourceFrame.OffsetToCopy(B_ORIGIN);
				
	BitmapMovie* movie = new BitmapMovie(fDestFrame.IntegerWidth() + 1,
					fDestFrame.IntegerHeight() + 1, fColorSpace);
				
	status_t status = movie->CreateFile(movieRef, fFileFormat, fFormat, fCodecInfo);
	if (status < B_OK) {
		delete movie;
		DisposeData();
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)status);
		fMessenger.SendMessage(&message);		
		return status;
	}
		
	// Bitmap and view used to convert the source bitmap
	// to the correct size and depth	
	BBitmap* destBitmap = new BBitmap(fDestFrame, fColorSpace, true);
	BView* destDrawer = new BView(fDestFrame, "drawing view", B_FOLLOW_NONE, 0);
	if (destBitmap->Lock()) {
		destBitmap->AddChild(destDrawer);
		destBitmap->Unlock();
	}
	
	const uint32 keyFrameFrequency = 10;
		// TODO: Make this tunable
	
	BMessage progressMessage(B_UPDATE_STATUS_BAR);
	progressMessage.AddFloat("delta", 1.0);
	
	status = B_OK;
	for (int32 i = 0; i < fFileList->CountItems(); i++) {
		bool keyFrame = (framesWritten % keyFrameFrequency == 0);
		const char* fileName = fFileList->ItemAt(i);
		BBitmap* frame = BTranslationUtils::GetBitmapFile(fileName);
		if (frame == NULL) {
			// TODO: What to do here ? Exit with an error ?
			continue;
		}
						
		// Draw scaled
		if (status == B_OK) {
			destBitmap->Lock();
			destDrawer->DrawBitmap(frame, frame->Bounds(), destDrawer->Bounds());
			destDrawer->Sync();
			destBitmap->Unlock();
		}
		
		delete frame;
			
		if (status == B_OK)
			status = movie->WriteFrame(destBitmap, keyFrame);
		
		if (status != B_OK)
			break;

		framesWritten++;

		if (fMessenger.IsValid())
			fMessenger.SendMessage(new BMessage(progressMessage));		
	}

	delete movie;
	delete destBitmap;
	
	DisposeData();
	
	if (fMessenger.IsValid()) {
		BMessage message(kEncodingFinished);
		message.AddInt32("status", (int32)status);
		message.AddInt32("frames", (int32)framesWritten);
		fMessenger.SendMessage(&message);
	}
		
	return status;
}