For Michael Pfeiffer, ready for beta...
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1108 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
dd6a407346
commit
8f13f87bf7
@ -7,6 +7,8 @@
|
||||
// very specific functions, but generally useful (could be here because of a
|
||||
// lack in the APIs, or just sheer lazyness :))
|
||||
//
|
||||
// Author
|
||||
// Ithamar R. Adema
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
|
@ -1,10 +1,76 @@
|
||||
/*****************************************************************************/
|
||||
// BeUtils.cpp
|
||||
//
|
||||
// Version: 1.0.0d1
|
||||
//
|
||||
// Several utilities for writing applications for the BeOS. It are small
|
||||
// very specific functions, but generally useful (could be here because of a
|
||||
// lack in the APIs, or just sheer lazyness :))
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2001 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef BEUTILS_H
|
||||
#define BEUTILS_H
|
||||
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
status_t TestForAddonExistence(const char* name, directory_which which,
|
||||
const char* section, BPath& outPath);
|
||||
|
||||
// Reference counted object
|
||||
class Object {
|
||||
private:
|
||||
volatile int32 fRefCount;
|
||||
|
||||
public:
|
||||
// After construction reference count is 1
|
||||
Object() : fRefCount(1) { }
|
||||
// dtor should be private, but ie. ObjectList requires a public dtor!
|
||||
virtual ~Object() { };
|
||||
|
||||
// thread-safe as long as thread that calls acquire has already
|
||||
// a reference to the object
|
||||
void Acquire() {
|
||||
atomic_add(&fRefCount, 1);
|
||||
}
|
||||
|
||||
bool Release() {
|
||||
atomic_add(&fRefCount, -1);
|
||||
if (fRefCount == 0) {
|
||||
delete this; return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,8 @@ Server
|
||||
PrintServerApp.Scripting.cpp
|
||||
Printer.Scripting.cpp
|
||||
Printer.cpp
|
||||
ResourceManager.cpp
|
||||
Jobs.cpp
|
||||
BeUtils.cpp
|
||||
;
|
||||
|
||||
|
307
src/servers/print/Jobs.cpp
Normal file
307
src/servers/print/Jobs.cpp
Normal file
@ -0,0 +1,307 @@
|
||||
/*****************************************************************************/
|
||||
// Jobs
|
||||
//
|
||||
// Author
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#include "pr_server.h"
|
||||
#include "Jobs.h"
|
||||
#include "PrintServerApp.h"
|
||||
|
||||
// posix
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// BeOS
|
||||
#include <Application.h>
|
||||
#include <Autolock.h>
|
||||
#include <Node.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
|
||||
Job::Job(const BEntry& job, BHandler* handler)
|
||||
: fHandler(handler)
|
||||
, fTime(-1)
|
||||
, fStatus(kUnknown)
|
||||
, fPrinter(NULL)
|
||||
{
|
||||
// store light weight versions of BEntry and BNode
|
||||
job.GetRef(&fEntry);
|
||||
job.GetNodeRef(&fNode);
|
||||
|
||||
BNode node(&job);
|
||||
if (node.InitCheck() != B_OK) return;
|
||||
|
||||
BNodeInfo info(&node);
|
||||
char mimeType[256];
|
||||
BString status;
|
||||
|
||||
// Is job a spool file?
|
||||
if (info.InitCheck() == B_OK /*&&
|
||||
info.GetType(mimeType) == B_OK &&
|
||||
strcmp(mimeType, PSRV_SPOOL_FILETYPE) == 0 &&
|
||||
node.ReadAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, status, sizeof(status))*/) {
|
||||
if (node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) != B_OK) {
|
||||
status = "";
|
||||
}
|
||||
// read status attribute
|
||||
UpdateStatus(status.String());
|
||||
// Now get file name and creation time from file name
|
||||
fTime = 0;
|
||||
BEntry entry(job);
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
if (entry.InitCheck() == B_OK && entry.GetName(name) == B_OK) {
|
||||
fName = name;
|
||||
// search for last '@' in file name
|
||||
char* p = NULL, *c = name;
|
||||
while ((c = strchr(c, '@')) != NULL) {
|
||||
p = c; c ++;
|
||||
}
|
||||
// and get time from file name
|
||||
fTime = atoi(p+1);
|
||||
}
|
||||
// start watching if everything is ok
|
||||
StartNodeWatching();
|
||||
}
|
||||
}
|
||||
|
||||
// conversion from string representation of status to JobStatus constant
|
||||
void Job::UpdateStatus(const char* status) {
|
||||
if (strcmp(status, PSRV_JOB_STATUS_WAITING) == 0) fStatus = kWaiting;
|
||||
else if (strcmp(status, PSRV_JOB_STATUS_PROCESSING) == 0) fStatus = kProcessing;
|
||||
else if (strcmp(status, PSRV_JOB_STATUS_FAILED) == 0) fStatus = kFailed;
|
||||
else fStatus = kUnknown;
|
||||
}
|
||||
|
||||
// Write to status attribute of node
|
||||
void Job::UpdateStatusAttribute(const char* status) {
|
||||
BNode node(&fEntry);
|
||||
if (node.InitCheck() == B_OK) {
|
||||
node.WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, status, strlen(status)+1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set status of object and optionally write to attribute of node
|
||||
void Job::SetStatus(JobStatus s, bool writeToNode) {
|
||||
fStatus = s;
|
||||
if (!writeToNode) return;
|
||||
switch (s) {
|
||||
case kWaiting: UpdateStatusAttribute(PSRV_JOB_STATUS_WAITING); break;
|
||||
case kProcessing: UpdateStatusAttribute(PSRV_JOB_STATUS_PROCESSING); break;
|
||||
case kFailed: UpdateStatusAttribute(PSRV_JOB_STATUS_FAILED); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronize file attribute with member variable
|
||||
void Job::UpdateAttribute() {
|
||||
BNode node(&fEntry);
|
||||
BString status;
|
||||
if (node.InitCheck() == B_OK &&
|
||||
node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) == B_OK) {
|
||||
UpdateStatus(status.String());
|
||||
}
|
||||
}
|
||||
|
||||
void Job::Remove() {
|
||||
BEntry entry(&fEntry);
|
||||
if (entry.InitCheck() == B_OK) entry.Remove();
|
||||
}
|
||||
|
||||
void Job::StartNodeWatching() {
|
||||
watch_node(&fNode, B_WATCH_ATTR, fHandler, be_app);
|
||||
}
|
||||
|
||||
void Job::StopNodeWatching() {
|
||||
watch_node(&fNode, B_STOP_WATCHING, fHandler, be_app);
|
||||
}
|
||||
|
||||
|
||||
// Implementation of Folder
|
||||
|
||||
// BObjectList CompareFunction
|
||||
int Folder::AscendingByTime(const Job* a, const Job* b) {
|
||||
return a->Time() - b->Time();
|
||||
}
|
||||
|
||||
bool Folder::AddJob(BEntry& entry) {
|
||||
Job* job = new Job(entry, this);
|
||||
if (job->InitCheck() == B_OK) {
|
||||
fJobs.AddItem(job);
|
||||
if (job->IsWaiting()) NotifyPrinter();
|
||||
return true;
|
||||
} else {
|
||||
job->Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// simplified assumption that ino_t identifies job file
|
||||
// will probabely not work in all cases with link to a file on another volume???
|
||||
Job* Folder::Find(ino_t node) {
|
||||
for (int i = 0; i < fJobs.CountItems(); i ++) {
|
||||
Job* job = fJobs.ItemAt(i);
|
||||
if (job->NodeRef().node == node) return job;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Folder::EntryCreated(BMessage* msg) {
|
||||
BString name;
|
||||
BEntry entry;
|
||||
if (msg->FindString("name", &name) == B_OK &&
|
||||
fSpoolDir.FindEntry(name.String(), &entry) == B_OK) {
|
||||
BAutolock lock(gLock);
|
||||
if (lock.IsLocked() && AddJob(entry)) {
|
||||
fJobs.SortItems(AscendingByTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::EntryRemoved(BMessage* msg) {
|
||||
ino_t node;
|
||||
if (msg->FindInt64("node", &node) == B_OK) {
|
||||
Job* job = Find(node);
|
||||
if (job) {
|
||||
fJobs.RemoveItem(job);
|
||||
job->StopNodeWatching();
|
||||
job->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::AttributeChanged(BMessage* msg) {
|
||||
ino_t node;
|
||||
if (msg->FindInt64("node", &node) == B_OK) {
|
||||
Job* job = Find(node);
|
||||
if (job) {
|
||||
job->UpdateAttribute();
|
||||
if (job->IsWaiting()) NotifyPrinter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::HandleNodeMonitorMessage(BMessage* msg) {
|
||||
BAutolock lock(gLock);
|
||||
if (!lock.IsLocked()) return;
|
||||
int32 opcode;
|
||||
if (msg->FindInt32("opcode", &opcode) != B_OK) return;
|
||||
switch (opcode) {
|
||||
case B_ENTRY_CREATED: // add to fJobs
|
||||
EntryCreated(msg);
|
||||
break;
|
||||
case B_ENTRY_REMOVED: // remove from fJobs
|
||||
EntryRemoved(msg);
|
||||
break;
|
||||
case B_ATTR_CHANGED: // notify Printer if status has changed to Waiting
|
||||
AttributeChanged(msg);
|
||||
break;
|
||||
default: // nothing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::NotifyPrinter() {
|
||||
be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB);
|
||||
}
|
||||
|
||||
// initial setup of job list
|
||||
void Folder::SetupJobList() {
|
||||
if (fSpoolDir.InitCheck() == B_OK) {
|
||||
fSpoolDir.Rewind();
|
||||
|
||||
BEntry entry;
|
||||
while (fSpoolDir.GetNextEntry(&entry) == B_OK) {
|
||||
AddJob(entry);
|
||||
}
|
||||
fJobs.SortItems(AscendingByTime);
|
||||
}
|
||||
}
|
||||
|
||||
Folder::Folder(const BDirectory& spoolDir)
|
||||
: fSpoolDir(spoolDir)
|
||||
, fJobs()
|
||||
{
|
||||
BAutolock lock(gLock);
|
||||
if (!lock.IsLocked()) return;
|
||||
// add this handler to the application for node monitoring
|
||||
be_app->AddHandler(this);
|
||||
|
||||
SetupJobList();
|
||||
|
||||
// start watching the spooler directory
|
||||
node_ref ref;
|
||||
spoolDir.GetNodeRef(&ref);
|
||||
watch_node(&ref, B_WATCH_DIRECTORY, this, be_app);
|
||||
}
|
||||
|
||||
|
||||
Folder::~Folder() {
|
||||
if (!gLock->Lock()) return;
|
||||
// stop node watching for jobs
|
||||
for (int i = 0; i < fJobs.CountItems(); i ++) {
|
||||
Job* job = fJobs.ItemAt(i);
|
||||
job->StopNodeWatching();
|
||||
job->Release();
|
||||
}
|
||||
// stop node watching for spooler directory
|
||||
node_ref ref;
|
||||
fSpoolDir.GetNodeRef(&ref);
|
||||
watch_node(&ref, B_STOP_WATCHING, this, be_app);
|
||||
// stop sending notifications to this handler
|
||||
stop_watching(this, be_app);
|
||||
gLock->Unlock();
|
||||
|
||||
if (be_app->Lock()) {
|
||||
// and remove it from application
|
||||
be_app->RemoveHandler(this);
|
||||
be_app->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Folder::MessageReceived(BMessage* msg) {
|
||||
if (msg->what == B_NODE_MONITOR) {
|
||||
HandleNodeMonitorMessage(msg);
|
||||
} else {
|
||||
inherited::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Job* Folder::GetNextJob() {
|
||||
for (int i = 0; i < fJobs.CountItems(); i ++) {
|
||||
Job* job = fJobs.ItemAt(i);
|
||||
if (job->IsWaiting()) {
|
||||
job->Acquire(); return job;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
122
src/servers/print/Jobs.h
Normal file
122
src/servers/print/Jobs.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*****************************************************************************/
|
||||
// Jobs
|
||||
//
|
||||
// Author
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _JOBS_H
|
||||
#define _JOBS_H
|
||||
|
||||
#include "BeUtils.h"
|
||||
#include "ObjectList.h"
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Handler.h>
|
||||
#include <String.h>
|
||||
#include <StorageDefs.h>
|
||||
|
||||
enum JobStatus {
|
||||
kWaiting,
|
||||
kProcessing,
|
||||
kFailed,
|
||||
kUnknown,
|
||||
};
|
||||
|
||||
class Printer;
|
||||
|
||||
class Job : public Object {
|
||||
private:
|
||||
BHandler* fHandler;
|
||||
BString fName;
|
||||
node_ref fNode;
|
||||
entry_ref fEntry;
|
||||
JobStatus fStatus;
|
||||
long fTime;
|
||||
Printer* fPrinter;
|
||||
|
||||
void UpdateStatus(const char* status);
|
||||
void UpdateStatusAttribute(const char* status);
|
||||
|
||||
public:
|
||||
Job(const BEntry& entry, BHandler* handler);
|
||||
|
||||
status_t InitCheck() const { return fTime >= 0 ? B_OK : B_ERROR; }
|
||||
|
||||
// accessors
|
||||
const BString& Name() const { return fName; }
|
||||
JobStatus Status() const { return fStatus; }
|
||||
long Time() const { return fTime; }
|
||||
const node_ref& NodeRef() const { return fNode; }
|
||||
const entry_ref& EntryRef() const { return fEntry; }
|
||||
bool IsWaiting() const { return fStatus == kWaiting; }
|
||||
Printer* GetPrinter() const { return fPrinter; }
|
||||
|
||||
// modification
|
||||
void SetPrinter(Printer* p) { fPrinter = p; }
|
||||
void SetStatus(JobStatus s, bool writeToNode = true);
|
||||
void UpdateAttribute();
|
||||
void Remove();
|
||||
|
||||
void StartNodeWatching();
|
||||
void StopNodeWatching();
|
||||
};
|
||||
|
||||
|
||||
class Folder : public BHandler {
|
||||
typedef BHandler inherited;
|
||||
|
||||
private:
|
||||
BDirectory fSpoolDir;
|
||||
BObjectList<Job> fJobs;
|
||||
|
||||
static int AscendingByTime(const Job* a, const Job* b);
|
||||
|
||||
bool AddJob(BEntry& entry);
|
||||
Job* Find(ino_t node);
|
||||
|
||||
// node monitor handling
|
||||
void EntryCreated(BMessage* msg);
|
||||
void EntryRemoved(BMessage* msg);
|
||||
void AttributeChanged(BMessage* msg);
|
||||
void HandleNodeMonitorMessage(BMessage* msg);
|
||||
|
||||
void NotifyPrinter();
|
||||
|
||||
void SetupJobList();
|
||||
|
||||
public:
|
||||
Folder(const BDirectory& spoolDir);
|
||||
~Folder();
|
||||
|
||||
void MessageReceived(BMessage* msg);
|
||||
|
||||
// Caller is responsible to set the status of the job appropriately
|
||||
// and to release the object when done
|
||||
Job* GetNextJob();
|
||||
};
|
||||
#endif
|
Binary file not shown.
@ -6,12 +6,9 @@
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
//
|
||||
//
|
||||
// TODO:
|
||||
// Handle spooled jobs at startup
|
||||
// Handle printer status (asked to print a spooled job but printer busy)
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
@ -53,12 +50,16 @@
|
||||
|
||||
struct AsyncThreadParams {
|
||||
Printer* printer;
|
||||
BMessage message;
|
||||
BMessage* message;
|
||||
|
||||
AsyncThreadParams(Printer* p, BMessage* m)
|
||||
: printer(p)
|
||||
, message(*m)
|
||||
, message(m)
|
||||
{ }
|
||||
|
||||
~AsyncThreadParams() {
|
||||
delete message;
|
||||
}
|
||||
};
|
||||
|
||||
status_t PrintServerApp::async_thread(void* data)
|
||||
@ -66,7 +67,7 @@ status_t PrintServerApp::async_thread(void* data)
|
||||
AsyncThreadParams* p = (AsyncThreadParams*)data;
|
||||
|
||||
Printer* printer = p->printer;
|
||||
BMessage* msg = &p->message;
|
||||
BMessage* msg = p->message;
|
||||
|
||||
switch (msg->what) {
|
||||
// Handle showing the page config dialog
|
||||
@ -131,10 +132,6 @@ void PrintServerApp::AsyncHandleMessage(BMessage* msg)
|
||||
|
||||
void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
|
||||
{
|
||||
printf("PrintServerApp::Handle_BeOSR5_Message\n");
|
||||
msg->PrintToStream();
|
||||
fflush(stdout);
|
||||
|
||||
switch(msg->what) {
|
||||
// Get currently selected printer
|
||||
case PSRV_GET_ACTIVE_PRINTER: {
|
||||
@ -186,18 +183,12 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
|
||||
|
||||
case PSRV_SHOW_PAGE_SETUP:
|
||||
case PSRV_SHOW_PRINT_SETUP:
|
||||
AsyncHandleMessage(msg);
|
||||
AsyncHandleMessage(DetachCurrentMessage());
|
||||
break;
|
||||
|
||||
// Tell printer addon to print a spooled job
|
||||
case PSRV_PRINT_SPOOLED_JOB: {
|
||||
BString name, jobpath;
|
||||
if (msg->FindString("Spool File",&jobpath) == B_OK &&
|
||||
msg->FindString("JobName", &name) == B_OK) {
|
||||
// Handle the spooled job
|
||||
HandleSpooledJob(name.String(), jobpath.String());
|
||||
}
|
||||
}
|
||||
case PSRV_PRINT_SPOOLED_JOB:
|
||||
HandleSpooledJobs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
// Author
|
||||
// Ithamar R. Adema
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
@ -105,7 +107,7 @@ PrintServerApp::HandleScriptingCommand(BMessage* msg)
|
||||
case B_DELETE_PROPERTY: {
|
||||
Printer* printer = GetPrinterFromSpecifier(&spec);
|
||||
status_t rc = B_BAD_VALUE;
|
||||
|
||||
|
||||
if (printer != NULL && (rc=printer->Remove()) == B_OK) {
|
||||
printer->Release();
|
||||
}
|
||||
|
@ -6,12 +6,9 @@
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
//
|
||||
//
|
||||
// TODO:
|
||||
// Handle spooled jobs at startup
|
||||
// Handle printer status (asked to print a spooled job but printer busy)
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
@ -45,23 +42,26 @@
|
||||
#include "pr_server.h"
|
||||
|
||||
// BeOS API
|
||||
#include <FindDirectory.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Directory.h>
|
||||
#include <PrintJob.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <String.h>
|
||||
#include <Roster.h>
|
||||
#include <image.h>
|
||||
#include <Alert.h>
|
||||
#include <Path.h>
|
||||
#include <Autolock.h>
|
||||
#include <Directory.h>
|
||||
#include <File.h>
|
||||
#include <image.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Mime.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <PrintJob.h>
|
||||
#include <String.h>
|
||||
|
||||
// ANSI C
|
||||
#include <stdio.h> //for printf
|
||||
#include <unistd.h> //for unlink
|
||||
|
||||
BLocker *gLock = NULL;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
typedef struct _printer_data {
|
||||
char defaultPrinterName[256];
|
||||
@ -83,16 +83,17 @@ typedef char* (*add_printer_func_t)(const char* printer_name);
|
||||
int
|
||||
main()
|
||||
{
|
||||
gLock = new BLocker();
|
||||
// Create our application object
|
||||
status_t rc = B_OK;
|
||||
new PrintServerApp(&rc);
|
||||
PrintServerApp print_server(&rc);
|
||||
|
||||
// If all went fine, let's start it
|
||||
if (rc == B_OK) {
|
||||
be_app->Run();
|
||||
print_server.Run();
|
||||
}
|
||||
|
||||
delete be_app;
|
||||
delete gLock;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -111,10 +112,14 @@ main()
|
||||
PrintServerApp::PrintServerApp(status_t* err)
|
||||
: Inherited(PSRV_SIGNATURE_TYPE, err),
|
||||
fSelectedIconMini(BRect(0,0,B_MINI_ICON-1,B_MINI_ICON-1), B_CMAP8),
|
||||
fSelectedIconLarge(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8)
|
||||
fSelectedIconLarge(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8),
|
||||
fNumberOfPrinters(0),
|
||||
fNoPrinterAvailable(0)
|
||||
{
|
||||
// If our superclass initialized ok
|
||||
if (*err == B_OK) {
|
||||
fNoPrinterAvailable = create_sem(1, "");
|
||||
|
||||
// let us try as well
|
||||
SetupPrinterList();
|
||||
RetrieveDefaultPrinter();
|
||||
@ -123,6 +128,9 @@ PrintServerApp::PrintServerApp(status_t* err)
|
||||
BMimeType type(PRNT_SIGNATURE_TYPE);
|
||||
type.GetIcon(&fSelectedIconMini, B_MINI_ICON);
|
||||
type.GetIcon(&fSelectedIconLarge, B_LARGE_ICON);
|
||||
|
||||
// Start handling of spooled files
|
||||
PostMessage(PSRV_PRINT_SPOOLED_JOB);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,11 +149,69 @@ bool PrintServerApp::QuitRequested()
|
||||
::watch_node(&nref, B_STOP_WATCHING, be_app_messenger);
|
||||
}
|
||||
}
|
||||
|
||||
// Release all printers
|
||||
Printer* printer;
|
||||
while ((printer = Printer::At(0)) != NULL) {
|
||||
Printer::Remove(printer);
|
||||
printer->AbortPrintThread();
|
||||
printer->Release();
|
||||
}
|
||||
|
||||
// Wait for printers
|
||||
if (fNoPrinterAvailable > 0) {
|
||||
acquire_sem(fNoPrinterAvailable);
|
||||
delete_sem(fNoPrinterAvailable);
|
||||
fNoPrinterAvailable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void PrintServerApp::RegisterPrinter(BDirectory* printer) {
|
||||
BString transport, address, connection;
|
||||
|
||||
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport);
|
||||
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address);
|
||||
printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection);
|
||||
|
||||
BAutolock lock(gLock);
|
||||
if (lock.IsLocked()) {
|
||||
Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String());
|
||||
new Printer(printer, r);
|
||||
if (fNumberOfPrinters == 0) acquire_sem(fNoPrinterAvailable);
|
||||
fNumberOfPrinters ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PrintServerApp::NotifyPrinterDeletion(Resource* res) {
|
||||
BAutolock lock(gLock);
|
||||
if (lock.IsLocked()) {
|
||||
fNumberOfPrinters --;
|
||||
fResourceManager.Free(res);
|
||||
if (fNumberOfPrinters == 0) release_sem(fNoPrinterAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintServerApp::HandleRemovedPrinter(BMessage* msg) {
|
||||
int32 opcode;
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
Printer* printer;
|
||||
if (msg->FindInt32("opcode", &opcode) == B_OK && opcode == B_ENTRY_REMOVED &&
|
||||
msg->FindInt32("device", &device) == B_OK &&
|
||||
msg->FindInt64("node", &node) == B_OK &&
|
||||
(printer = Printer::Find(device, node)) != NULL) {
|
||||
if (printer == fDefaultPrinter) fDefaultPrinter = NULL;
|
||||
Printer::Remove(printer);
|
||||
printer->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// SetupPrinterList
|
||||
//
|
||||
@ -176,14 +242,14 @@ status_t PrintServerApp::SetupPrinterList()
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory()) {
|
||||
// Check it's Mime type for a spool director
|
||||
BNode node(&entry);
|
||||
BDirectory node(&entry);
|
||||
BNodeInfo info(&node);
|
||||
char buffer[256];
|
||||
|
||||
if (info.GetType(buffer) == B_OK &&
|
||||
strcmp(buffer, PSRV_PRINTER_FILETYPE) == 0) {
|
||||
// Yes, it is a printer definition node
|
||||
new Printer(&node);
|
||||
RegisterPrinter(&node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,10 +300,12 @@ PrintServerApp::MessageReceived(BMessage* msg)
|
||||
case B_EXECUTE_PROPERTY:
|
||||
HandleScriptingCommand(msg);
|
||||
break;
|
||||
|
||||
case B_NODE_MONITOR:
|
||||
HandleRemovedPrinter(msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("PrintServerApp::MessageReceived(): ");
|
||||
msg->PrintToStream();
|
||||
Inherited::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
@ -298,10 +366,12 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName,
|
||||
// call the function and check its result
|
||||
if ((*func)(printerName) == NULL) {
|
||||
BEntry entry;
|
||||
if (printer.GetEntry(&entry) == B_OK && entry.GetPath(&path) == B_OK) {
|
||||
if (printer.GetEntry(&entry) == B_OK) {
|
||||
// Delete the printer if function failed
|
||||
::rmdir(path.Path());
|
||||
entry.Remove();
|
||||
}
|
||||
} else {
|
||||
RegisterPrinter(&printer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,55 +430,19 @@ PrintServerApp::SelectPrinter(const char* printerName)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// HandleSpooledJob(const char* jobname, const char* filepath)
|
||||
// HandleSpooledJobs()
|
||||
//
|
||||
// Handles calling the printer driver for printing a spooled job.
|
||||
// Handles calling the printer drivers for printing a spooled job.
|
||||
//
|
||||
// Parameters:
|
||||
// msg - A copy of the message received, will be accessible
|
||||
// to the printer driver for reading job config
|
||||
// details.
|
||||
// Returns:
|
||||
// BMessage containing new job data, or NULL pointer if not
|
||||
// successfull.
|
||||
// ---------------------------------------------------------------
|
||||
status_t
|
||||
PrintServerApp::HandleSpooledJob(const char* jobname, const char* filepath)
|
||||
void
|
||||
PrintServerApp::HandleSpooledJobs()
|
||||
{
|
||||
BFile spoolFile(filepath, B_READ_ONLY);
|
||||
print_file_header header;
|
||||
BString driverName;
|
||||
BMessage settings;
|
||||
Printer* printer;
|
||||
status_t rc;
|
||||
BPath path;
|
||||
|
||||
// Open the spool file
|
||||
if ((rc=spoolFile.InitCheck()) == B_OK) {
|
||||
// Read header from filestream
|
||||
spoolFile.Seek(0, SEEK_SET);
|
||||
spoolFile.Read(&header, sizeof(header));
|
||||
|
||||
// Get the printer settings
|
||||
settings.Unflatten(&spoolFile);
|
||||
|
||||
// Get name of printer from settings
|
||||
const char* printerName;
|
||||
if ((rc=settings.FindString("current_printer", &printerName)) == B_OK) {
|
||||
// Find printer definition for this printer
|
||||
if ((printer=Printer::Find(printerName)) != NULL) {
|
||||
// and tell the printer to print the spooled job
|
||||
printer->PrintSpooledJob(&spoolFile, settings);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove spool file if printing was successfull.
|
||||
if (rc == B_OK) {
|
||||
::unlink(filepath);
|
||||
}
|
||||
const int n = Printer::CountPrinters();
|
||||
for (int i = 0; i < n; i ++) {
|
||||
Printer* printer = Printer::At(i);
|
||||
printer->HandleSpooledJob();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
@ -6,6 +6,9 @@
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
@ -35,12 +38,18 @@
|
||||
#ifndef PRINTSERVERAPP_H
|
||||
#define PRINTSERVERAPP_H
|
||||
|
||||
#include "ResourceManager.h"
|
||||
|
||||
class PrintServerApp;
|
||||
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
|
||||
// global BLocker for synchronisation
|
||||
extern BLocker* gLock;
|
||||
|
||||
/*****************************************************************************/
|
||||
// PrintServerApp
|
||||
//
|
||||
@ -52,8 +61,10 @@ class PrintServerApp : public BApplication
|
||||
typedef BApplication Inherited;
|
||||
public:
|
||||
PrintServerApp(status_t* err);
|
||||
|
||||
bool QuitRequested();
|
||||
void MessageReceived(BMessage* msg);
|
||||
void NotifyPrinterDeletion(Resource* res);
|
||||
|
||||
// Scripting support, see PrintServerApp.Scripting.cpp
|
||||
status_t GetSupportedSuites(BMessage* msg);
|
||||
@ -64,12 +75,15 @@ public:
|
||||
private:
|
||||
status_t SetupPrinterList();
|
||||
|
||||
status_t HandleSpooledJob(const char* jobname, const char* filepath);
|
||||
void HandleSpooledJobs();
|
||||
|
||||
status_t SelectPrinter(const char* printerName);
|
||||
status_t CreatePrinter( const char* printerName, const char* driverName,
|
||||
const char* connection, const char* transportName,
|
||||
const char* transportPath);
|
||||
|
||||
void RegisterPrinter(BDirectory* node);
|
||||
void HandleRemovedPrinter(BMessage* msg);
|
||||
|
||||
status_t StoreDefaultPrinter();
|
||||
status_t RetrieveDefaultPrinter();
|
||||
@ -77,14 +91,18 @@ private:
|
||||
status_t FindPrinterNode(const char* name, BNode& node);
|
||||
status_t FindPrinterDriver(const char* name, BPath& outPath);
|
||||
|
||||
ResourceManager fResourceManager;
|
||||
Printer* fDefaultPrinter;
|
||||
BBitmap fSelectedIconMini;
|
||||
BBitmap fSelectedIconLarge;
|
||||
int fNumberOfPrinters;
|
||||
sem_id fNoPrinterAvailable;
|
||||
|
||||
// "Classic" BeOS R5 support, see PrintServerApp.R5.cpp
|
||||
static status_t async_thread(void* data);
|
||||
void AsyncHandleMessage(BMessage* msg);
|
||||
void Handle_BeOSR5_Message(BMessage* msg);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,39 @@
|
||||
/*****************************************************************************/
|
||||
// print_server Background Application.
|
||||
//
|
||||
// Version: 1.0.0d1
|
||||
//
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
// Author
|
||||
// Ithamar R. Adema
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2001 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "Printer.h"
|
||||
|
||||
|
||||
|
@ -6,18 +6,15 @@
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
//
|
||||
//
|
||||
// TODO:
|
||||
// Handle spooled jobs at startup
|
||||
// Handle printer status (asked to print a spooled job but printer busy)
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2001 OpenBeOS Project
|
||||
// Copyright (c) 2001,2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
@ -42,13 +39,21 @@
|
||||
|
||||
#include "pr_server.h"
|
||||
#include "BeUtils.h"
|
||||
#include "PrintServerApp.h"
|
||||
|
||||
// posix
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// BeOS API
|
||||
#include <Application.h>
|
||||
#include <Autolock.h>
|
||||
#include <Message.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <String.h>
|
||||
#include <File.h>
|
||||
#include <Path.h>
|
||||
#include <StorageKit.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
typedef BMessage* (*config_func_t)(BNode*, const BMessage*);
|
||||
@ -84,9 +89,18 @@ Printer* Printer::Find(const BString& name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32 Printer::CountPrinters()
|
||||
Printer* Printer::Find(dev_t dev, ino_t node)
|
||||
{
|
||||
return sPrinters.CountItems();
|
||||
// Look in list to find printer definition
|
||||
for (int32 idx=0; idx < sPrinters.CountItems(); idx++) {
|
||||
Printer* printer = sPrinters.ItemAt(idx);
|
||||
node_ref ref;
|
||||
printer->fNode.GetNodeRef(&ref);
|
||||
if (ref.device == dev && ref.node == node) return printer;
|
||||
}
|
||||
|
||||
// None found, so return NULL
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Printer* Printer::At(int32 idx)
|
||||
@ -94,6 +108,15 @@ Printer* Printer::At(int32 idx)
|
||||
return sPrinters.ItemAt(idx);
|
||||
}
|
||||
|
||||
void Printer::Remove(Printer* printer) {
|
||||
sPrinters.RemoveItem(printer);
|
||||
}
|
||||
|
||||
int32 Printer::CountPrinters()
|
||||
{
|
||||
return sPrinters.CountItems();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Printer [constructor]
|
||||
//
|
||||
@ -106,15 +129,22 @@ Printer* Printer::At(int32 idx)
|
||||
// Returns:
|
||||
// none.
|
||||
// ---------------------------------------------------------------
|
||||
Printer::Printer(const BNode* node)
|
||||
Printer::Printer(const BDirectory* node, Resource* res)
|
||||
: Inherited(B_EMPTY_STRING),
|
||||
fFolder(*node),
|
||||
fResource(res),
|
||||
fNode(*node),
|
||||
fRefCount(1)
|
||||
fSinglePrintThread(true),
|
||||
fJob(NULL),
|
||||
fProcessing(0),
|
||||
fAbort(false)
|
||||
{
|
||||
// Set our name to the name of the passed node
|
||||
BString name;
|
||||
fNode.ReadAttrString(PSRV_PRINTER_ATTR_PRT_NAME, &name);
|
||||
SetName(name.String());
|
||||
|
||||
if (name == "Preview") fSinglePrintThread = false;
|
||||
|
||||
// Add us to the global list of known printer definitions
|
||||
sPrinters.AddItem(this);
|
||||
@ -123,19 +153,7 @@ Printer::Printer(const BNode* node)
|
||||
|
||||
Printer::~Printer()
|
||||
{
|
||||
sPrinters.RemoveItem(this);
|
||||
be_app->RemoveHandler(this);
|
||||
}
|
||||
|
||||
void Printer::Acquire()
|
||||
{
|
||||
fRefCount ++;
|
||||
}
|
||||
|
||||
void Printer::Release()
|
||||
{
|
||||
fRefCount --;
|
||||
if (fRefCount == 0) delete this;
|
||||
((PrintServerApp*)be_app)->NotifyPrinterDeletion(fResource);
|
||||
}
|
||||
|
||||
status_t Printer::Remove()
|
||||
@ -144,6 +162,8 @@ status_t Printer::Remove()
|
||||
BPath path;
|
||||
|
||||
if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY, &path)) == B_OK) {
|
||||
sPrinters.RemoveItem(this);
|
||||
be_app->RemoveHandler(this);
|
||||
path.Append(Name());
|
||||
rc = rmdir(path.Path());
|
||||
}
|
||||
@ -242,29 +262,11 @@ status_t Printer::ConfigureJob(BMessage& settings)
|
||||
if ((rc=get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) {
|
||||
// call the function and check its result
|
||||
BMessage* new_settings = (*func)(&fNode, &settings);
|
||||
if (new_settings != NULL && new_settings->what != 'baad')
|
||||
if ((new_settings != NULL) && (new_settings->what != 'baad'))
|
||||
settings = *new_settings;
|
||||
}
|
||||
|
||||
::unload_add_on(id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings)
|
||||
{
|
||||
take_job_func_t func;
|
||||
image_id id;
|
||||
status_t rc;
|
||||
|
||||
if ((rc=LoadPrinterAddon(id)) == B_OK) {
|
||||
// Addon was loaded, so try and get the take_job symbol
|
||||
if ((rc=get_image_symbol(id, "take_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) {
|
||||
// call the function and check its result
|
||||
BMessage* result = (*func)(spoolFile, &fNode, &settings);
|
||||
if (result == NULL || result->what == 'baad')
|
||||
else
|
||||
rc = B_ERROR;
|
||||
delete new_settings;
|
||||
}
|
||||
|
||||
::unload_add_on(id);
|
||||
@ -273,6 +275,23 @@ status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// HandleSpooledJobs
|
||||
//
|
||||
// Print spooled jobs in a new thread.
|
||||
// ---------------------------------------------------------------
|
||||
void Printer::HandleSpooledJob() {
|
||||
BAutolock lock(gLock);
|
||||
if (lock.IsLocked() && (!fSinglePrintThread || fProcessing == 0) && FindSpooledJob()) {
|
||||
StartPrintThread();
|
||||
}
|
||||
}
|
||||
|
||||
void Printer::AbortPrintThread() {
|
||||
fAbort = true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// LoadPrinterAddon
|
||||
//
|
||||
@ -310,6 +329,10 @@ status_t Printer::LoadPrinterAddon(image_id& id)
|
||||
|
||||
void Printer::MessageReceived(BMessage* msg)
|
||||
{
|
||||
printf("Printer::MessageReceived(): ");
|
||||
msg->PrintToStream();
|
||||
|
||||
|
||||
switch(msg->what) {
|
||||
case B_GET_PROPERTY:
|
||||
case B_SET_PROPERTY:
|
||||
@ -324,3 +347,84 @@ void Printer::MessageReceived(BMessage* msg)
|
||||
Inherited::MessageReceived(msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool Printer::FindSpooledJob() {
|
||||
fJob = fFolder.GetNextJob();
|
||||
if (fJob) fJob->SetPrinter(this);
|
||||
return fJob;
|
||||
}
|
||||
|
||||
void Printer::CloseJob() {
|
||||
fJob->Release();
|
||||
}
|
||||
|
||||
status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings)
|
||||
{
|
||||
take_job_func_t func;
|
||||
image_id id;
|
||||
status_t rc;
|
||||
|
||||
if ((rc=LoadPrinterAddon(id)) == B_OK) {
|
||||
// Addon was loaded, so try and get the take_job symbol
|
||||
if ((rc=get_image_symbol(id, "take_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) {
|
||||
// call the function and check its result
|
||||
BMessage* result = (*func)(spoolFile, &fNode, &settings);
|
||||
if (result == NULL || result->what == 'baad')
|
||||
rc = B_ERROR;
|
||||
}
|
||||
|
||||
::unload_add_on(id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Printer::PrintThread(Job* job) {
|
||||
fResource->Lock();
|
||||
if (!fAbort) {
|
||||
BFile jobFile(&job->EntryRef(), B_READ_ONLY);
|
||||
print_file_header header;
|
||||
BMessage settings;
|
||||
|
||||
// Read header from filestream
|
||||
jobFile.Seek(0, SEEK_SET);
|
||||
jobFile.Read(&header, sizeof(header));
|
||||
|
||||
// Get the printer settings
|
||||
settings.Unflatten(&jobFile);
|
||||
|
||||
// and tell the printer to print the spooled job
|
||||
if (PrintSpooledJob(&jobFile, settings) == B_OK) {
|
||||
// Remove spool file if printing was successfull.
|
||||
job->Remove();
|
||||
} else {
|
||||
job->SetStatus(kFailed);
|
||||
}
|
||||
} else {
|
||||
job->SetStatus(kFailed);
|
||||
}
|
||||
fResource->Unlock();
|
||||
job->Release();
|
||||
atomic_add(&fProcessing, -1);
|
||||
Release();
|
||||
be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB);
|
||||
}
|
||||
|
||||
status_t Printer::print_thread(void* data) {
|
||||
Job* job = static_cast<Job*>(data);
|
||||
job->GetPrinter()->PrintThread(job);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t Printer::StartPrintThread() {
|
||||
Acquire();
|
||||
thread_id tid = spawn_thread(print_thread, "print", B_NORMAL_PRIORITY, (void*)fJob);
|
||||
if (tid > 0) {
|
||||
fJob->SetStatus(kProcessing);
|
||||
atomic_add(&fProcessing, 1);
|
||||
resume_thread(tid);
|
||||
} else {
|
||||
CloseJob(); Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,10 @@
|
||||
//
|
||||
// The print_server manages the communication between applications and the
|
||||
// printer and transport drivers.
|
||||
//
|
||||
//
|
||||
//
|
||||
// TODO:
|
||||
// Handle spooled jobs at startup
|
||||
// Handle printer status (asked to print a spooled job but printer busy)
|
||||
//
|
||||
// Authors
|
||||
// Ithamar R. Adema
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
@ -43,11 +40,17 @@
|
||||
|
||||
class Printer;
|
||||
|
||||
#include "BeUtils.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "Jobs.h"
|
||||
|
||||
// BeOS API
|
||||
#include <Directory.h>
|
||||
#include <Handler.h>
|
||||
#include <String.h>
|
||||
#include <image.h>
|
||||
#include <Node.h>
|
||||
#include <Locker.h>
|
||||
#include <PrintJob.h>
|
||||
#include <String.h>
|
||||
|
||||
// OpenTracker shared sources
|
||||
#include "ObjectList.h"
|
||||
@ -58,27 +61,27 @@ class Printer;
|
||||
// This class represents one printer definition. It is manages all actions &
|
||||
// data related to that printer.
|
||||
/*****************************************************************************/
|
||||
class Printer : public BHandler
|
||||
class Printer : public BHandler, public Object
|
||||
{
|
||||
typedef BHandler Inherited;
|
||||
|
||||
public:
|
||||
Printer(const BNode* node);
|
||||
Printer(const BDirectory* node, Resource* res);
|
||||
~Printer();
|
||||
|
||||
void Acquire();
|
||||
void Release();
|
||||
|
||||
// Static helper functions
|
||||
static Printer* Find(const BString& name);
|
||||
static Printer* Find(dev_t device, ino_t node);
|
||||
static Printer* At(int32 idx);
|
||||
static void Remove(Printer* printer);
|
||||
static int32 CountPrinters();
|
||||
|
||||
status_t Remove();
|
||||
status_t ConfigurePrinter();
|
||||
status_t ConfigureJob(BMessage& ioSettings);
|
||||
status_t ConfigurePage(BMessage& ioSettings);
|
||||
status_t PrintSpooledJob(BFile* spoolFile, const BMessage& settings);
|
||||
void HandleSpooledJob();
|
||||
void AbortPrintThread();
|
||||
|
||||
void MessageReceived(BMessage* msg);
|
||||
|
||||
@ -90,10 +93,22 @@ public:
|
||||
private:
|
||||
status_t LoadPrinterAddon(image_id& id);
|
||||
|
||||
BNode fNode;
|
||||
int32 fRefCount;
|
||||
Folder fFolder;
|
||||
Resource* fResource;
|
||||
BDirectory fNode;
|
||||
bool fSinglePrintThread;
|
||||
Job* fJob;
|
||||
volatile vint32 fProcessing;
|
||||
bool fAbort;
|
||||
|
||||
static BObjectList<Printer> sPrinters;
|
||||
|
||||
bool FindSpooledJob();
|
||||
void CloseJob();
|
||||
status_t PrintSpooledJob(BFile* spoolFile, const BMessage& settings);
|
||||
void PrintThread(Job* job);
|
||||
static status_t print_thread(void* data);
|
||||
status_t StartPrintThread();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
104
src/servers/print/ResourceManager.cpp
Normal file
104
src/servers/print/ResourceManager.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/*****************************************************************************/
|
||||
// ResourceManager
|
||||
//
|
||||
// Author
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "ResourceManager.h"
|
||||
|
||||
#include <Debug.h>
|
||||
#include <Autolock.h>
|
||||
|
||||
Resource::Resource(const char* transport, const char* address, const char* connection)
|
||||
: fTransport(transport)
|
||||
, fTransportAddress(address)
|
||||
, fConnection(connection)
|
||||
, fResourceAvailable(0)
|
||||
|
||||
{
|
||||
if (NeedsLocking()) {
|
||||
fResourceAvailable = create_sem(1, "resource");
|
||||
}
|
||||
}
|
||||
|
||||
Resource::~Resource() {
|
||||
if (fResourceAvailable > 0) delete_sem(fResourceAvailable);
|
||||
}
|
||||
|
||||
bool Resource::NeedsLocking() {
|
||||
return !(fTransport == "Print to File" || fTransport == "NONE");
|
||||
}
|
||||
|
||||
bool Resource::Equals(const char* transport, const char* address, const char* connection) {
|
||||
return fTransport == transport &&
|
||||
fTransportAddress == address &&
|
||||
fConnection == connection;
|
||||
}
|
||||
|
||||
bool Resource::Lock() {
|
||||
if (fResourceAvailable > 0) {
|
||||
return acquire_sem(fResourceAvailable) == B_NO_ERROR;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Resource::Unlock() {
|
||||
if (fResourceAvailable > 0) {
|
||||
release_sem(fResourceAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager() {
|
||||
ASSERT(fResources.CountItems() == 0);
|
||||
}
|
||||
|
||||
Resource* ResourceManager::Find(const char* transport, const char* address, const char* connection) {
|
||||
for (int i = 0; i < fResources.CountItems(); i ++) {
|
||||
Resource* r = fResources.ItemAt(i);
|
||||
if (r->Equals(transport, address, connection)) return r;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Resource* ResourceManager::Allocate(const char* transport, const char* address, const char* connection) {
|
||||
Resource* r = Find(transport, address, connection);
|
||||
if (r == NULL) {
|
||||
r = new Resource(transport, address, connection);
|
||||
fResources.AddItem(r);
|
||||
} else {
|
||||
r->Acquire();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void ResourceManager::Free(Resource* r) {
|
||||
if (r->Release()) {
|
||||
fResources.RemoveItem(r);
|
||||
}
|
||||
}
|
78
src/servers/print/ResourceManager.h
Normal file
78
src/servers/print/ResourceManager.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*****************************************************************************/
|
||||
// ResourceManager
|
||||
//
|
||||
// Author
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2002 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef RESOURCE_MANAGER_H
|
||||
#define RESOURCE_MANAGER_H
|
||||
|
||||
#include "ObjectList.h"
|
||||
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "BeUtils.h"
|
||||
|
||||
class Resource : public Object {
|
||||
private:
|
||||
BString fTransport;
|
||||
BString fTransportAddress;
|
||||
BString fConnection;
|
||||
sem_id fResourceAvailable;
|
||||
|
||||
bool NeedsLocking();
|
||||
|
||||
|
||||
public:
|
||||
Resource(const char* transport, const char* address, const char* connection);
|
||||
~Resource();
|
||||
|
||||
bool Equals(const char* transport, const char* address, const char* connection);
|
||||
|
||||
const BString& Transport() const { return fTransport; }
|
||||
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
};
|
||||
|
||||
class ResourceManager {
|
||||
private:
|
||||
BObjectList<Resource> fResources;
|
||||
|
||||
Resource* Find(const char* transport, const char* address, const char* connection);
|
||||
|
||||
public:
|
||||
~ResourceManager();
|
||||
|
||||
Resource* Allocate(const char* transport, const char* address, const char* connection);
|
||||
void Free(Resource* r);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user