[Xprint] Application printing using Xprint

Roland Mainz roland.mainz at nrubsig.org
Sun Apr 24 00:59:36 EDT 2005


Martin Deppe wrote:
> I just subscribed to this list because I got xprint knowing a few days
> ago and tried to create little program using xprint to print something
> from inside my application.
> 
> I have been looking for the documentation of the client functions and
> some sample source code. I found something, but nothing that really
> helped me to finish my little applictation successfully.
> 
> I hope my "problem" is very easy to answer and the answer is as easy as
> the question. Maybe someone can point me to some sample source code in
> which a connection to the X print server is being established, some more
> initializations are done, a job is being started, a page is being
> opened, some output (such as text and - more important - graphics, such
> as lines and points) is being done and then everything that has been
> started is being completed so that the data can be show on my printer.
> 
> What I found were some sources that needed GL-something, xpu-something,
> xpt-something or whatever, which I didn't have and didn't find. The
> xprintutils, which I downloaded didn't compile so that I couldn't use
> them as a blueprint for my own application.

Which compile error did you get for the XprintUtils stuff ?

> Here is the code I wanted to use to print some lines on the printer:
> -----------------------------------------------------------------------------------------------------------------------------
> void printDrawing(void)
> {
>    Display    *pdsp;
>    Window      pwin;
>    Screen     *pScreen;
>    XPContext   pContext;
>    XGCValues values;
>    unsigned long valuemask = 0;
>    GC          gc;
>    XRectangle  rect;
>    unsigned short width, height;
>    int rc;
> 
>    if (!printingAvailable)
>    {
>       chkPrinter(0);
>       return;
>    }
> 
>    pdsp = XOpenDisplay(":33");

Uhm... you may want to use the XprintUtils libraries's |XpuGetPrinter()|
instead of |XOpenDisplay()| - the XprintUtils function parses the
XPSERVLIST/LPDEST environment variables and returns a |Display *| and
|XPContext| based on the name given as argument (if you don't give an
argument it just uses the default printer as defined by |LPDEST|&co.,
otherwise the first printer in the list returns by the first Xprint
server specified by XPSERVERLIST).
The XprintUtils source can be found at
http://cvs.freedesktop.org/xorg/xc/lib/XprintUtil/ (this is no dynamic
library yet as the API is not stable (yet), just add it to your
codebase... :)

>    if (pdsp == NULL)
>    {
>       fprintf(stderr, "could not connect to X printserver (again)\n");
>       return;
>    }
> 
>    pContext = XpCreateContext(pdsp, prtName);
>    fprintf(stderr, "pContext=%d\n", pContext);
>    XpSetContext(pdsp, pContext); // void XpSetContext()
>    gc = XCreateGC(pdsp, pwin, valuemask, &values);

|pwin| seems to be undefined at this point... that cannot work...

>    fprintf(stderr, "XCreateGC()=%d\n", gc); // debug output
>    if (gc < 0)
>       fprintf(stderr, "XCreateGC failed - cannot process print request\n");

Uhm... AFAIK this should be |gc == 0| (or |gc == None| - which is the
same) ...

>    else
>    {
>       XpStartJob(pdsp, XPSpool); // void XpStartJob()
>       fprintf(stderr, "XpStartJob()\n"); // debug output
> 
>       // Generate the first page
>       pScreen = XpGetScreenOfContext(pdsp, pContext);
>       fprintf(stderr, "XpGetScreen()=%d\n", pScreen); // debug output
>       fprintf(stderr, "XpGetPageDimensions()=%d\n",
> XpGetPageDimensions(pdsp, pContext, &width, &height, &rect)); // debug
> output included
>       pwin = XCreateSimpleWindow(pdsp, RootWindowOfScreen(pScreen),
>                                  rect.x, rect.y, rect.width, rect.height, 2,
>                                  BlackPixelOfScreen(pScreen),
>                                  WhitePixelOfScreen(pScreen));
>       fprintf(stderr, "pwin=%d\n", pwin); // debug output
> 
>       XpStartPage(pdsp, pwin);
>       fprintf(stderr, "XDrawLine=%d\n", XDrawLine(pdsp, pwin, gc, 20,
> 20, 120, 120));
>       fprintf(stderr, "XDrawLine=%d\n", XDrawLine(pdsp, pwin, gc, 120,
> 120, 20, 20));
>       fprintf(stderr, "XDrawLine=%d\n", XDrawLine(pdsp, pwin, gc, 20,
> 20, 120, 20));
>       fprintf(stderr, "XDrawLine=%d\n", XDrawLine(pdsp, pwin, gc, 20,
> 120, 120, 120));
> 
>       XpEndPage(pdsp);
>       XFreeGC(pdsp, gc); /* free the GC */
> 
>       // End the print job - the final results are sent by the X print
> server to the spooler sub system.
>       XpEndJob(pdsp);

AFAIK you should always wait here for the |XPEndJobNotify| event -
otherwise the |XpDestroyContext()| may kill the print job while it is
being prepared for spooling.

Normally the sequence looks like this:
-- snip --
XpEndJob(xparms.d);
XpuWaitForPrintNotify(xparms.d, xparms.xp_event_base,
XPEndJobNotify);    
<do more cleanup if you were printing to a file>
XpDestroyContext()
-- snip --

>    }
>    XpDestroyContext(pdsp, pContext);
>    XCloseDisplay(pdsp);
> }
> -----------------------------------------------------------------------------------------------------------------------------
> 
> I hope that the code is not to confusing and someone can tell me, why I
> get some response from the printer, but no page out of it.

See above - you created an invalid GC which could not be used
afterwards. Additionally you didn't wait for print job completion which
may lead to a race condition - depending on the time the finalisation
needed you may not get a print job delivered to the printer (I've seen
that with Hitatchis Xprint server where the OpenGL engine runs in a
seperate thread and therefore the GL rendering may complete async to the
main server rendering).

> I could connect to the X print server and get a list of my available
> printers. I could start a job and a page, but I didn't get anything else
> out of the printer than the initialization of it, after which it simply
> stopped doing anything again, as if I wouldn't have done anything.
> 
> The debug output of this code was:
> -----------------------------------------------------------------------------------------------------------------------------
> pContext=2097153
> XCreateGC()=134588832
> 1: X-Server Error code: BadDrawable (invalid Pixmap or Window parameter)

The bad thing happens here already with the GC...

> XpStartJob()
> XpGetScreen()=134588368
> XpGetPageDimensions()=1
> pwin=2097155
> XDrawLine=1
> XDrawLine=1
> XDrawLine=1
> XDrawLine=1
> 2: X-Server Error code: BadGC (invalid GC parameter)
> 3: X-Server Error code: BadGC (invalid GC parameter)
> -----------------------------------------------------------------------------------------------------------------------------

BTW: See
http://cvs.freedesktop.org/xorg/xc/programs/xphelloworld/xpsimplehelloworld/xpsimplehelloworld.c?rev=1.4&view=markup
for the source code of a similar example...

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz at nrubsig.org
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 7950090
 (;O/ \/ \O;)


More information about the Xprint mailing list