smart_jobname - программа для отображения размеров сепарации в окне Output Controller на Harlequin R

Статус
Закрыто для дальнейших ответов.

oshch

Участник
Топикстартер
Сообщения
15
Реакции
73
Выкладываю свой вариант. Берите, кому надо.

smart_jobname_v.1.0 (page feature for Harlequin RIP)

Программа создает комбинированное имя для задания, содержащее размеры, время и день риповки и некоторые предупреждения.
Кроме того, программа выполняет ожидание полной записи файла перед началом рипования,
а также отключает вывод заданий на фотонабор, если активная очередь пуста.
Разрабатывалось и тестировалось для ECRM RIPMate 7.2 на базе Harlequin RIP Genesis Release (7.2r0).

Архив с программой:

Посмотреть вложение smart_jobname_v_1.zip

Скриншот:

smart_jobname_v_1_screenshot.jpg

Код программы тоже выложу здесь, чтобы поисковиками проиндексировался.

Пишите в этой ветке, если есть какие-нибудь предложения по улучшению, исправлению ошибок.

Мне также будет приятно почитать положительные отзывы ;)
 

oshch

Участник
Топикстартер
Сообщения
15
Реакции
73
smart_jobname_v.1.0 (Part 1)

Код программы. Первая часть.

Код:
%!PS-Adobe-3.0
%%Title: smart_jobname_v.1.0 page feature for Harlequin RIP.
%%CreationDate: Jul 2012
%%Creator: Oleg Shchukin
%
% Программа создает комбинированное имя для задания, содержащее размеры и предупреждения.
% Кроме того, программа выполняет ожидание полной записи файла перед началом рипования,
% а также отключает вывод заданий на фотонабор, если активная очередь пуста. 
% Разрабатывалось и тестировалось для ECRM RIPMate 7.2 на базе Harlequin RIP Genesis Release (7.2r0). 
%
% Copyright (с) Олег Щукин, 2012.
% Copyright (с) Издательский дом ПИН, г. Петрозаводск, 2012. http://www.pinptz.ru
% ECRM RIPMate(R) и Harlequin(R) являются зарегистрированными торговыми марками их владельцев.
%
% Условия использования: вы можете использовать эту программу бесплатно.
% Условия распространения: вы можете распространять эту программу без ограничений.
% Условия модификации: вы можете изменять эту программу, но должны сохранить имеющиеся здесь копирайты.
% Условия использования исходного кода: вы можете использовать код программы в других программах бесплатно.
%
% Установка: скопируйте файл smart_jobname_v.1.0 в каталог "sw\Page Features\",
%  затем в окне "Edit Page Setup" в списке "Enable Feature" выберите "smart_jobname_v.1.0".
%
%
% Если вы внесли изменения в программу, опишите их здесь:
%
% (Внесены такие-то изменения, кем, когда).
%
%
%%EndComments


21 dict begin

% ======================= Localization data
% Set the language to use:
% 0 - English
% 1 - Russian (проверено для Windows)
/UseLanguage 1 def

/EnglishLabels <<
 /copies ( copies ?!)
 /mm ( mm )
 /wider_than_media ( Wider than media!)
 /need_rotation ( Rotate it!)
>> def

/RussianLabels <<
 /copies ( -Fu-Fy-Fz-Fs-Fs ?!)
 /mm ( -Fw-Fw )
 /wider_than_media ( -Fx-Fp -Fz-G--Fy-Fv-Fk-Fr-Fs-G1!)
 /need_rotation ( -Fz-Fy-Fm-Fp-G--Fx-Fs -Fw-Fp-Fx-GE!)
>> def

% =======================

% Выбор строки нужного языка по указанному литералу:
/funcLocalizedLabel {
  //UseLanguage 0 eq
  {
    //EnglishLabels
  }
  {
    //RussianLabels
  } ifelse
  exch get
} bind def

% Печать стека операндов на консоль. Можно использовать при отладке.
/procPrintStack {
  (Stack content :\n) print
  (begin>>>\n) print
  pstack
  (<<<end\n) print
} def

% Объединение двух строк в одну.
% (abc) (def) funcCombineStrings (abcdef)
/funcCombineStrings {
  exch dup length dup 3 index length add string
  dup 0 5 -1 roll putinterval
  dup 4 2 roll exch putinterval
} bind def

% Объединение массива строк в одну строку:
% [(ab1) (cd2) (ef3)] funcArrayToString (ab1cd2ef3)
/funcArrayToString {
  dup 0 exch { length add } forall string
  exch 0 exch {
    exch dup 2 index length add 4 copy pop exch putinterval exch pop exch pop
  } forall
  pop
} bind def

% Ожидает указанное число миллисекунд (спин-таймер):
/procSleep {
  usertime add {
    dup usertime le { exit } if
  } loop pop
} def
 
% Удалить из стека все значения до марки, кроме самого верхнего (марка тоже удаляется): 
/procClearToMarkButKeepTop {
  counttomark
  1 add
  1 roll
  cleartomark
} bind def

% Время дня в формате "HH:MM": 23:55
/funcLocaleDayTimeAsHHMM {
  localedaytime dup length 8 sub 5 getinterval
} bind def

% День месяца: либо "22", либо "2 ", если день <10
/funcLocalDayOfMonth {
  localedaytime 0 2 getinterval
} bind def

% Время и день месяца в формате "HH:MM/DD": 23:55/21
/funcDayTimeAndDay {
  [ //funcLocaleDayTimeAsHHMM exec (/) //funcLocalDayOfMonth exec ] //funcArrayToString exec
} bind def

% Ориентация страницы - как записано в .ps/.pdf-файле: 
/funcPageOrientation {
  mark
  statusdict /pageparams get exec
  //procClearToMarkButKeepTop exec
} bind def

% Поворачивается ли страница на 90 или 270 градусов:
/funcIsPageRotatedBy90or270 {
  % ExtraOrientation - это из настроек Page Setup в рипе.
  % (0 - 0; 1 - 270; 2 - 180; 3 - 90)
  currentpagedevice /ExtraOrientation get exec 2 mod 0 eq
  {
    false
  }
  {
    true
  } ifelse
  % а это - собственная ориентация файла: 
  //funcPageOrientation exec 2 mod 0 eq
  {
    true
  }
  {
    false
  } ifelse
  eq
} bind def

% Ширина повернутой страницы в пунктах:
/funcPageWidthInPoints {
  //funcIsPageRotatedBy90or270 exec
  {
    statusdict /pageparams get exec pop pop pop
  }
  {
    statusdict /pageparams get exec pop pop exch pop
  } ifelse
} bind def

% Высота повернутой страницы в пунктах:
/funcPageHeightInPoints {
  //funcIsPageRotatedBy90or270 exec
  {
    statusdict /pageparams get exec pop pop exch pop
  }
  {
    statusdict /pageparams get exec pop pop pop
  } ifelse
} bind def

% Ширина пленки в пунктах:
/funcMediaWidthInPoints {
  statusdict /mediawidth get exec
} bind def
 

oshch

Участник
Топикстартер
Сообщения
15
Реакции
73
smart_jobname_v.1.0 (Part 2)

Код программы. Вторая часть.

Код:
% Конструируем новое имя для задания.
% Входной параметр на вершине стека - имя файла (без пути).
% После выполнения на вершине стека будет новое имя в формате:
% "[ X копий ?! ]  <Имя задачи> ( <ширина> x <длина> мм HH:MM/DD)"
/funcConstructJobName {

  count 1 lt {
    /funcConstructJobName errordict /stackunderflow get exec
  } if
  
  % Проверяем количество копий страницы, указанное в файле:  
  statusdict /NumCopies get exec dup 1 gt
  {
    % Вставляем предупреждение перед имененем задания, если в файле указана больше, чем одна копия:
    ([ ) exch (             ) cvs //funcCombineStrings exec
    /copies //funcLocalizedLabel exec //funcCombineStrings exec  
    ( ]  ) //funcCombineStrings exec
    exch //funcCombineStrings exec
  }
  {
    pop
  } ifelse
  
  % Добавляем размеры страницы и текущее время:
  [
    ( \( )
    % ширина:
    //funcPageWidthInPoints exec 72 div 25.4 mul round cvi (             ) cvs
    ( x )
    % высота:
    //funcPageHeightInPoints exec 72 div 25.4 mul round cvi (             ) cvs
    /mm //funcLocalizedLabel exec
    % время:
    //funcDayTimeAndDay exec
    (\)) 
  ] //funcArrayToString exec
  //funcCombineStrings exec
     
  % Сравниваем размеры страницы и ширину пленки, добавляем предупреждения, если нужно: 
  //funcPageWidthInPoints exec //funcMediaWidthInPoints exec gt 
  {
    //funcPageHeightInPoints exec //funcMediaWidthInPoints exec gt
    {
      % ( не пролазит!)
      /wider_than_media //funcLocalizedLabel exec
    }
    {
      % ( поверни меня!)
      /need_rotation //funcLocalizedLabel exec
    } ifelse
  }
  {
    //funcPageHeightInPoints exec //funcPageWidthInPoints exec gt 
    //funcPageHeightInPoints exec //funcMediaWidthInPoints exec le and
    {
      % ( поверни меня!)
      /need_rotation //funcLocalizedLabel exec
    }
    {
      () % вроде все ок (пустая строка)
    } ifelse
  } ifelse
  //funcCombineStrings exec
  
} bind def

% Процедура включает чекбокс "Disable output" в окне "Output Controller/Monitor"
% в том случае, если активная очередь пуста. Это сделано для того, чтобы случайно
% не вывести на фотонаборе непроверенное задание.
% (Если же активная очередь не пуста и чекбокс снят - то это означает, 
%  что вы выводите и рипуете одновременно, поэтому вывод отключаться не будет.): 
/procDisableOutputIfActiveQueueIsEmpty {
  /HqnThroughputControl /ProcSet findresource
  begin 
    0 { pop 1 add } pgbactiveforall
    0 eq {
      (%pgb%) currentdevparams /OutputState get
      (Off) ne {
        false pgbenable
        (********** Output disabled.\n) print
      } if
    } if
  end
} bind def

% Получить полное имя файла (с путем) из объекта-файла:
% <file-stream> funcFilenameFromFile (filename)
/funcFilenameFromFile {
  4096 string statusdict /filename get exec pop
} bind def

% Стартовая процедура создания имени задания:
/procMain_SmartJobname {

  % Отключим вывод непроверенного задания:  
  //procDisableOutputIfActiveQueueIsEmpty exec

  //globaldict /pinptz_jobname known {

    % Если имя задания уже сохранено в глобальном словаре (при обработке 
    % первой сепарации задания), то сразу берем это имя:
    //globaldict /pinptz_jobname get

  }
  {
    
    1183615869 internaldict /fileObject known {
    
      % Если обрабатывается обычный файл, то берем его из внутреннего словаря: 
      1183615869 internaldict /fileObject get 

      % Получаем полное имя файла (с путем):
      //funcFilenameFromFile exec

      % Ожидаем, пока файл увеличивается в размере и пока последний байт файла равен нулю:
      dup (r) file 
      {
        2 copy exch dup
        % Проверка увеличения длины файла.
        % Примечание: собственно эта проверка не особо важна,
        % поскольку рип уже делает такую проверку для файлов из горячих папок
        % (см. Input Controller->Edit->Type=SpoolFolder->Configure->Time to wait for file to stabilize.)
        status pop pop pop exch pop % получили длину файла
        300 //procSleep exec % ждем 0.3 секунды 
        exch status pop pop pop exch pop % получили длину файла еще раз
        dup 4 1 roll % len2 file len1 len2
        eq {
          % Если длина файла не растет, то (по крайней мере, под Windows) это еще не означает, 
          % что файл уже полностью записан.
          % Поэтому здесь проверяется последний байт - для .ps и .pdf он (обычно) не равен нулю.
          dup 3 -1 roll
          1 sub setfileposition
          read
          {
            0 ne { exit } if % все хорошо, прерываем ожидание.
          }
          {
            exit % не смогли прочитать - просто выходим
          } ifelse
        }
        {
          pop pop
        } ifelse
        
        ( Waiting for file... ) ==
        2000 //procSleep exec % ждем 2 секунды
      } loop
      closefile
    
    }
    {
      % Если задание - не обычный файл, а передано через стандарный поток, возьмем его:
      serverdict /stdin get 

      % Получаем имя потока:
      //funcFilenameFromFile exec
    } ifelse 
    
    % Оставляем только имя файла без пути:
    /HqnLocal /ProcSet findresource /StripFileName_1 get exec

    % Конструируем новое имя задания:
    //funcConstructJobName exec

    % Перенесем строку с построенным именем задания в глобальную виртуальную память:
    currentglobal true setglobal exch dup length string copy exch setglobal

    % Сохраняем ссылку в глобальном словаре:
    //globaldict /pinptz_jobname 2 index put
    
  } ifelse

  % Для установки имени задания имеются jobname в statusdict и JobNameUTF8 в %pagebuffer%.
  % Но никакой разницы на ECRM RIPMate 7.2 под Windows XP, к сожалению, не видно -
  % в окне лога буквы UTF-8 отображаются неправильно во всех вариантах.
  
  % Устанавливаем наше имя задания в JobNameUTF8:   
  (%pagebuffer%) << /JobNameUTF8 3 index >> setdevparams

  % Заменяем также и имя задания в словаре statusdict:
  statusdict /jobname 3 -1 roll put
      
} bind def

<<
  % Все элементы словаря StartRender трактуются рипом как процедуры
  % и выполняются перед рипованием каждой сепарации сепарированного файла
  % или один раз для композитного. Процедуры выполняются в алфавитном порядке. 
  /StartRender <<
  
    /main_StartRender {
      
      % (\n<<<<<<< main_StartRender begin >>>>>\n) print //procPrintStack exec
    
      //procMain_SmartJobname exec
      
      % (\n<<<<<<< end main_StartRender >>>>>\n) print //procPrintStack exec
      
    } bind
    
  >>
  
%  /EndRender <<
%    /main_EndRender {
%      (\n<<<<<<< EndRender >>>>>\n) print
%    } bind
%  >>
  
%  /StartJob  <<
%    /main_StartJob {
%      (\n<<<<<<< StartJob >>>>>\n) print
%      statusdict /jobname (< StartJob >) put
%    } bind
%  >>

>> setpagedevice

end

%%EOF
 

polbol

15 лет на форуме
Сообщения
1 410
Реакции
402
Ответ: smart_jobname_v.1.0 (Part 2)

Наверное полезная штука. Но пробовать не стану, мы за порядок в названии файла... Иначе со временем и особенно Арлекином концов совсем не найдешь.
 

oshch

Участник
Топикстартер
Сообщения
15
Реакции
73
Ответ: smart_jobname_v.1.0 (Part 2)

...мы за порядок в названии файла...
Если вы про троеточия в названиях в правой части скриншота, - то они отображаются только в Output Controller когда длинное имя не влезает в колонку.
Само имя файла не обрезается - его еще можно посмотреть в свойствах по двойному клику (там поле шире, чем колонка).
А полное имя всегда можно в логе увидеть после "Job Completed: ".

Если в smart_jobname установить английский язык, то в логе не будет юникодовских крякозябр.
 

oshch

Участник
Топикстартер
Сообщения
15
Реакции
73
Хот фикс до версии 1.1

Переписывая под английский Windows, нашел ошибку в функциях четырехлетней давности,
из-за которой время и день месяца не будут отображаться, если Windows не русский
(или если в русском Windows в настройках региональных параметров изменены
форматы времени и даты).

Нужно либо заменить код с ошибками:

Код:
% Время дня в формате "HH:MM": 23:55
/funcLocaleDayTimeAsHHMM {
  localedaytime dup length 8 sub 5 getinterval
} bind def

% День месяца: либо "22", либо "2 ", если день <10
/funcLocalDayOfMonth {
  localedaytime 0 2 getinterval
} bind def

На правильный:

Код:
% Время дня в формате "HH:MM": 23:55 или 0:23
/funcLocaleDayTimeAsHHMM {
  % localedaytime % (Sat, Jul 21, 2012 1:25:09 AM) under English Windows
                  % (21 ???? 2012 ?. 1:25:09) under Russian Windows

  daytime         % (Sat Jul 21 01:25:09 2012) under English Windows
                  % (Sat Jul 21 01:25:09 2012) under Russian Windows

  dup 11 2 getinterval cvi (  ) cvs
  exch 13 3 getinterval
  //funcCombineStrings exec
} bind def

% День месяца: либо "22", либо "2", если день <10
/funcLocalDayOfMonth {
  daytime        % (Sat Jul 21 01:25:09 2012)
  8 2 getinterval cvi (  ) cvs
} bind def

либо забрать исправленный файл:

Посмотреть вложение smart_jobname_v_1_1.zip


По-видимому, тогда думал, что daytime - это в UTC/GMT,
а оказалось, что это тоже локальное время,
только в фиксированной английской форме.
 
Статус
Закрыто для дальнейших ответов.