Clean up.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2094 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2002-11-26 23:32:04 +00:00
parent af09bc0a28
commit 87f0c75967
15 changed files with 706 additions and 155 deletions
-101
View File
@@ -1,101 +0,0 @@
/*****************************************************************************/
// 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>
#include <Picture.h>
#include <PictureButton.h>
#include <TranslatorFormats.h>
#include <TranslationUtils.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() {
if (atomic_add(&fRefCount, -1) == 1) {
delete this; return true;
} else {
return false;
}
}
};
// Automatically send a reply to sender on destruction of object
// and delete sender
class AutoReply {
BMessage* fSender;
BMessage fReply;
public:
AutoReply(BMessage* sender, uint32 what);
~AutoReply();
void SetReply(BMessage* m) { fReply = *m; }
};
// mimetype from sender
bool MimeTypeForSender(BMessage* sender, BString& mime);
// adds fields to message or replaces existing fields
bool AddFields(BMessage* to, const BMessage* from);
// load bitmap from application resources
BBitmap* LoadBitmap(const char* name, uint32 type_code = B_TRANSLATOR_BITMAP);
// convert bitmap to picture; view must be attached to a window!
// returns NULL if bitmap is NULL
BPicture *BitmapToPicture(BView* view, BBitmap *bitmap);
BPicture *BitmapToGrayedPicture(BView* view, BBitmap *bitmap);
#endif
+113 -4
View File
@@ -30,12 +30,15 @@
/*****************************************************************************/
#include "pr_server.h"
#include "Printer.h"
#include "PrintServerApp.h"
#include "ConfigWindow.h"
#include "BeUtils.h"
// posix
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -44,6 +47,65 @@
#include <Autolock.h>
#include <Window.h>
static const float a0_width = 2380.0;
static const float a0_height = 3368.0;
static const float a1_width = 1684.0;
static const float a1_height = 2380.0;
static const float a2_width = 1190.0;
static const float a2_height = 1684.0;
static const float a3_width = 842.0;
static const float a3_height = 1190.0;
static const float a4_width = 595.0;
static const float a4_height = 842.0;
static const float a5_width = 421.0;
static const float a5_height = 595.0;
static const float a6_width = 297.0;
static const float a6_height = 421.0;
static const float b5_width = 501.0;
static const float b5_height = 709.0;
static const float letter_width = 612.0;
static const float letter_height = 792.0;
static const float legal_width = 612.0;
static const float legal_height = 1008.0;
static const float ledger_width = 1224.0;
static const float ledger_height = 792.0;
static const float p11x17_width = 792.0;
static const float p11x17_height = 1224.0;
static struct PageFormat
{
char *label;
float width;
float height;
} pageFormat[] =
{
{"Letter", letter_width, letter_height },
{"Legal", legal_width, legal_height },
{"Ledger", ledger_width, ledger_height },
{"p11x17", p11x17_width, p11x17_height },
{"A0", a0_width, a0_height },
{"A1", a1_width, a1_height },
{"A2", a2_width, a2_height },
{"A3", a3_width, a3_height },
{"A4", a4_width, a4_height },
{"A5", a5_width, a5_height },
{"A6", a6_width, a6_height },
{"B5", b5_width, b5_height },
};
static void GetPageFormat(float w, float h, BString& label) {
w = floor(w + 0.5); h = floor(h + 0.5);
for (int i = 0; i < sizeof(pageFormat) / sizeof(struct PageFormat); i ++) {
struct PageFormat& pf = pageFormat[i];
if (pf.width == w && pf.height == h || pf.width == h && pf.height == w) {
label = pf.label; return;
}
}
float unit = 72.0; // currently inc[h]es only
label << (w / unit) << "x" << (h / unit) << " in.";
}
ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender)
: BWindow(ConfigWindow::GetWindowFrame(), "Page Setup",
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
@@ -81,8 +143,10 @@ ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMes
r.OffsetTo(left, top);
fPageSetup = AddPictureButton(panel, r, "Page Format", "PAGE_SETUP_ON", "PAGE_SETUP_OFF", MSG_PAGE_SETUP);
// add description to button
r.OffsetTo(left + fPageSetup->Bounds().Width() + 5, top + fPageSetup->Bounds().Height()/2-5);
r.OffsetTo(left + fPageSetup->Bounds().Width() + 5, top + 5);
AddStringView(panel, r, "Setup page format");
r.OffsetBy(0, 10);
fPageFormatText = AddStringView(panel, r, "");
top += fPageSetup->Bounds().Height() + 5;
// page selection button
@@ -91,8 +155,10 @@ ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMes
r.OffsetTo(left, top);
fJobSetup = AddPictureButton(panel, r, "Page Selection", "JOB_SETUP_ON", "JOB_SETUP_OFF", MSG_JOB_SETUP);
// add description to button
r.OffsetTo(left + fJobSetup->Bounds().Width() + 5, top + fJobSetup->Bounds().Width()/2-5);
r.OffsetTo(left + fJobSetup->Bounds().Width() + 5, top + 5);
AddStringView(panel, r, "Setup print job");
r.OffsetBy(0, 10);
fJobSetupText = AddStringView(panel, r, "");
top += fJobSetup->Bounds().Height() + 5;
}
top += 5;
@@ -266,11 +332,13 @@ BPictureButton* ConfigWindow::AddPictureButton(BView* panel, BRect frame, const
return button;
}
void ConfigWindow::AddStringView(BView* panel, BRect frame, const char* text) {
BStringView* ConfigWindow::AddStringView(BView* panel, BRect frame, const char* text) {
// frame.bottom = frame.top ;
BStringView* string = new BStringView(frame, "", text);
string->SetViewColor(panel->ViewColor());
string->SetLowColor(panel->ViewColor());
panel->AddChild(string);
return string;
}
void ConfigWindow::PrinterForMimeType() {
@@ -347,8 +415,12 @@ void ConfigWindow::UpdateSettings(bool read) {
void ConfigWindow::UpdateUI() {
if (fCurrentPrinter == NULL) {
fPageSetup->SetEnabled(false);
if (fJobSetup) fJobSetup->SetEnabled(false);
if (fJobSetup) {
fJobSetup->SetEnabled(false);
fJobSetupText->SetText("Undefined job settings");
}
fOk->SetEnabled(false);
fPageFormatText->SetText("Undefined paper format");
} else {
fPageSetup->SetEnabled(true);
@@ -357,6 +429,43 @@ void ConfigWindow::UpdateUI() {
}
fOk->SetEnabled(fKind == kJobSetup && !fJobSettings.IsEmpty() ||
fKind == kPageSetup && !fPageSettings.IsEmpty());
// display information about page format
BRect paperRect;
BString pageFormat;
if (fPageSettings.FindRect(PSRV_FIELD_PAPER_RECT, &paperRect) == B_OK) {
GetPageFormat(paperRect.Width(), paperRect.Height(), pageFormat);
int32 orientation = 0;
fPageSettings.FindInt32(PSRV_FIELD_ORIENTATION, &orientation);
if (orientation == 0) pageFormat << ", Portrait";
else pageFormat << ", Landscape";
} else {
pageFormat << "Undefined paper format";
}
fPageFormatText->SetText(pageFormat.String());
// display information about job
if (fKind == kJobSetup) {
BString job;
int32 first, last, copies;
if (fJobSettings.FindInt32(PSRV_FIELD_FIRST_PAGE, &first) == B_OK &&
fJobSettings.FindInt32(PSRV_FIELD_LAST_PAGE, &last) == B_OK) {
if (first >= 1 && first <= last && last != INT_MAX) {
job << "From page " << first << " to " << last;
} else {
job << "All pages";
}
int32 copies;
if (fJobSettings.FindInt32(PSRV_FIELD_COPIES, &copies) == B_OK && copies > 1) {
job << ", " << copies << " copies";
}
} else {
job << "Undefined job settings";
}
fJobSetupText->SetText(job.String());
}
}
}
+3 -1
View File
@@ -65,7 +65,7 @@ public:
private:
BPictureButton* AddPictureButton(BView* panel, BRect frame, const char* name, const char* on, const char* off, uint32 what);
void AddStringView(BView* panel, BRect frame, const char* text);
BStringView* AddStringView(BView* panel, BRect frame, const char* text);
void PrinterForMimeType();
void SetupPrintersMenu(BMenu* menu);
void UpdateAppSettings(const char* mime, const char* printer);
@@ -90,6 +90,8 @@ private:
BPictureButton* fPageSetup;
BPictureButton* fJobSetup;
BButton* fOk;
BStringView* fPageFormatText;
BStringView* fJobSetupText;
};
#endif
+7 -5
View File
@@ -1,7 +1,10 @@
SubDir OBOS_TOP src servers print ;
UsePrivateHeaders interface ;
UsePrivateHeaders shared ;
SubInclude OBOS_TOP src servers print shared ;
SubDir OBOS_TOP src servers print ;
UsePrivateHeaders shared interface print ;
AddResources
print_server
@@ -18,8 +21,6 @@ Server
Printer.Scripting.cpp
Printer.cpp
ResourceManager.cpp
Jobs.cpp
BeUtils.cpp
Settings.cpp
ConfigWindow.cpp
;
@@ -29,5 +30,6 @@ LinkSharedOSLibs
:
be
root
translation
translation
libprint.a
;
+35
View File
@@ -126,6 +126,38 @@ status_t PrintServerApp::async_thread(void* data)
}
}
break;
// Create a new printer
case PSRV_MAKE_PRINTER: {
BString driverName, transportName, transportPath;
BString printerName, connection;
if (msg->FindString("driver", &driverName) == B_OK &&
msg->FindString("transport", &transportName) == B_OK &&
msg->FindString("transport path", &transportPath) == B_OK &&
msg->FindString("printer name", &printerName) == B_OK
) {
if (msg->FindString("connection", &connection) != B_OK)
connection = "Local";
// then create the actual printer
if (p->app->CreatePrinter(printerName.String(), driverName.String(),
connection.String(),
transportName.String(), transportPath.String()) == B_OK) {
// If printer was created ok, ask if it needs to be the default
char buffer[256];
::sprintf(buffer, "Would you like to make %s the default\nprinter?",
printerName.String());
BAlert* alert = new BAlert("", buffer, "No", "Yes");
if (alert->Go() == 1) {
p->app->SelectPrinter(printerName.String());
}
}
}
}
break;
}
}
@@ -180,6 +212,7 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
}
break;
#if 0
// Create a new printer
case PSRV_MAKE_PRINTER: {
BString driverName, transportName, transportPath;
@@ -211,10 +244,12 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg)
}
}
break;
#endif
case PSRV_SHOW_PAGE_SETUP:
case PSRV_SHOW_PRINT_SETUP:
case PSRV_GET_DEFAULT_SETTINGS:
case PSRV_MAKE_PRINTER:
AsyncHandleMessage(DetachCurrentMessage());
break;
@@ -13,7 +13,7 @@
// 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"),
+51 -28
View File
@@ -14,7 +14,7 @@
// 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"),
@@ -112,7 +112,8 @@ PrintServerApp::PrintServerApp(status_t* err)
fSelectedIconLarge(NULL),
fReferences(0),
fHasReferences(0),
fUseConfigWindow(true)
fUseConfigWindow(true),
fFolder(NULL)
{
fSettings = Settings::GetSettings();
LoadSettings();
@@ -151,6 +152,8 @@ bool PrintServerApp::QuitRequested()
bool rc = Inherited::QuitRequested();
if (rc) {
delete fFolder; fFolder = NULL;
#if 0
// Find directory containing printer definition nodes
BPath path;
if (::find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK) {
@@ -162,6 +165,7 @@ bool PrintServerApp::QuitRequested()
::watch_node(&nref, B_STOP_WATCHING, be_app_messenger);
}
}
#endif
// Release all printers
Printer* printer;
@@ -195,18 +199,28 @@ void PrintServerApp::Release() {
}
void PrintServerApp::RegisterPrinter(BDirectory* printer) {
BString transport, address, connection;
BString transport, address, connection, state;
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport);
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address);
printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection);
if (printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection) == B_OK &&
printer->ReadAttrString(PSRV_PRINTER_ATTR_STATE, &state) == B_OK &&
state == "free") {
BAutolock lock(gLock);
if (lock.IsLocked()) {
Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String());
Printer* p = new Printer(printer, r);
AddHandler(p);
Acquire();
BAutolock lock(gLock);
if (lock.IsLocked()) {
// check if printer is already registered
node_ref node;
Printer* p;
if (printer->GetNodeRef(&node) != B_OK) return;
p = Printer::Find(&node);
if (p != NULL) return;
// register new printer
Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String());
p = new Printer(printer, r);
AddHandler(p);
Acquire();
}
}
}
@@ -224,20 +238,29 @@ void PrintServerApp::NotifyPrinterDeletion(Printer* printer) {
}
}
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) {
void PrintServerApp::EntryCreated(node_ref* node, entry_ref* entry) {
BEntry printer(entry);
if (printer.InitCheck() == B_OK && printer.IsDirectory()) {
BDirectory dir(&printer);
if (dir.InitCheck() == B_OK) RegisterPrinter(&dir);
}
}
void PrintServerApp::EntryRemoved(node_ref* node) {
Printer* printer = Printer::Find(node);
if (printer) {
if (printer == fDefaultPrinter) fDefaultPrinter = NULL;
UnregisterPrinter(printer);
}
}
void PrintServerApp::AttributeChanged(node_ref* node) {
BDirectory printer(node);
if (printer.InitCheck() == B_OK) {
RegisterPrinter(&printer);
}
}
// ---------------------------------------------------------------
// SetupPrinterList
@@ -280,7 +303,11 @@ status_t PrintServerApp::SetupPrinterList()
}
}
}
fFolder = new FolderWatcher(this, dir, true);
fFolder->SetListener(this);
#if 0
// If we scanned all entries successfully
node_ref nref;
if (rc == B_ENTRY_NOT_FOUND &&
@@ -288,6 +315,7 @@ status_t PrintServerApp::SetupPrinterList()
// Get node to watch
rc = ::watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger);
}
#endif
}
}
@@ -328,10 +356,6 @@ PrintServerApp::MessageReceived(BMessage* msg)
case B_EXECUTE_PROPERTY:
HandleScriptingCommand(msg);
break;
case B_NODE_MONITOR:
HandleRemovedPrinter(msg);
break;
default:
Inherited::MessageReceived(msg);
@@ -378,7 +402,6 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName,
// Store the settings in its attributes
printer.WriteAttr(PSRV_PRINTER_ATTR_PRT_NAME, B_STRING_TYPE, 0, printerName, ::strlen(printerName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_DRV_NAME, B_STRING_TYPE, 0, driverName, ::strlen(driverName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT, B_STRING_TYPE, 0, transportName,::strlen(transportName)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, B_STRING_TYPE, 0, transportPath,::strlen(transportPath)+1);
printer.WriteAttr(PSRV_PRINTER_ATTR_CNX, B_STRING_TYPE, 0, connection, ::strlen(connection)+1);
@@ -399,7 +422,7 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName,
entry.Remove();
}
} else {
RegisterPrinter(&printer);
printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1);
}
}
+9 -4
View File
@@ -14,7 +14,7 @@
// 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"),
@@ -40,6 +40,7 @@
#include "ResourceManager.h"
#include "Settings.h"
#include "FolderWatcher.h"
class PrintServerApp;
@@ -57,7 +58,7 @@ extern BLocker* gLock;
// Application class for print_server.
/*****************************************************************************/
class Printer;
class PrintServerApp : public BApplication
class PrintServerApp : public BApplication, public FolderListener
{
typedef BApplication Inherited;
public:
@@ -93,8 +94,11 @@ private:
void RegisterPrinter(BDirectory* node);
void UnregisterPrinter(Printer* printer);
void HandleRemovedPrinter(BMessage* msg);
// FolderListener
void EntryCreated(node_ref* node, entry_ref* entry);
void EntryRemoved(node_ref* node);
void AttributeChanged(node_ref* node);
status_t StoreDefaultPrinter();
status_t RetrieveDefaultPrinter();
@@ -109,6 +113,7 @@ private:
sem_id fHasReferences;
Settings*fSettings;
bool fUseConfigWindow;
FolderWatcher* fFolder;
// "Classic" BeOS R5 support, see PrintServerApp.R5.cpp
static status_t async_thread(void* data);
+1 -1
View File
@@ -13,7 +13,7 @@
// 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"),
+22 -5
View File
@@ -55,6 +55,23 @@
#include <StorageKit.h>
#include <SupportDefs.h>
SpoolFolder::SpoolFolder(BLocker*locker, BLooper* looper, const BDirectory& spoolDir)
: Folder(locker, looper, spoolDir)
{
}
// Notify print_server that there is a job file waiting for printing
void SpoolFolder::Notify(Job* job, int kind)
{
if ((kind == kJobAdded || kind == kJobAttrChanged) &&
job->IsValid() && job->IsWaiting()) {
be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB);
}
}
// ---------------------------------------------------------------
typedef BMessage* (*config_func_t)(BNode*, const BMessage*);
typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*);
@@ -90,14 +107,14 @@ Printer* Printer::Find(const BString& name)
return NULL;
}
Printer* Printer::Find(dev_t dev, ino_t node)
Printer* Printer::Find(node_ref* node)
{
node_ref n;
// Look in list to find printer definition
for (int32 idx=0; idx < sPrinters.CountItems(); idx++) {
Printer* printer = sPrinters.ItemAt(idx);
node_ref ref;
printer->SpoolDir()->GetNodeRef(&ref);
if (ref.device == dev && ref.node == node) return printer;
printer->SpoolDir()->GetNodeRef(&n);
if (n == *node) return printer;
}
// None found, so return NULL
@@ -132,7 +149,7 @@ int32 Printer::CountPrinters()
// ---------------------------------------------------------------
Printer::Printer(const BDirectory* node, Resource* res)
: Inherited(B_EMPTY_STRING),
fPrinter(*node),
fPrinter(gLock, be_app, *node),
fResource(res),
fSinglePrintThread(true),
fJob(NULL),
+12 -4
View File
@@ -14,7 +14,7 @@
// 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"),
@@ -55,6 +55,14 @@ class Printer;
// OpenTracker shared sources
#include "ObjectList.h"
class SpoolFolder : public Folder {
protected:
void Notify(Job* job, int kind);
public:
SpoolFolder(BLocker* locker, BLooper* looper, const BDirectory& spoolDir);
};
/*****************************************************************************/
// Printer
//
@@ -71,7 +79,7 @@ public:
// Static helper functions
static Printer* Find(const BString& name);
static Printer* Find(dev_t device, ino_t node);
static Printer* Find(node_ref* node);
static Printer* At(int32 idx);
static void Remove(Printer* printer);
static int32 CountPrinters();
@@ -102,11 +110,11 @@ private:
status_t LoadPrinterAddon(image_id& id);
void AddCurrentPrinter(BMessage* m);
Folder fPrinter; // the printer spooling directory
Resource* fResource; // the resource required for processing a print job
SpoolFolder fPrinter; // the printer spooling directory
bool fSinglePrintThread; // is printer add-on allowed to process multiple print job at once
Job* fJob; // the next job to process
vint32 fProcessing; // the current number of processing threads
vint32 fProcessing; // the current nmber of processing threads
bool fAbort; // stop processing
static BObjectList<Printer> sPrinters;
@@ -15,7 +15,7 @@
// 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"),
+175
View File
@@ -0,0 +1,175 @@
/*****************************************************************************/
// FolderWatcher
//
// 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 "FolderWatcher.h"
#include <stdio.h>
// BeOS
#include <kernel/fs_attr.h>
#include <Node.h>
#include <NodeInfo.h>
#include <NodeMonitor.h>
// Implementation of FolderWatcher
FolderWatcher::FolderWatcher(BLooper* looper, const BDirectory& folder, bool watchAttrChanges)
: fFolder(folder)
, fListener(NULL)
, fWatchAttrChanges(watchAttrChanges)
{
// add this handler to the application for node monitoring
if (looper->Lock()) {
looper->AddHandler(this);
looper->Unlock();
}
// start attribute change watching for existing files
if (watchAttrChanges) {
BEntry entry;
node_ref node;
while (fFolder.GetNextEntry(&entry) == B_OK && entry.GetNodeRef(&node) == B_OK) {
StartAttrWatching(&node);
}
}
// start watching the spooler directory
node_ref ref;
fFolder.GetNodeRef(&ref);
watch_node(&ref, B_WATCH_DIRECTORY, this);
}
FolderWatcher::~FolderWatcher() {
// stop node watching for spooler directory
node_ref ref;
fFolder.GetNodeRef(&ref);
watch_node(&ref, B_STOP_WATCHING, this);
// stop sending notifications to this handler
stop_watching(this);
if (LockLooper()) {
BLooper* looper = Looper();
// and remove it
looper->RemoveHandler(this);
looper->Unlock();
}
}
void FolderWatcher::SetListener(FolderListener* listener) {
fListener = listener;
}
bool FolderWatcher::BuildEntryRef(BMessage* msg, const char* dirName, entry_ref* entry) {
const char* name;
if (msg->FindInt32("device", &entry->device) == B_OK &&
msg->FindInt64(dirName, &entry->directory) == B_OK &&
msg->FindString("name", &name) == B_OK) {
entry->set_name(name);
return true;
}
return false;
}
bool FolderWatcher::BuildNodeRef(BMessage* msg, node_ref* node) {
return (msg->FindInt32("device", &node->device) == B_OK &&
msg->FindInt64("node", &node->node) == B_OK);
}
void FolderWatcher::HandleCreatedEntry(BMessage* msg, const char* dirName) {
node_ref node;
entry_ref entry;
if (BuildEntryRef(msg, dirName, &entry) &&
BuildNodeRef(msg, &node)) {
if (fWatchAttrChanges) StartAttrWatching(&node);
fListener->EntryCreated(&node, &entry);
}
}
void FolderWatcher::HandleRemovedEntry(BMessage* msg) {
node_ref node;
if (BuildNodeRef(msg, &node)) {
if (fWatchAttrChanges) StopAttrWatching(&node);
fListener->EntryRemoved(&node);
}
}
void FolderWatcher::HandleChangedAttr(BMessage* msg) {
node_ref node;
if (BuildNodeRef(msg, &node)) {
fListener->AttributeChanged(&node);
}
}
void FolderWatcher::MessageReceived(BMessage* msg) {
int32 opcode;
node_ref folder;
ino_t dir;
if (msg->what == B_NODE_MONITOR) {
if (fListener == NULL || msg->FindInt32("opcode", &opcode) != B_OK) return;
switch (opcode) {
case B_ENTRY_CREATED:
HandleCreatedEntry(msg, "directory");
break;
case B_ENTRY_REMOVED:
HandleRemovedEntry(msg);
break;
case B_ENTRY_MOVED:
fFolder.GetNodeRef(&folder);
if (msg->FindInt64("to directory", &dir) == B_OK && folder.node == dir) {
// entry moved into this folder
HandleCreatedEntry(msg, "to directory");
} else if (msg->FindInt64("from directory", &dir) == B_OK && folder.node == dir) {
// entry removed from this folder
HandleRemovedEntry(msg);
}
break;
case B_ATTR_CHANGED:
HandleChangedAttr(msg);
break;
default: // nothing to do
break;
}
} else {
inherited::MessageReceived(msg);
}
}
status_t FolderWatcher::StartAttrWatching(node_ref* node) {
return watch_node(node, B_WATCH_ATTR, this);
}
status_t FolderWatcher::StopAttrWatching(node_ref* node) {
return watch_node(node, B_STOP_WATCHING, this);
}
+11
View File
@@ -0,0 +1,11 @@
SubDir OBOS_TOP src servers print shared ;
UsePrivateHeaders shared interface print ;
StaticLibrary
print
:
BeUtils.cpp
FolderWatcher.cpp
Jobs.cpp
;
+265
View File
@@ -0,0 +1,265 @@
/*****************************************************************************/
// 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 <kernel/fs_attr.h>
#include <Application.h>
#include <Node.h>
#include <NodeInfo.h>
#include <NodeMonitor.h>
// Implementation of Job
Job::Job(const BEntry& job, Folder* folder)
: fFolder(folder)
, fTime(-1)
, fStatus(kUnknown)
, fValid(false)
, fPrinter(NULL)
{
// store light weight versions of BEntry and BNode
job.GetRef(&fEntry);
job.GetNodeRef(&fNode);
fValid = IsValidJobFile();
BNode node(&job);
if (node.InitCheck() != B_OK) return;
BString status;
// read status attribute
if (node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) != B_OK) {
status = "";
}
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
if (p) fTime = atoi(p+1);
}
}
// 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 if (strcmp(status, PSRV_JOB_STATUS_COMPLETED) == 0) fStatus = kCompleted;
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);
}
}
bool Job::HasAttribute(BNode* n, const char* name) {
attr_info info;
return n->GetAttrInfo(name, &info) == B_OK;
}
bool Job::IsValidJobFile() {
BNode node(&fEntry);
if (node.InitCheck() != B_OK) return false;
BNodeInfo info(&node);
char mimeType[256];
// Is job a spool file?
return (info.InitCheck() == B_OK &&
info.GetType(mimeType) == B_OK &&
strcmp(mimeType, PSRV_SPOOL_FILETYPE) == 0) &&
HasAttribute(&node, PSRV_SPOOL_ATTR_MIMETYPE) &&
HasAttribute(&node, PSRV_SPOOL_ATTR_PAGECOUNT) &&
HasAttribute(&node, PSRV_SPOOL_ATTR_DESCRIPTION) &&
HasAttribute(&node, PSRV_SPOOL_ATTR_PRINTER) &&
HasAttribute(&node, PSRV_SPOOL_ATTR_STATUS);
}
// 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;
case kCompleted: UpdateStatusAttribute(PSRV_JOB_STATUS_COMPLETED); break;
default: break;
}
}
// Synchronize file attribute with member variable
void Job::UpdateAttribute() {
fValid = fValid || IsValidJobFile();
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();
}
// Implementation of Folder
// BObjectList CompareFunction
int Folder::AscendingByTime(const Job* a, const Job* b) {
return a->Time() - b->Time();
}
bool Folder::AddJob(BEntry& entry, bool notify) {
Job* job = new Job(entry, this);
if (job->InitCheck() == B_OK) {
fJobs.AddItem(job);
if (notify) Notify(job, kJobAdded);
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(node_ref* node) {
for (int i = 0; i < fJobs.CountItems(); i ++) {
Job* job = fJobs.ItemAt(i);
if (job->NodeRef() == *node) return job;
}
return NULL;
}
void Folder::EntryCreated(node_ref* node, entry_ref* entry) {
BEntry job(entry);
if (job.InitCheck() == B_OK && Lock()) {
if (AddJob(job)) {
fJobs.SortItems(AscendingByTime);
}
Unlock();
}
}
void Folder::EntryRemoved(node_ref* node) {
Job* job = Find(node);
if (job && Lock()) {
fJobs.RemoveItem(job);
Notify(job, kJobRemoved);
job->Release();
Unlock();
}
}
void Folder::AttributeChanged(node_ref* node) {
Job* job = Find(node);
if (job && Lock()) {
job->UpdateAttribute();
Notify(job, kJobAttrChanged);
Unlock();
}
}
// initial setup of job list
void Folder::SetupJobList() {
if (inherited::Folder()->InitCheck() == B_OK) {
inherited::Folder()->Rewind();
BEntry entry;
while (inherited::Folder()->GetNextEntry(&entry) == B_OK) {
AddJob(entry, false);
}
fJobs.SortItems(AscendingByTime);
}
}
Folder::Folder(BLocker* locker, BLooper* looper, const BDirectory& spoolDir)
: fLocker(locker)
, FolderWatcher(looper, spoolDir, true)
, fJobs()
{
SetListener(this);
if (Lock()) {
SetupJobList();
Unlock();
}
}
Folder::~Folder() {
if (!Lock()) return;
// release jobs
for (int i = 0; i < fJobs.CountItems(); i ++) {
Job* job = fJobs.ItemAt(i);
job->Release();
}
Unlock();
}
Job* Folder::GetNextJob() {
for (int i = 0; i < fJobs.CountItems(); i ++) {
Job* job = fJobs.ItemAt(i);
if (job->IsValid() && job->IsWaiting()) {
job->Acquire(); return job;
}
}
return NULL;
}