ubuntu: เครื่องคัดลอกแผ่นซีดี

จะรีไซเคิลเครื่องเก่า มาทำเครื่องคัดลอกซีดีเพื่อถวายวัด
เครื่องใหม่ราคาประมาณหมื่นเศษ

สเปคเครื่องเก่าคือ Celeron 850MHz, RAM 128MB, HD 15G (เป็น /dev/hda)
ลงทุนซื้อใหม่คือ CD-Writer 3 ตัว ตัวละ 750 บาท
เนื่องจากจะไม่มีจอภาพ จึงจะใช้เสียงเป็นตัวแจ้งสถานะ

จะทำให้มีการทำงานคือ

  • เมื่อเปิดเครื่อง ถาด /dev/hdb จะดีดออกเพื่อรอการอ่านข้อมูล ใช้เสียงดัง 1 ปี๊บ ทุก 3 วินาที
  • เมื่อใส่แผ่นต้นฉบับ เครื่องจะตรวจสอบแผ่น ถ้าแผ่นเสียจะแจ้งเป็นเสียง 6 ปี๊บ ทุก 3 วินาที เพื่อรออ่านแผ่นใหม่
  • ถ้าแผ่นดีจะอ่านจนเสร็จ แล้วทั้งสามถาดจะถูกดีดออกเพื่อรอการเขียนข้อมูล โดยใช้เสียงดัง 2 ปี๊บ ทุก 3 วินาที
  • จะเขียนวนไปเรื่อยจนกระทั่งปิดเครื่องเขียนด้วยถาดเปล่า ไดร์ฟนั้นก็จะหยุดทำงาน
  • เมื่อหยุดทำงานครบสามไดร์ฟแล้ว เครื่องจะปิดตัวเอง
  • ในระหว่างที่ถาดถูกดีดออก ถ้าไม่มีการใส่แผ่นใหม่เข้าไป หลังจากผ่านไป 100 ปี๊ป (หรืออาจเป็นเรากดถาดเปล่าดีดกลับเข้าไป) ถาดจะปิดตัวเอง และปิดการทำงานของถาดนั้นตลอดไป

หมายเหตุ

  • เนื่องจากเป็นการทำงานแบบขนาน ทุกไดร์ฟจึงทำงานเป็นอิสระ
  • กำหนดให้ความเร็วในการเขียนเป็นแค่ 8x เพื่อให้ฮาร์ดดิสก์อ่านข้อมูลได้ทัน และเพิ่มความคงทนของข้อมูล
  • แผ่นต้นฉบับควรเป็นแผ่นที่ดี ถึงดีมาก ผลจึงจะออกมาดี

วิธีการสร้าง
เริ่มด้วย ติดตั้งอูบุนตู dapper แบบ server โดยเลือกไม่ติดตั้งอะไรเพิ่มเติมเลย
ดามด้วยเอาแพคเก็จที่จำเป็นคือ setcd สำหรับเขียนสคริปต์ และ cdrecord
$ su
# aptitude install eject setcd cdrecord

สร้างสคริปต์สำหรับให้ init เรียกใช้ตอนเปิดเครื่อง สำหรับให้อ่านแผ่นต้นฉบับ
ตั้งชื่อว่า d.inittab-cpcd
# vi d.inittab-cpcd

#!/bin/bash
# THIS IS THE COPY CD PROGRAM
# PUT THE LINE
#     D1:2345:once:/root/d.inittab-cpcd
# IN /etc/inittab THEN REBOOT 
# 

beep() {
    echo -e "\7" 
}
beeperror() {
    for i in `seq 1 6`; do beep; sleep .15; done
}
wait_read_close() {
    # MAX RETRY LOOP = 100
    for (( i=0; i<=100; i++ )) 	
    do
        if setcd -i $DEV | grep open >> /dev/null; then
            # SLEEP 1 SECONDS 
            beep; sleep 3
        else
            readcd -clone dev=$DEV f=$TMP
            return
        fi
    done
    eject -t $1 
    /sbin/shutdown -h now
    return 
}

# TEMPOLARY IMAGE FILE
DEV=/dev/hdb
#KERNEL-2.4 #ATA="ATAPI:0,1,0"
#KERNEL-2.6 #ATA=/dev/hdb
ATA=/dev/hdb
TMP=/tmp/x.bin

rm -rf $TMP

#CHECK 1ST CDR IS ORIGINAL CD THEN DUP. TO /tmp
while ! [ -s $TMP ]
do
    eject $DEV
    wait_read_close $DEV
    beep
done

# CALL MULTIPLE INSTANCE
#d.func.cpcd DEVICE SPEED ISOFILE
#KERNEL-2.4
#/root/sh-func-cpcd /dev/hdb ATAPI:0,1,0 8 $TMP &
#/root/sh-func-cpcd /dev/hdc ATAPI:1,0,0 8 $TMP &
#/root/sh-func-cpcd /dev/hdd ATAPI:1,1,0 8 $TMP &
#KERNEL-2.6
/root/d.func-cpcd /dev/hdb /dev/hdb 8 $TMP &
/root/d.func-cpcd /dev/hdc /dev/hdc 8 $TMP &
/root/d.func-cpcd /dev/hdd /dev/hdd 8 $TMP &
wait
/sbin/shutdown -h now

อีกไฟล์นึงเป็นฟังก์ชั่นสำหรับเขียนซีดี ตั้งชื่อว่า d.func-cpcd
# vi d.func-cpcd

#!/bin/bash
beep() {
    echo -e "\7"
}
beepwrite() {
    beep; sleep .15; beep
}
beeperror() {
    for i in `seq 1 6`; do beep; sleep .15; done
}
wait_write_close() {
    # MAX RETRY LOOP = 100
    for (( i=0; i<=100; i++ ))
    do
        # WAIT FOR INSERT DISC
        if setcd -i $DEV | grep 'is open' >> /dev/null; then
            beepwrite; sleep 3
        # IF NO DISC INSERTED THEN BREAK
        elif setcd -i $DEV | grep 'No disc' >> /dev/null; then
            exit 1
        else
            cdrecord -clone -raw96r dev=$ATA speed=$SPEED driveropts=burnfree gracetime=2 -overburn -eject $TMP
            # LAST CHECK WRITING
            if setcd -i $DEV | grep 'error' >> /dev/null; then
                beeperror; sleep 3
            else
                eject $DEV
                return
            fi
        fi
    done
    #END PROG
    eject -t $1
    exit 1 
}
if [ ! $1 ] && [ ! $2 ] && [ ! $3 ] && [ ! $4 ] ; then
    echo "   USAGE : $0 DRIVE ATAPI SPEED TEMP-IMG" 
    echo "   EXAM1 : $0 /dev/hdb ATAPI:0,1,0 4 /tmp/x.bin"
    exit 1
fi

DEV=$1
ATA=$2
SPEED=$3
TMP=$4

#CHECK IMAGE FILE
if ! [ -f $TMP ] ; then
	echo "  Image file $TMP does not existed"
	exit 1
fi

#COPY TO NEW BLANK CD
while [ -f $TMP ]
do
	eject $DEV
	wait_write_close $DEV
	beepwrite
done

ต่อไปแก้ไขไฟล์ /etc/inittab ให้มาเรียกใช้โปรแกรม d.inittab-cpcd ตอนเปิดเครื่อง
# vi /etc/inittab
(ไปบรรทัดล่างสุด กด G)

...
D1:2345:once:/root/d.inittab-cpcd

เสร็จแล้วก็รีบูตทดสอบได้เลยครับ

update: 49-11-25
cdrecord เติมพารามิเตอร์ gracetime=2

update: ubuntu edgy
edgy ใช้แพกเกจ upstart แทน sysvinit ทำให้บูตเร็วขึ้น
upstart ไม่ใช้ไฟล์ /etc/inittab แต่ใช้สคริปต์ใน /etc/event.d แทน
เราต้องสร้างสคริปต์ สมมุติว่าชื่อ cpcd เอาไว้ใน /etc/event.d
(สคริปต์นี้ ห้ามรันได้ คือแอตทริบิวต์ x ต้องไม่ถูกเซ็ต)
$ sudo vi /etc/event.d/cpcd

#
start on runlevel-2
start on runlevel-3
start on runlevel-4
start on runlevel-5
#
stop on shutdown
#
exec /root/d.inittab-cpcd
console output

รีบูตเครื่องก็ใช้ได้

update: 49-11-28
มีปัญหากับไดร์ฟ

  • Liteon SOHR-5239V 2$0D
  • Liteon SOHR-5239S 2$0B

ไม่สามารถอ่านดิสก์แบบ multisession ที่ถูก overburn ได้ (เช่นแผ่น VCD)
ยังแก้ไม่ตก