Back to index

lightning-sunbird  0.9+nobinonly
Classes | Typedefs | Functions
nsSanePlugin.h File Reference
#include "prthread.h"
#include "nscore.h"
#include "nsplugin.h"
#include "gdksuperwin.h"
#include "gtkmozbox.h"
#include "gtk/gtk.h"
#include "nsIPlugin.h"
#include "nsSanePluginControl.h"
#include "nsIScriptContext.h"
#include "nsIServiceManager.h"
#include "nsISupports.h"
#include "nsISupportsUtils.h"
#include "nsIEventQueueService.h"
#include "nsIEventQueue.h"
#include <jpeglib.h>
#include <sane/sane.h>
#include <sane/sanei.h>
#include <sane/saneopts.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _PlatformInstance
class  nsSanePluginInstance
class  nsSanePluginStreamListener

Typedefs

typedef struct _PlatformInstance PlatformInstance

Functions

void PR_CALLBACK scanimage_thread_routine (void *arg)

Class Documentation

struct _PlatformInstance

Definition at line 77 of file nsSanePlugin.h.

Collaboration diagram for _PlatformInstance:
Class Members
Display * display
uint32 height
int placeholder
GdkSuperWin * superwin
GtkWidget * widget
uint32 width
Window window
uint16 x
uint16 y

Typedef Documentation


Function Documentation

Definition at line 2397 of file nsSanePlugin.cpp.

{
    nsSanePluginInstance * pthis = (nsSanePluginInstance *)arg;

    nsresult rv;
    SANE_Status status;
    SANE_Parameters param;
    int len;
    FILE * out;
    SANE_Byte * buf;
    JSAMPROW row_pointer[1];
    char *fname;

    // JPEG stuff
    struct jpeg_compress_struct cinfo;
       struct jpeg_error_mgr jerr;

       // Error handling
    jerr.error_exit = my_jpeg_error_exit; // fatal errors
       cinfo.err = jpeg_std_error(&jerr);

       jpeg_create_compress(&cinfo);

    rv = pthis->OpenSaneDeviceIF();
    if (rv != NS_OK)
        goto error_exit;

    // open image file
    fname = pthis->GetImageFilename();
    if (!fname)
        goto error_exit;
    out = fopen(fname, "wb");
    PR_FREEIF(fname);
    if (out == NULL) {
        NS_ERROR("Unable to open mImageFilename!\n");
        sane_cancel(pthis->mSaneHandle);
        goto error_exit;       
    }
    jpeg_stdio_dest(&cinfo, out);

    status = sane_start(pthis->mSaneHandle);
    if (status != SANE_STATUS_GOOD) {
        NS_ERROR("Error trying to start sane device!");
        goto error_exit;
    }

    status = sane_get_parameters(pthis->mSaneHandle, &param);
    if (status != SANE_STATUS_GOOD) {
        NS_ERROR("Error trying to get image parameters!\n");
        sane_cancel(pthis->mSaneHandle);
        goto error_exit;
    }
    cinfo.image_width = param.pixels_per_line;
    cinfo.image_height = param.lines;

    switch (param.format) {
    case SANE_FRAME_RED:
    case SANE_FRAME_GREEN:
    case SANE_FRAME_BLUE:
        // NOT Supported!
        NS_ERROR("Multiframe devices not supported!\n");
        sane_cancel(pthis->mSaneHandle);
        goto error_exit;
        break;
                
    case SANE_FRAME_RGB:
        cinfo.input_components = 3;
        cinfo.in_color_space = JCS_RGB;
        break;

    case SANE_FRAME_GRAY:
        cinfo.input_components = 1;
        cinfo.in_color_space = JCS_GRAYSCALE;
        break;
    }
    jpeg_set_defaults(&cinfo); 
    cinfo.dct_method = pthis->mCompMethod; 
    jpeg_set_quality(&cinfo, pthis->mCompQuality, FALSE);
    jpeg_start_compress(&cinfo, TRUE);

    buf = (SANE_Byte *)PR_MALLOC(param.bytes_per_line);
    if (!buf) {
        NS_ERROR("Error trying to allocate buffer!\n");
        jpeg_destroy_compress(&cinfo);
        fclose(out);
        sane_cancel(pthis->mSaneHandle);
        goto error_exit;
    }

    int total;
    while(1) {
        total = 0;
        while (total < param.bytes_per_line) {
            // Read in data from sane device
            status = sane_read(pthis->mSaneHandle, buf + total, 
                               param.bytes_per_line - total, 
                               &len);
            if (status != SANE_STATUS_GOOD) {
                if (status == SANE_STATUS_EOF)
                    // done with this frame
                    goto finished_scan;
                else {
                    NS_ERROR("Error trying to read from sane device!\n");
                    PR_FREEIF(buf);
                    jpeg_destroy_compress(&cinfo);
                    fclose(out);
                    sane_cancel(pthis->mSaneHandle);
                    goto error_exit;
                }
            }
            total += len;
        }

        row_pointer[0] = (JSAMPLE *) buf;
        jpeg_write_scanlines(&cinfo, row_pointer, 1); 

    } // end while

    // cleanup
 finished_scan:
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    PR_FREEIF(buf);
    sane_cancel(pthis->mSaneHandle);
    fclose(out);
    pthis->SetSuccess(PR_TRUE); // allow caller to check for success

 error_exit:

    // Call onScanComplete callback in the UI thread

    nsCOMPtr<nsIEventQueue> eventQ;

    // Get the event queue of the current thread...
    nsCOMPtr<nsIEventQueueService> eventQService = 
             do_GetService(kEventQueueService, &rv);
    if (NS_FAILED(rv)) {
        NS_ERROR("Unable to get event queue service!\n");
        return;
    }

    rv = eventQService->GetThreadEventQueue(pthis->mUIThread,
                                            getter_AddRefs(eventQ));
    if (NS_FAILED(rv)) {
        NS_ERROR("Unable to get thread queue!\n");
        return;
    }

    PLEvent *event = new PLEvent;
    if (!event) {
        NS_ERROR("Unable to create new event!\n");
        return;
    }

    // ThreadHandleEvent will now execute in the UI thread.
    PL_InitEvent(event, 
                 pthis,
                 (PLHandleEventProc)  ThreadedHandleEvent,
                 (PLDestroyEventProc) ThreadedDestroyEvent);

    if (NS_FAILED(eventQ->PostEvent(event))) {
        NS_ERROR("Error trying to post event!\n");
        PL_DestroyEvent(event);
        return;
    }
}

Here is the call graph for this function: