예제 #1
0
// GetJobState gets the current state of the job indicated by jobID.
func (c *CUPS) GetJobState(jobID uint32) (cdd.PrintJobStateDiff, error) {
	ja := C.newArrayOfStrings(C.int(len(jobAttributes)))
	defer C.freeStringArrayAndStrings(ja, C.int(len(jobAttributes)))
	for i, attribute := range jobAttributes {
		C.setStringArrayValue(ja, C.int(i), C.CString(attribute))
	}

	response, err := c.cc.getJobAttributes(C.int(jobID), ja)
	if err != nil {
		return cdd.PrintJobStateDiff{}, err
	}

	// cupsDoRequest() returned ipp_t pointer needs explicit free.
	defer C.ippDelete(response)

	s := C.ippFindAttribute(response, C.JOB_STATE, C.IPP_TAG_ENUM)
	state := int32(C.ippGetInteger(s, C.int(0)))

	p := C.ippFindAttribute(response, C.JOB_MEDIA_SHEETS_COMPLETED, C.IPP_TAG_INTEGER)
	var pages int32
	if p != nil {
		pages = int32(C.ippGetInteger(p, C.int(0)))
	}

	return convertJobState(state, pages), nil
}
예제 #2
0
// attributesToTags converts a slice of C.ipp_attribute_t to a
// string:string "tag" map. Outside of this package, "printer attributes" are
// known as "tags".
func attributesToTags(attributes []*C.ipp_attribute_t) map[string][]string {
	tags := make(map[string][]string)

	for _, a := range attributes {
		key := C.GoString(C.ippGetName(a))
		count := int(C.ippGetCount(a))
		values := make([]string, count)

		switch C.ippGetValueTag(a) {
		case C.IPP_TAG_NOVALUE, C.IPP_TAG_NOTSETTABLE:
			// No value means no value.

		case C.IPP_TAG_INTEGER, C.IPP_TAG_ENUM:
			for i := 0; i < count; i++ {
				values[i] = strconv.FormatInt(int64(C.ippGetInteger(a, C.int(i))), 10)
			}

		case C.IPP_TAG_BOOLEAN:
			for i := 0; i < count; i++ {
				if int(C.ippGetInteger(a, C.int(i))) == 0 {
					values[i] = "false"
				} else {
					values[i] = "true"
				}
			}

		case C.IPP_TAG_STRING, C.IPP_TAG_TEXT, C.IPP_TAG_NAME, C.IPP_TAG_KEYWORD, C.IPP_TAG_URI, C.IPP_TAG_CHARSET, C.IPP_TAG_LANGUAGE, C.IPP_TAG_MIMETYPE:
			for i := 0; i < count; i++ {
				values[i] = C.GoString(C.ippGetString(a, C.int(i), nil))
			}

		case C.IPP_TAG_DATE:
			for i := 0; i < count; i++ {
				date := C.ippGetDate(a, C.int(i))
				t := convertIPPDateToTime(date)
				values[i] = strconv.FormatInt(t.Unix(), 10)
			}

		case C.IPP_TAG_RESOLUTION:
			for i := 0; i < count; i++ {
				yres := C.int(-1)
				unit := C.int(-1)
				xres := C.ippGetResolutionWrapper(a, C.int(i), &yres, &unit)
				if unit == C.IPP_RES_PER_CM {
					values[i] = fmt.Sprintf("%dx%dpp%s", int(xres), int(yres), "cm")
				} else {
					values[i] = fmt.Sprintf("%dx%dpp%s", int(xres), int(yres), "i")
				}
			}

		case C.IPP_TAG_RANGE:
			for i := 0; i < count; i++ {
				uppervalue := C.int(-1)
				lowervalue := C.ippGetRange(a, C.int(i), &uppervalue)
				values[i] = fmt.Sprintf("%d~%d", int(lowervalue), int(uppervalue))
			}

		default:
			if count > 0 {
				values = []string{"unknown or unsupported type"}
			}
		}

		if len(values) == 1 && values[0] == "none" {
			values = []string{}
		}
		// This block fixes some drivers' marker types, which list an extra
		// type containing a comma, which CUPS interprets as an extra type.
		// The extra type starts with a space, so it's easy to detect.
		if len(values) > 1 && len(values[len(values)-1]) > 1 && values[len(values)-1][0:1] == " " {
			newValues := make([]string, len(values)-1)
			for i := 0; i < len(values)-2; i++ {
				newValues[i] = values[i]
			}
			newValues[len(newValues)-1] = strings.Join(values[len(values)-2:], ",")
			values = newValues
		}
		tags[key] = values
	}

	return tags
}