xref: /haiku/src/add-ons/print/drivers/gutenprint/GPBinding.cpp (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
1 /*
2 * Copyright 2010, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Pfeiffer
7 */
8 #include "GPBinding.h"
9 
10 #include <list>
11 #include <set>
12 #include <string>
13 
14 #include <gutenprint/gutenprint.h>
15 
16 
17 #include "GPCapabilityExtractor.h"
18 
19 using namespace std;
20 
21 
22 // printer manufacturer
23 static const char* kManufacturerId = "id";
24 static const char* kManufacturerDisplayName = "name";
25 
26 // printer model
27 static const char* kModelDisplayName = "model";
28 static const char* kModelDriver = "driver";
29 
30 
31 GPBinding::GPBinding()
32 :
33 fInitialized(false),
34 fOutputStream(NULL)
35 {
36 
37 }
38 
39 
40 GPBinding::~GPBinding()
41 {
42 	DeleteBands();
43 }
44 
45 
46 status_t
47 GPBinding::GetPrinterManufacturers(BMessage& manufacturers)
48 {
49 	InitGutenprint();
50 
51 	list<string> ids;
52 	set<string> manufacturerSet;
53 
54 	for (int i = 0; i < stp_printer_model_count(); i ++) {
55 		const stp_printer_t* printer = stp_get_printer_by_index(i);
56 		string manufacturer = stp_printer_get_manufacturer(printer);
57 
58 		// ignore unnamed manufacturers
59 		if (manufacturer == "")
60 			continue;
61 
62 		// add manufacturer only once
63 		if (manufacturerSet.find(manufacturer) != manufacturerSet.end())
64 			continue;
65 
66 		manufacturerSet.insert(manufacturer);
67 
68 		ids.push_back(manufacturer);
69 	}
70 
71 	ids.sort();
72 
73 	list<string>::iterator it = ids.begin();
74 	for (; it != ids.end(); it ++) {
75 		string manufacturer = *it;
76 		const char* id = manufacturer.c_str();
77 		const char* name = manufacturer.c_str();
78 		AddManufacturer(manufacturers, id, name);
79 	}
80 	return B_OK;
81 }
82 
83 
84 bool
85 GPBinding::ExtractManufacturer(const BMessage& manufacturers, int32 index,
86 	BString& id, BString& displayName)
87 {
88 	if (manufacturers.FindString(kManufacturerId, index, &id) != B_OK)
89 		return false;
90 	if (manufacturers.FindString(kManufacturerDisplayName, index, &displayName)
91 		!= B_OK)
92 		return false;
93 	return true;
94 }
95 
96 
97 void
98 GPBinding::AddManufacturer(BMessage& manufacturers, const char* id,
99 	const char* displayName)
100 {
101 	manufacturers.AddString(kManufacturerId, id);
102 	manufacturers.AddString(kManufacturerDisplayName, displayName);
103 }
104 
105 
106 status_t
107 GPBinding::GetPrinterModels(const char* manufacturer, BMessage& models)
108 {
109 	for (int i = 0; i < stp_printer_model_count(); i ++) {
110 		const stp_printer_t* printer = stp_get_printer_by_index(i);
111 		if (strcmp(manufacturer, stp_printer_get_manufacturer(printer)) != 0)
112 			continue;
113 
114 		const char* displayName = stp_printer_get_long_name(printer);
115 		const char* driver = stp_printer_get_driver(printer);
116 		AddModel(models, displayName, driver);
117 	}
118 	return B_OK;
119 }
120 
121 
122 bool
123 GPBinding::ExtractModel(const BMessage& models, int32 index, BString& displayName,
124 	BString& driver)
125 {
126 	if (models.FindString(kModelDisplayName, index, &displayName) != B_OK)
127 		return false;
128 	if (models.FindString(kModelDriver, index, &driver) != B_OK)
129 		return false;
130 	return true;
131 }
132 
133 
134 void
135 GPBinding::AddModel(BMessage& models, const char* displayName,	const char* driver)
136 {
137 	models.AddString(kModelDisplayName, displayName);
138 	models.AddString(kModelDriver, driver);
139 }
140 
141 
142 status_t
143 GPBinding::GetCapabilities(const char* driver, GPCapabilities* capabilities)
144 {
145 	InitGutenprint();
146 	const stp_printer_t* printer = stp_get_printer_by_driver(driver);
147 	if (printer == NULL)
148 		return B_ERROR;
149 
150 	GPCapabilityExtractor extractor(capabilities);
151 	extractor.Visit(printer);
152 	return B_OK;
153 }
154 
155 
156 status_t
157 GPBinding::BeginJob(GPJobConfiguration* configuration,
158 	OutputStream* outputStream)
159 {
160 	fOutputStream = outputStream;
161 	fJob.SetApplicationName("Gutenprint");
162 	fJob.SetConfiguration(configuration);
163 	fJob.SetOutputStream(outputStream);
164 
165 	return fJob.Begin();
166 }
167 
168 
169 void
170 GPBinding::EndJob()
171 {
172 	fJob.End();
173 	fOutputStream = NULL;
174 }
175 
176 
177 void
178 GPBinding::BeginPage()
179 {
180 }
181 
182 
183 void
184 GPBinding::EndPage()
185 {
186 	status_t status = fJob.PrintPage(fBands);
187 	DeleteBands();
188 	if (status == B_IO_ERROR)
189 		throw TransportException("I/O Error");
190 	if (status == B_ERROR) {
191 		BString message;
192 		fJob.GetErrorMessage(message);
193 		throw TransportException(message.String());
194 	}
195 }
196 
197 
198 status_t
199 GPBinding::AddBitmapToPage(BBitmap* bitmap, BRect validRect, BPoint where)
200 {
201 	GPBand* band = new(nothrow) GPBand(bitmap, validRect, where);
202 	if (band == NULL) {
203 		return B_NO_MEMORY;
204 	}
205 
206 	fBands.push_back(band);
207 	return B_OK;
208 }
209 
210 
211 void
212 GPBinding::InitGutenprint()
213 {
214 	if (fInitialized)
215 		return;
216 	fInitialized = true;
217 	// there is no "destroy" counter part so this creates memory leaks
218 	// this is no problem because the print server loads printer add-ons
219 	// in a new application instance that is terminated when not used anymore
220 	stp_init();
221 	stp_set_output_codeset("UTF-8");
222 }
223 
224 
225 void
226 GPBinding::DeleteBands()
227 {
228 	list<GPBand*>::iterator it = fBands.begin();
229 	for (; it != fBands.end(); it ++) {
230 		GPBand* band = *it;
231 		delete band;
232 	}
233 	fBands.clear();
234 }
235