/* 
    Webcam Lab

    This program 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.

    This program 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; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    (C) 2005 Jason Hunt
    nulluser@gmail.com
    
    file: camera.cpp
*/


#include <windows.h>
#include <stdio.h>

#include "types.h"
#include "window.h"
#include "display.h"
#include "vfwmod.h"

extern HWND main_win;
extern HDC main_dc;

HWND capture_win = NULL;                // Handle to the capture window

int camera_x_size = 0;         // Size of camera image
int camera_y_size = 0;

color_type *camera_buffer = NULL;       // Buffer for camera data
BITMAPINFO camera_buffer_info;          // Bitmap info for camera

bool running = true;                    // True if we are pulling frames  

bool fast_capture = false;

/* This is called when the capture is done */
static LRESULT CALLBACK frame_callback(HWND hWnd, LPVIDEOHDR lpVHdr)
{
    if (camera_buffer == NULL) return(true);
 
    if (!fast_capture) return(true);
     
    // Turn stream data into a bitmap
    HBITMAP tmp_bitmap = CreateBitmap(camera_x_size, camera_y_size, 1, 24, lpVHdr->lpData);

    // Transfor into image array
    GetDIBits(main_dc, tmp_bitmap, 0, camera_y_size, camera_buffer, &camera_buffer_info, DIB_RGB_COLORS);
      
    DeleteObject(tmp_bitmap);

    return(true); 
}
/* End of frame_callback */


/* Get a fram from the camera */
void camera_frame(void)
{
    if (!capture_win || !camera_buffer || !running) return;
         
    capGrabFrame(capture_win);  // Capture frame and wait for callback

    if (!fast_capture)
    {    
        capEditCopy(capture_win);
			
        OpenClipboard(NULL);
	
        HBITMAP tmp =(HBITMAP) GetClipboardData(CF_BITMAP);
	
        CloseClipboard();
	
        // Transfor into image array
        GetDIBits(main_dc, tmp, 0, camera_y_size, camera_buffer, &camera_buffer_info, DIB_RGB_COLORS);
       	
        DeleteObject(tmp);
    }
}
/* End of get frame */



/* Setup buffer for camera image */
void camera_setup_buffer( void )
{    
    if (camera_buffer != NULL) free(camera_buffer);    

    camera_buffer = (color_type *) malloc(camera_x_size * camera_y_size * sizeof(color_type));
        
    if (camera_buffer == NULL)
    {            
        add_line("Unable to create camera buffer");
        return;
    }        

    // Set the new Bitmap information
    camera_buffer_info.bmiHeader.biSize = sizeof(camera_buffer_info.bmiHeader);
    camera_buffer_info.bmiHeader.biWidth = camera_x_size;
    camera_buffer_info.bmiHeader.biHeight = camera_y_size; 
    camera_buffer_info.bmiHeader.biPlanes = 1;
    camera_buffer_info.bmiHeader.biBitCount = 32;
    camera_buffer_info.bmiHeader.biCompression = BI_RGB;
    camera_buffer_info.bmiHeader.biSizeImage = camera_x_size * camera_y_size  * 4;
    camera_buffer_info.bmiHeader.biClrUsed = 0;
    camera_buffer_info.bmiHeader.biClrImportant = 0;

}
/* End of camera_setup_buffer */


/* Setup the camera buffers and parameters */
void setup_camera( bool ask_info)
{        
    // Get video format information

    if (ask_info)
    {
        capDlgVideoSource(capture_win);
        capDlgVideoFormat(capture_win);         
    }

    // Get video format information
    capGetVideoFormat(capture_win, &camera_buffer_info, sizeof(camera_buffer_info));
   
    char buff[400];
    sprintf(buff, "Size (%dx%d)", camera_buffer_info.bmiHeader.biWidth,
                                  camera_buffer_info.bmiHeader.biHeight);
    add_line(buff);

    camera_x_size = camera_buffer_info.bmiHeader.biWidth;
    camera_y_size = camera_buffer_info.bmiHeader.biHeight;   
  
    camera_setup_buffer();
}
/* End of setup camera */



/* Start camera system */
void camera_start( void )
{
    char buff[400];

   //add_line("Init camera");      

    // Debug:
    //    capture_win = capCreateCaptureWindow ("Webcam", WS_VISIBLE, 0, 0, 640, 480,

    capture_win = capCreateCaptureWindow ("Webcam", 0, 0, 0, 640, 480,
                                           HWND_DESKTOP, 0); 
                    
    if (!capture_win)
    {
        add_line("Unable to create capture window");
        return;
    }

    // Setup Frame callback 
    capSetCallbackOnFrame(capture_win, frame_callback);
               
   // Used for displaying a list of devices 
    char device_name[80];
    char device_version[80];
    for (int i = 0; i < 10; i++)
        if (capGetDriverDescription (i, device_name, sizeof (device_name), 
                                             device_version, sizeof (device_version)))
        { 
            sprintf(buff, "Device: %d %s", i, device_name);
            add_line(buff);                      
        }

    
    int device_num = 0;
    
    // Read the device number from file
    FILE *f = fopen("device.txt", "rt");

    if (f != NULL)
    {
        fscanf(f, "%d", &device_num);
        fclose(f);    
    }
    
    sprintf(buff, "Using device %d", device_num);
    add_line(buff);

    capDriverConnect(capture_win, 0);       // connect to driver    

   // capPreviewRate(capture_win, 1);         // Max preview rate
   // capPreview(capture_win, FALSE);          // Show preview     

    setup_camera(false);   // setup buffers
}
/* End of Start camera */



/* Stop camera system */
void camera_stop( void )
{
    if (camera_buffer)
        free(camera_buffer);      

    if (!capture_win) return;

    SendMessage(capture_win, WM_CAP_DRIVER_DISCONNECT, 0, 0);   
}
/* End of stop_camera */







