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
GPBinding()31 GPBinding::GPBinding()
32 :
33 fInitialized(false),
34 fOutputStream(NULL)
35 {
36
37 }
38
39
~GPBinding()40 GPBinding::~GPBinding()
41 {
42 DeleteBands();
43 }
44
45
46 status_t
GetPrinterManufacturers(BMessage & manufacturers)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
ExtractManufacturer(const BMessage & manufacturers,int32 index,BString & id,BString & displayName)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
AddManufacturer(BMessage & manufacturers,const char * id,const char * displayName)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
GetPrinterModels(const char * manufacturer,BMessage & models)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
ExtractModel(const BMessage & models,int32 index,BString & displayName,BString & driver)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
AddModel(BMessage & models,const char * displayName,const char * driver)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
GetCapabilities(const char * driver,GPCapabilities * capabilities)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
BeginJob(GPJobConfiguration * configuration,OutputStream * outputStream)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
EndJob()170 GPBinding::EndJob()
171 {
172 fJob.End();
173 fOutputStream = NULL;
174 }
175
176
177 void
BeginPage()178 GPBinding::BeginPage()
179 {
180 }
181
182
183 void
EndPage()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
AddBitmapToPage(BBitmap * bitmap,BRect validRect,BPoint where)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
InitGutenprint()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
DeleteBands()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