summaryrefslogtreecommitdiffabout
path: root/gammu/emb
Unidiff
Diffstat (limited to 'gammu/emb') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/common.pro1
-rw-r--r--gammu/emb/common/service/gsmring.c6
2 files changed, 6 insertions, 1 deletions
diff --git a/gammu/emb/common/common.pro b/gammu/emb/common/common.pro
index 9342cb7..0e719ee 100644
--- a/gammu/emb/common/common.pro
+++ b/gammu/emb/common/common.pro
@@ -1,186 +1,187 @@
1###################################################################### 1######################################################################
2# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004 2# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004
3###################################################################### 3######################################################################
4 4
5TEMPLATE = lib 5TEMPLATE = lib
6DEPENDPATH += device \ 6DEPENDPATH += device \
7 misc \ 7 misc \
8 phone \ 8 phone \
9 protocol \ 9 protocol \
10 service \ 10 service \
11 device/bluetoth \ 11 device/bluetoth \
12 device/irda \ 12 device/irda \
13 device/serial \ 13 device/serial \
14 misc/coding \ 14 misc/coding \
15 phone/alcatel \ 15 phone/alcatel \
16 phone/at \ 16 phone/at \
17 phone/nokia \ 17 phone/nokia \
18 phone/obex \ 18 phone/obex \
19 phone/symbian \ 19 phone/symbian \
20 protocol/alcatel \ 20 protocol/alcatel \
21 protocol/at \ 21 protocol/at \
22 protocol/nokia \ 22 protocol/nokia \
23 protocol/obex \ 23 protocol/obex \
24 protocol/symbian \ 24 protocol/symbian \
25 service/backup \ 25 service/backup \
26 service/sms \ 26 service/sms \
27 phone/nokia/dct3 \ 27 phone/nokia/dct3 \
28 phone/nokia/dct4 28 phone/nokia/dct4
29INCLUDEPATH += . \ 29INCLUDEPATH += . \
30 misc/coding \ 30 misc/coding \
31 misc \ 31 misc \
32 device \ 32 device \
33 phone/nokia/dct4 \ 33 phone/nokia/dct4 \
34 phone/nokia/dct3 \ 34 phone/nokia/dct3 \
35 phone/at \ 35 phone/at \
36 phone/alcatel \ 36 phone/alcatel \
37 phone/obex \ 37 phone/obex \
38 phone/symbian \ 38 phone/symbian \
39 protocol \ 39 protocol \
40 protocol/nokia \ 40 protocol/nokia \
41 protocol/at \ 41 protocol/at \
42 protocol/alcatel \ 42 protocol/alcatel \
43 protocol/obex \ 43 protocol/obex \
44 protocol/symbian \ 44 protocol/symbian \
45 device/serial \ 45 device/serial \
46 device/irda \ 46 device/irda \
47 device/bluetoth \ 47 device/bluetoth \
48 service \ 48 service \
49 service/sms \ 49 service/sms \
50 service/backup \ 50 service/backup \
51 phone/nokia \ 51 phone/nokia \
52 phone 52 phone
53 53
54# Input 54# Input
55HEADERS += config.h \ 55HEADERS += config.h \
56 gammu.h \ 56 gammu.h \
57 gsmcomon.h \ 57 gsmcomon.h \
58 gsmstate.h \ 58 gsmstate.h \
59 device/devfunc.h \ 59 device/devfunc.h \
60 misc/cfg.h \ 60 misc/cfg.h \
61 misc/misc.h \ 61 misc/misc.h \
62 phone/pfunc.h \ 62 phone/pfunc.h \
63 protocol/protocol.h \ 63 protocol/protocol.h \
64 service/gsmcal.h \ 64 service/gsmcal.h \
65 service/gsmcall.h \ 65 service/gsmcall.h \
66 service/gsmdata.h \ 66 service/gsmdata.h \
67 service/gsmlogo.h \ 67 service/gsmlogo.h \
68 service/gsmmisc.h \ 68 service/gsmmisc.h \
69 service/gsmnet.h \ 69 service/gsmnet.h \
70 service/gsmpbk.h \ 70 service/gsmpbk.h \
71 service/gsmprof.h \ 71 service/gsmprof.h \
72 service/gsmring.h \ 72 service/gsmring.h \
73 device/bluetoth/affix.h \ 73 device/bluetoth/affix.h \
74 device/bluetoth/blue_w32.h \ 74 device/bluetoth/blue_w32.h \
75 device/bluetoth/bluetoth.h \ 75 device/bluetoth/bluetoth.h \
76 device/bluetoth/bluez.h \ 76 device/bluetoth/bluez.h \
77 device/irda/irda.h \ 77 device/irda/irda.h \
78 device/irda/irda_unx.h \ 78 device/irda/irda_unx.h \
79 device/irda/irda_w32.h \ 79 device/irda/irda_w32.h \
80 device/serial/ser_djg.h \ 80 device/serial/ser_djg.h \
81 device/serial/ser_unx.h \ 81 device/serial/ser_unx.h \
82 device/serial/ser_w32.h \ 82 device/serial/ser_w32.h \
83 misc/coding/coding.h \ 83 misc/coding/coding.h \
84 misc/coding/md5.h \ 84 misc/coding/md5.h \
85 phone/alcatel/alcatel.h \ 85 phone/alcatel/alcatel.h \
86 phone/at/atgen.h \ 86 phone/at/atgen.h \
87 phone/nokia/ncommon.h \ 87 phone/nokia/ncommon.h \
88 phone/nokia/nfunc.h \ 88 phone/nokia/nfunc.h \
89 phone/nokia/nfuncold.h \ 89 phone/nokia/nfuncold.h \
90 phone/obex/obexgen.h \ 90 phone/obex/obexgen.h \
91 phone/symbian/mroutgen.h \ 91 phone/symbian/mroutgen.h \
92 protocol/alcatel/alcabus.h \ 92 protocol/alcatel/alcabus.h \
93 protocol/at/at.h \ 93 protocol/at/at.h \
94 protocol/nokia/fbus2.h \ 94 protocol/nokia/fbus2.h \
95 protocol/nokia/mbus2.h \ 95 protocol/nokia/mbus2.h \
96 protocol/nokia/phonet.h \ 96 protocol/nokia/phonet.h \
97 protocol/obex/obex.h \ 97 protocol/obex/obex.h \
98 protocol/symbian/mrouter.h \ 98 protocol/symbian/mrouter.h \
99 service/backup/backgen.h \ 99 service/backup/backgen.h \
100 service/backup/backics.h \ 100 service/backup/backics.h \
101 service/backup/backldif.h \ 101 service/backup/backldif.h \
102 service/backup/backlmb.h \ 102 service/backup/backlmb.h \
103 service/backup/backtext.h \ 103 service/backup/backtext.h \
104 service/backup/backvcf.h \ 104 service/backup/backvcf.h \
105 service/backup/backvcs.h \ 105 service/backup/backvcs.h \
106 service/backup/gsmback.h \ 106 service/backup/gsmback.h \
107 service/sms/gsmems.h \ 107 service/sms/gsmems.h \
108 service/sms/gsmmulti.h \ 108 service/sms/gsmmulti.h \
109 service/sms/gsmsms.h \ 109 service/sms/gsmsms.h \
110 phone/nokia/dct3/dct3comm.h \ 110 phone/nokia/dct3/dct3comm.h \
111 phone/nokia/dct3/dct3func.h \ 111 phone/nokia/dct3/dct3func.h \
112 phone/nokia/dct3/n6110.h \ 112 phone/nokia/dct3/n6110.h \
113 phone/nokia/dct3/n7110.h \ 113 phone/nokia/dct3/n7110.h \
114 phone/nokia/dct3/n9210.h \ 114 phone/nokia/dct3/n9210.h \
115 phone/nokia/dct4/dct4func.h \ 115 phone/nokia/dct4/dct4func.h \
116 phone/nokia/dct4/n3320.h \ 116 phone/nokia/dct4/n3320.h \
117 phone/nokia/dct4/n3650.h \ 117 phone/nokia/dct4/n3650.h \
118 phone/nokia/dct4/n6510.h 118 phone/nokia/dct4/n6510.h
119SOURCES +=gsmcomon.c \ 119SOURCES +=gsmcomon.c \
120gsmstate.c \ 120gsmstate.c \
121misc/misc.c \ 121misc/misc.c \
122misc/cfg.c \ 122misc/cfg.c \
123misc/coding/coding.c \ 123misc/coding/coding.c \
124misc/coding/md5.c \ 124misc/coding/md5.c \
125service/sms/gsmsms.c \ 125service/sms/gsmsms.c \
126service/sms/gsmems.c \ 126service/sms/gsmems.c \
127service/sms/gsmmulti.c \ 127service/sms/gsmmulti.c \
128service/gsmcal.c \ 128service/gsmcal.c \
129service/gsmdata.c \ 129service/gsmdata.c \
130service/gsmpbk.c \ 130service/gsmpbk.c \
131service/gsmring.c \ 131service/gsmring.c \
132service/gsmlogo.c \ 132service/gsmlogo.c \
133service/gsmmisc.c \ 133service/gsmmisc.c \
134service/gsmnet.c \ 134service/gsmnet.c \
135service/backup/gsmback.c \ 135service/backup/gsmback.c \
136service/backup/backldif.c \ 136service/backup/backldif.c \
137service/backup/backlmb.c \ 137service/backup/backlmb.c \
138service/backup/backtext.c \ 138service/backup/backtext.c \
139service/backup/backvcs.c \ 139service/backup/backvcs.c \
140service/backup/backvcf.c \ 140service/backup/backvcf.c \
141service/backup/backics.c \ 141service/backup/backics.c \
142device/bluetoth/affix.c \ 142device/bluetoth/affix.c \
143device/bluetoth/bluez.c \ 143device/bluetoth/bluez.c \
144device/bluetoth/blue_w32.c \ 144device/bluetoth/blue_w32.c \
145device/bluetoth/bluetoth.c \ 145device/bluetoth/bluetoth.c \
146device/serial/ser_djg.c \ 146device/serial/ser_djg.c \
147device/irda/irda.c \ 147device/irda/irda.c \
148device/devfunc.c \ 148device/devfunc.c \
149protocol/at/at.c \ 149protocol/at/at.c \
150protocol/alcatel/alcabus.c \ 150protocol/alcatel/alcabus.c \
151protocol/nokia/mbus2.c \ 151protocol/nokia/mbus2.c \
152protocol/nokia/fbus2.c \ 152protocol/nokia/fbus2.c \
153protocol/nokia/phonet.c \ 153protocol/nokia/phonet.c \
154protocol/obex/obex.c \ 154protocol/obex/obex.c \
155protocol/symbian/mrouter.c \ 155protocol/symbian/mrouter.c \
156phone/pfunc.c \ 156phone/pfunc.c \
157phone/at/atgen.c \ 157phone/at/atgen.c \
158phone/at/siemens.c \ 158phone/at/siemens.c \
159phone/at/sonyeric.c \ 159phone/at/sonyeric.c \
160phone/alcatel/alcatel.c \ 160phone/alcatel/alcatel.c \
161phone/nokia/dct3/n6110.c \ 161phone/nokia/dct3/n6110.c \
162phone/nokia/dct3/n7110.c \ 162phone/nokia/dct3/n7110.c \
163phone/nokia/dct3/n9210.c \ 163phone/nokia/dct3/n9210.c \
164phone/nokia/dct3/dct3func.c \ 164phone/nokia/dct3/dct3func.c \
165phone/nokia/dct4/n3320.c \ 165phone/nokia/dct4/n3320.c \
166phone/nokia/dct4/n3650.c \ 166phone/nokia/dct4/n3650.c \
167phone/nokia/dct4/n6510.c \ 167phone/nokia/dct4/n6510.c \
168phone/nokia/dct4/dct4func.c \ 168phone/nokia/dct4/dct4func.c \
169phone/nokia/nauto.c \ 169phone/nokia/nauto.c \
170phone/nokia/nfunc.c \ 170phone/nokia/nfunc.c \
171phone/nokia/nfuncold.c \ 171phone/nokia/nfuncold.c \
172phone/obex/obexgen.c \ 172phone/obex/obexgen.c \
173phone/symbian/mroutgen.c 173phone/symbian/mroutgen.c
174 174
175DEFINES += DESKTOP_VERSION
175TARGET = microgammu 176TARGET = microgammu
176CONFIG = warn_off release console 177CONFIG = warn_off release console
177DESTDIR = ../../../bin 178DESTDIR = ../../../bin
178OBJECTS_DIR = obj/unix 179OBJECTS_DIR = obj/unix
179MOC_DIR = moc/unix 180MOC_DIR = moc/unix
180 181
181unix: { 182unix: {
182SOURCES += device/serial/ser_unx.c 183SOURCES += device/serial/ser_unx.c
183} 184}
184win32:{ 185win32:{
185SOURCES += device/serial/ser_w32.c 186SOURCES += device/serial/ser_w32.c
186} 187}
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
index f7f7082..7df46f1 100644
--- a/gammu/emb/common/service/gsmring.c
+++ b/gammu/emb/common/service/gsmring.c
@@ -1,1132 +1,1136 @@
1/* (c) 2001-2004 by Marcin Wiacek */ 1/* (c) 2001-2004 by Marcin Wiacek */
2/* Based on some work from Ralf Thelen (7110 ringtones), 2/* Based on some work from Ralf Thelen (7110 ringtones),
3 * Gnokii (RTTL and SM) and others 3 * Gnokii (RTTL and SM) and others
4 */ 4 */
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h> 7#include <string.h>
8#include <ctype.h> 8#include <ctype.h>
9#include <math.h> 9#include <math.h>
10#ifdef WIN32 10#ifdef WIN32
11# include <windows.h> 11# include <windows.h>
12#endif 12#endif
13 13
14#include "../gsmcomon.h" 14#include "../gsmcomon.h"
15#include "../misc/coding/coding.h" 15#include "../misc/coding/coding.h"
16#include "../gsmstate.h" 16#include "../gsmstate.h"
17#include "gsmring.h" 17#include "gsmring.h"
18#include "sms/gsmsms.h" 18#include "sms/gsmsms.h"
19 19
20int GSM_RingNoteGetFrequency(GSM_RingNote Note) 20int GSM_RingNoteGetFrequency(GSM_RingNote Note)
21{ 21{
22 double freq=0; 22 double freq=0;
23 23
24 /* Values according to the software from http://iki.fi/too/sw/xring/ 24 /* Values according to the software from http://iki.fi/too/sw/xring/
25 * generated with: 25 * generated with:
26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)' 26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
27 */ 27 */
28 switch (Note.Note) { 28 switch (Note.Note) {
29 case Note_C : freq = 523.3; break; 29 case Note_C : freq = 523.3; break;
30 case Note_Cis: freq = 554.4; break; 30 case Note_Cis: freq = 554.4; break;
31 case Note_D : freq = 587.3; break; 31 case Note_D : freq = 587.3; break;
32 case Note_Dis: freq = 622.3; break; 32 case Note_Dis: freq = 622.3; break;
33 case Note_E : freq = 659.3; break; 33 case Note_E : freq = 659.3; break;
34 case Note_F : freq = 698.5; break; 34 case Note_F : freq = 698.5; break;
35 case Note_Fis: freq = 740; break; 35 case Note_Fis: freq = 740; break;
36 case Note_G : freq = 784; break; 36 case Note_G : freq = 784; break;
37 case Note_Gis: freq = 830.6; break; 37 case Note_Gis: freq = 830.6; break;
38 case Note_A : freq = 880; break; 38 case Note_A : freq = 880; break;
39 case Note_Ais: freq = 932.3; break; 39 case Note_Ais: freq = 932.3; break;
40 case Note_H : freq = 987.8; break; 40 case Note_H : freq = 987.8; break;
41 case Note_Pause: break; 41 case Note_Pause: break;
42 } 42 }
43 switch (Note.Scale) { 43 switch (Note.Scale) {
44 case Scale_440 : freq = freq / 2; break; 44 case Scale_440 : freq = freq / 2; break;
45 case Scale_880 : break; 45 case Scale_880 : break;
46 case Scale_1760: freq = freq * 2; break; 46 case Scale_1760: freq = freq * 2; break;
47 case Scale_3520: freq = freq * 4; break; 47 case Scale_3520: freq = freq * 4; break;
48 default : break; 48 default : break;
49 } 49 }
50 return (int)freq; 50 return (int)freq;
51} 51}
52 52
53int GSM_RingNoteGetFullDuration(GSM_RingNote Note) 53int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
54{ 54{
55 int duration = 1; 55 int duration = 1;
56 56
57 switch (Note.Duration) { 57 switch (Note.Duration) {
58 case Duration_Full : duration = 128; break; 58 case Duration_Full : duration = 128; break;
59 case Duration_1_2 : duration = 64; break; 59 case Duration_1_2 : duration = 64; break;
60 case Duration_1_4 : duration = 32; break; 60 case Duration_1_4 : duration = 32; break;
61 case Duration_1_8 : duration = 16; break; 61 case Duration_1_8 : duration = 16; break;
62 case Duration_1_16 : duration = 8; break; 62 case Duration_1_16 : duration = 8; break;
63 case Duration_1_32 : duration = 4; break; 63 case Duration_1_32 : duration = 4; break;
64 } 64 }
65 switch (Note.DurationSpec) { 65 switch (Note.DurationSpec) {
66 case NoSpecialDuration : break; 66 case NoSpecialDuration : break;
67 case DottedNote : duration = duration * 3/2;break; 67 case DottedNote : duration = duration * 3/2;break;
68 case DoubleDottedNote : duration = duration * 9/4;break; 68 case DoubleDottedNote : duration = duration * 9/4;break;
69 case Length_2_3 : duration = duration * 2/3;break; 69 case Length_2_3 : duration = duration * 2/3;break;
70 } 70 }
71 return duration; 71 return duration;
72} 72}
73 73
74#ifndef PI 74#ifndef PI
75# define PI 3.141592654 75# define PI 3.141592654
76#endif 76#endif
77 77
78#define WAV_SAMPLE_RATE 44100 78#define WAV_SAMPLE_RATE 44100
79 79
80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone) 80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
81{ 81{
82 unsigned char WAV_Header[] = { 82 unsigned char WAV_Header[] = {
83 'R','I','F','F', 83 'R','I','F','F',
84 0x00,0x00,0x00,0x00,/* Length */ 84 0x00,0x00,0x00,0x00,/* Length */
85 'W','A','V','E'}; 85 'W','A','V','E'};
86 unsigned char FMT_Header[] = {'f','m','t',' ', 86 unsigned char FMT_Header[] = {'f','m','t',' ',
87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac, 87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00}; 88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
89 unsigned char DATA_Header[] = { 89 unsigned char DATA_Header[] = {
90 'd','a','t','a', 90 'd','a','t','a',
91 0x00,0x00,0x00,0x00};/* Length */ 91 0x00,0x00,0x00,0x00};/* Length */
92 short DATA_Buffer[60000]; 92 short DATA_Buffer[60000];
93 long wavfilesize; 93 long wavfilesize;
94 GSM_RingNote *Note; 94 GSM_RingNote *Note;
95 long i,j,length=0; 95 long i,j,length=0;
96 double phase=0,phase_step; 96 double phase=0,phase_step;
97 97
98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); 98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); 99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); 100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
101 101
102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
104 Note = &ringtone->NoteTone.Commands[i].Note; 104 Note = &ringtone->NoteTone.Commands[i].Note;
105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5; 105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5;
106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) { 106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) {
107 /*DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));*/ 107#ifdef DESKTOP_VERSION
108 DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));
109#else
110 // we have no sin on Zaurus
108 DATA_Buffer[j] = ((int)(0.5*50000)); 111 DATA_Buffer[j] = ((int)(0.5*50000));
112#endif
109 phase = phase + phase_step; 113 phase = phase + phase_step;
110 length++; 114 length++;
111 } 115 }
112 fwrite(&DATA_Buffer,sizeof(short),j,file); 116 fwrite(&DATA_Buffer,sizeof(short),j,file);
113 } 117 }
114 } 118 }
115 119
116 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2; 120 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
117 WAV_Header[4] = ((unsigned char)wavfilesize % 256); 121 WAV_Header[4] = ((unsigned char)wavfilesize % 256);
118 WAV_Header[5] = ((unsigned char)wavfilesize / 256); 122 WAV_Header[5] = ((unsigned char)wavfilesize / 256);
119 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256)); 123 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
120 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); 124 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
121 wavfilesize = wavfilesize - 54; 125 wavfilesize = wavfilesize - 54;
122 DATA_Header[4] = ((unsigned char)wavfilesize % 256); 126 DATA_Header[4] = ((unsigned char)wavfilesize % 256);
123 DATA_Header[5] = ((unsigned char)wavfilesize / 256); 127 DATA_Header[5] = ((unsigned char)wavfilesize / 256);
124 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256)); 128 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
125 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); 129 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
126 130
127 fseek( file, 0, SEEK_SET); 131 fseek( file, 0, SEEK_SET);
128 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); 132 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
129 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); 133 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
130 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); 134 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
131 135
132 return ERR_NONE; 136 return ERR_NONE;
133} 137}
134 138
135static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone) 139static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
136{ 140{
137 char nullchar=0x00; 141 char nullchar=0x00;
138 142
139 fwrite(&nullchar,1,1,file); 143 fwrite(&nullchar,1,1,file);
140 fwrite(&nullchar,1,1,file); 144 fwrite(&nullchar,1,1,file);
141 fprintf(file,"\x0C\x01\x2C"); 145 fprintf(file,"\x0C\x01\x2C");
142 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name)); 146 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
143 fwrite(&nullchar,1,1,file); 147 fwrite(&nullchar,1,1,file);
144 fwrite(&nullchar,1,1,file); 148 fwrite(&nullchar,1,1,file);
145 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); 149 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
146 return ERR_NONE; 150 return ERR_NONE;
147} 151}
148 152
149static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone) 153static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
150{ 154{
151 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); 155 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
152 return ERR_NONE; 156 return ERR_NONE;
153} 157}
154 158
155GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone) 159GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
156{ 160{
157 GSM_RingNoteScaleDefNoteScale; 161 GSM_RingNoteScaleDefNoteScale;
158 GSM_RingNoteDurationDefNoteDuration; 162 GSM_RingNoteDurationDefNoteDuration;
159 163
160 GSM_RingNoteStyleDefNoteStyle=0; 164 GSM_RingNoteStyleDefNoteStyle=0;
161 int DefNoteTempo=0; 165 int DefNoteTempo=0;
162 166
163 bool started = false, firstcomma = true; 167 bool started = false, firstcomma = true;
164 GSM_RingNote *Note; 168 GSM_RingNote *Note;
165 169
166 unsigned char buffer[15]; 170 unsigned char buffer[15];
167 int i,j,k=0; 171 int i,j,k=0;
168 172
169 /* Saves ringtone name */ 173 /* Saves ringtone name */
170 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name)); 174 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
171 175
172 /* Find the most frequently used duration */ 176 /* Find the most frequently used duration */
173 for (i=0;i<6;i++) buffer[i]=0; 177 for (i=0;i<6;i++) buffer[i]=0;
174 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 178 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
175 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 179 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
176 Note = &ringtone->NoteTone.Commands[i].Note; 180 Note = &ringtone->NoteTone.Commands[i].Note;
177 /* some durations need 2 bytes in file, some 1 */ 181 /* some durations need 2 bytes in file, some 1 */
178 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) { 182 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
179 buffer[Note->Duration/32]++; 183 buffer[Note->Duration/32]++;
180 } 184 }
181 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) { 185 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
182 buffer[Note->Duration/32]+=2; 186 buffer[Note->Duration/32]+=2;
183 } 187 }
184 } 188 }
185 } 189 }
186 /* Now find the most frequently used */ 190 /* Now find the most frequently used */
187 j=0; 191 j=0;
188 for (i=0;i<6;i++) { 192 for (i=0;i<6;i++) {
189 if (buffer[i]>j) { 193 if (buffer[i]>j) {
190 k=i; 194 k=i;
191 j=buffer[i]; 195 j=buffer[i];
192 } 196 }
193 } 197 }
194 /* Finally convert the default duration */ 198 /* Finally convert the default duration */
195 DefNoteDuration = k * 32; 199 DefNoteDuration = k * 32;
196 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); 200 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
197 switch (DefNoteDuration) { 201 switch (DefNoteDuration) {
198 case Duration_Full:fprintf(file,"d=1"); break; 202 case Duration_Full:fprintf(file,"d=1"); break;
199 case Duration_1_2 :fprintf(file,"d=2"); break; 203 case Duration_1_2 :fprintf(file,"d=2"); break;
200 case Duration_1_4 :fprintf(file,"d=4"); break; 204 case Duration_1_4 :fprintf(file,"d=4"); break;
201 case Duration_1_8 :fprintf(file,"d=8"); break; 205 case Duration_1_8 :fprintf(file,"d=8"); break;
202 case Duration_1_16:fprintf(file,"d=16");break; 206 case Duration_1_16:fprintf(file,"d=16");break;
203 case Duration_1_32:fprintf(file,"d=32");break; 207 case Duration_1_32:fprintf(file,"d=32");break;
204 } 208 }
205 209
206 /* Find the most frequently used scale */ 210 /* Find the most frequently used scale */
207 for (i=0;i<9;i++) buffer[i]=0; 211 for (i=0;i<9;i++) buffer[i]=0;
208 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 212 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
209 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 213 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
210 Note = &ringtone->NoteTone.Commands[i].Note; 214 Note = &ringtone->NoteTone.Commands[i].Note;
211 if (Note->Note!=Note_Pause && 215 if (Note->Note!=Note_Pause &&
212 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) { 216 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
213 buffer[Note->Scale - 1]++; 217 buffer[Note->Scale - 1]++;
214 } 218 }
215 } 219 }
216 } 220 }
217 j=0; 221 j=0;
218 for (i=0;i<9;i++) { 222 for (i=0;i<9;i++) {
219 if (buffer[i]>j) { 223 if (buffer[i]>j) {
220 k = i; 224 k = i;
221 j=buffer[i]; 225 j=buffer[i];
222 } 226 }
223 } 227 }
224 DefNoteScale = k + 1; 228 DefNoteScale = k + 1;
225 /* Save the default scale */ 229 /* Save the default scale */
226 fprintf(file,",o=%i,",DefNoteScale); 230 fprintf(file,",o=%i,",DefNoteScale);
227 dbgprintf("DefNoteScale=%d\n", DefNoteScale); 231 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
228 232
229 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 233 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
230 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue; 234 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
231 235
232 Note = &ringtone->NoteTone.Commands[i].Note; 236 Note = &ringtone->NoteTone.Commands[i].Note;
233 237
234 /* Trick from PPM Edit */ 238 /* Trick from PPM Edit */
235 if (Note->DurationSpec == DoubleDottedNote) { 239 if (Note->DurationSpec == DoubleDottedNote) {
236 switch (Note->Duration) { 240 switch (Note->Duration) {
237 case Duration_Full:Note->Duration = Duration_Full;break; 241 case Duration_Full:Note->Duration = Duration_Full;break;
238 case Duration_1_2 :Note->Duration = Duration_Full;break; 242 case Duration_1_2 :Note->Duration = Duration_Full;break;
239 case Duration_1_4 :Note->Duration = Duration_1_2; break; 243 case Duration_1_4 :Note->Duration = Duration_1_2; break;
240 case Duration_1_8 :Note->Duration = Duration_1_4; break; 244 case Duration_1_8 :Note->Duration = Duration_1_4; break;
241 case Duration_1_16:Note->Duration = Duration_1_8; break; 245 case Duration_1_16:Note->Duration = Duration_1_8; break;
242 case Duration_1_32:Note->Duration = Duration_1_16;break; 246 case Duration_1_32:Note->Duration = Duration_1_16;break;
243 } 247 }
244 Note->DurationSpec = NoSpecialDuration; 248 Note->DurationSpec = NoSpecialDuration;
245 } 249 }
246 250
247 if (!started) { 251 if (!started) {
248 DefNoteTempo=Note->Tempo; 252 DefNoteTempo=Note->Tempo;
249 DefNoteStyle=Note->Style; 253 DefNoteStyle=Note->Style;
250 switch (Note->Style) { 254 switch (Note->Style) {
251 case StaccatoStyle: fprintf(file,"s=S,"); break; 255 case StaccatoStyle: fprintf(file,"s=S,"); break;
252 case NaturalStyle : fprintf(file,"s=N,"); break; 256 case NaturalStyle : fprintf(file,"s=N,"); break;
253 case ContinuousStyle : break; 257 case ContinuousStyle : break;
254 } 258 }
255 /* Save the default tempo */ 259 /* Save the default tempo */
256 fprintf(file,"b=%i:",DefNoteTempo); 260 fprintf(file,"b=%i:",DefNoteTempo);
257 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo); 261 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo);
258 started = true; 262 started = true;
259 firstcomma = true; 263 firstcomma = true;
260 } 264 }
261 265
262 if (!started) continue; 266 if (!started) continue;
263 267
264 if (Note->Style!=DefNoteStyle) { 268 if (Note->Style!=DefNoteStyle) {
265 /* And a separator */ 269 /* And a separator */
266 if (!firstcomma) fprintf(file,","); 270 if (!firstcomma) fprintf(file,",");
267 firstcomma = false; 271 firstcomma = false;
268 DefNoteStyle=Note->Style; 272 DefNoteStyle=Note->Style;
269 switch (Note->Style) { 273 switch (Note->Style) {
270 case StaccatoStyle : fprintf(file,"s=S"); break; 274 case StaccatoStyle : fprintf(file,"s=S"); break;
271 case NaturalStyle : fprintf(file,"s=N"); break; 275 case NaturalStyle : fprintf(file,"s=N"); break;
272 case ContinuousStyle: fprintf(file,"s=C"); break; 276 case ContinuousStyle: fprintf(file,"s=C"); break;
273 } 277 }
274 } 278 }
275 if (Note->Tempo!=DefNoteTempo) { 279 if (Note->Tempo!=DefNoteTempo) {
276 /* And a separator */ 280 /* And a separator */
277 if (!firstcomma) fprintf(file,","); 281 if (!firstcomma) fprintf(file,",");
278 firstcomma = false; 282 firstcomma = false;
279 DefNoteTempo=Note->Tempo; 283 DefNoteTempo=Note->Tempo;
280 fprintf(file,"b=%i",DefNoteTempo); 284 fprintf(file,"b=%i",DefNoteTempo);
281 } 285 }
282 /* This note has a duration different than the default. We must save it */ 286 /* This note has a duration different than the default. We must save it */
283 if (Note->Duration!=DefNoteDuration) { 287 if (Note->Duration!=DefNoteDuration) {
284 /* And a separator */ 288 /* And a separator */
285 if (!firstcomma) fprintf(file,","); 289 if (!firstcomma) fprintf(file,",");
286 firstcomma = false; 290 firstcomma = false;
287 switch (Note->Duration) { 291 switch (Note->Duration) {
288 case Duration_Full:fprintf(file,"1"); break; 292 case Duration_Full:fprintf(file,"1"); break;
289 case Duration_1_2 :fprintf(file,"2"); break; 293 case Duration_1_2 :fprintf(file,"2"); break;
290 case Duration_1_4 :fprintf(file,"4"); break; 294 case Duration_1_4 :fprintf(file,"4"); break;
291 case Duration_1_8 :fprintf(file,"8"); break; 295 case Duration_1_8 :fprintf(file,"8"); break;
292 case Duration_1_16:fprintf(file,"16");break; 296 case Duration_1_16:fprintf(file,"16");break;
293 case Duration_1_32:fprintf(file,"32");break; 297 case Duration_1_32:fprintf(file,"32");break;
294 } 298 }
295 } else { 299 } else {
296 /* And a separator */ 300 /* And a separator */
297 if (!firstcomma) fprintf(file,","); 301 if (!firstcomma) fprintf(file,",");
298 firstcomma = false; 302 firstcomma = false;
299 } 303 }
300 /* Now save the actual note */ 304 /* Now save the actual note */
301 switch (Note->Note) { 305 switch (Note->Note) {
302 case Note_C :fprintf(file,"c");break; 306 case Note_C :fprintf(file,"c");break;
303 case Note_Cis:fprintf(file,"c#");break; 307 case Note_Cis:fprintf(file,"c#");break;
304 case Note_D :fprintf(file,"d");break; 308 case Note_D :fprintf(file,"d");break;
305 case Note_Dis:fprintf(file,"d#");break; 309 case Note_Dis:fprintf(file,"d#");break;
306 case Note_E :fprintf(file,"e");break; 310 case Note_E :fprintf(file,"e");break;
307 case Note_F :fprintf(file,"f");break; 311 case Note_F :fprintf(file,"f");break;
308 case Note_Fis:fprintf(file,"f#");break; 312 case Note_Fis:fprintf(file,"f#");break;
309 case Note_G :fprintf(file,"g");break; 313 case Note_G :fprintf(file,"g");break;
310 case Note_Gis:fprintf(file,"g#");break; 314 case Note_Gis:fprintf(file,"g#");break;
311 case Note_A :fprintf(file,"a");break; 315 case Note_A :fprintf(file,"a");break;
312 case Note_Ais:fprintf(file,"a#");break; 316 case Note_Ais:fprintf(file,"a#");break;
313 case Note_H :fprintf(file,"h");break; 317 case Note_H :fprintf(file,"h");break;
314 default :fprintf(file,"p");break; /*Pause ?*/ 318 default :fprintf(file,"p");break; /*Pause ?*/
315 } 319 }
316 switch (Note->DurationSpec) { 320 switch (Note->DurationSpec) {
317 case DottedNote : fprintf(file,".");break; 321 case DottedNote : fprintf(file,".");break;
318 default : break; 322 default : break;
319 } 323 }
320 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { 324 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
321 fprintf(file,"%i",Note->Scale); 325 fprintf(file,"%i",Note->Scale);
322 } 326 }
323 } 327 }
324 return ERR_NONE; 328 return ERR_NONE;
325} 329}
326 330
327void saveimelody(FILE *file, GSM_Ringtone *ringtone) 331void saveimelody(FILE *file, GSM_Ringtone *ringtone)
328{ 332{
329 char Buffer[2000]; 333 char Buffer[2000];
330 int i=2000; 334 int i=2000;
331 335
332 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true); 336 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true);
333 337
334 fwrite(Buffer, 1, i, file); 338 fwrite(Buffer, 1, i, file);
335} 339}
336 340
337#ifndef ENABLE_LGPL 341#ifndef ENABLE_LGPL
338 342
339static void WriteVarLen(unsigned char* midifile, int* current, long value) 343static void WriteVarLen(unsigned char* midifile, int* current, long value)
340{ 344{
341 long buffer; 345 long buffer;
342 346
343 buffer = value & 0x7f; 347 buffer = value & 0x7f;
344 348
345 while (value >>= 7) { 349 while (value >>= 7) {
346 buffer <<= 8; 350 buffer <<= 8;
347 buffer |= 0x80; 351 buffer |= 0x80;
348 buffer += (value & 0x7f); 352 buffer += (value & 0x7f);
349 } 353 }
350 354
351 while (1) { 355 while (1) {
352 midifile[(*current)++] = (unsigned char)buffer; 356 midifile[(*current)++] = (unsigned char)buffer;
353 if (buffer & 0x80) { 357 if (buffer & 0x80) {
354 buffer >>= 8; 358 buffer >>= 8;
355 } else { 359 } else {
356 break; 360 break;
357 } 361 }
358 } 362 }
359} 363}
360 364
361#define singlepauses 365#define singlepauses
362 366
363/* FIXME: need adding tempo before each note and scale too ? */ 367/* FIXME: need adding tempo before each note and scale too ? */
364void savemid(FILE* file, GSM_Ringtone *ringtone) 368void savemid(FILE* file, GSM_Ringtone *ringtone)
365{ 369{
366 int pause = 0, current = 26, duration, i, note=0, length = 20; 370 int pause = 0, current = 26, duration, i, note=0, length = 20;
367 bool started = false; 371 bool started = false;
368 GSM_RingNote *Note; 372 GSM_RingNote *Note;
369 unsigned char midifile[3000] = { 373 unsigned char midifile[3000] = {
370 0x4D, 0x54, 0x68, 0x64, // MThd 374 0x4D, 0x54, 0x68, 0x64, // MThd
371 0x00, 0x00, 0x00, 0x06, // chunk length 375 0x00, 0x00, 0x00, 0x06, // chunk length
372 0x00, 0x00, // format 0 376 0x00, 0x00, // format 0
373 0x00, 0x01, // one track 377 0x00, 0x01, // one track
374 0x00, 0x20, // 32 per quarter note 378 0x00, 0x20, // 32 per quarter note
375 0x4D, 0x54, 0x72, 0x6B, // MTrk 379 0x4D, 0x54, 0x72, 0x6B, // MTrk
376 0x00, 0x00, 0x00, 0x00, // chunk length 380 0x00, 0x00, 0x00, 0x00, // chunk length
377 0x00, 0xFF, 0x51, 0x03, // tempo meta event 381 0x00, 0xFF, 0x51, 0x03, // tempo meta event
378 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note 382 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note
379 383
380 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) { 384 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
381 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 385 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
382 Note = &ringtone->NoteTone.Commands[i].Note; 386 Note = &ringtone->NoteTone.Commands[i].Note;
383 if (!started) { 387 if (!started) {
384 /* readmid does not read pauses at the beginning */ 388 /* readmid does not read pauses at the beginning */
385 if (Note->Note != Note_Pause) { 389 if (Note->Note != Note_Pause) {
386 /* FIXME: we need add tempo before each note or so... */ 390 /* FIXME: we need add tempo before each note or so... */
387 long duration=60000000/Note->Tempo; 391 long duration=60000000/Note->Tempo;
388 392
389 midifile[current++] = (unsigned char)(duration >> 16); 393 midifile[current++] = (unsigned char)(duration >> 16);
390 midifile[current++] = (unsigned char)(duration >> 8); 394 midifile[current++] = (unsigned char)(duration >> 8);
391 midifile[current++] = (unsigned char)duration; 395 midifile[current++] = (unsigned char)duration;
392 396
393 started = true; 397 started = true;
394 } 398 }
395 } 399 }
396 if (!started) continue; 400 if (!started) continue;
397 duration = GSM_RingNoteGetFullDuration(*Note); 401 duration = GSM_RingNoteGetFullDuration(*Note);
398 if (Note->Note == Note_Pause) { 402 if (Note->Note == Note_Pause) {
399 pause += duration; 403 pause += duration;
400#ifdef singlepauses 404#ifdef singlepauses
401 WriteVarLen(midifile,&current,pause); 405 WriteVarLen(midifile,&current,pause);
402 pause=0; 406 pause=0;
403 midifile[current++]=0x00; // pause 407 midifile[current++]=0x00; // pause
404 midifile[current++]=0x00; 408 midifile[current++]=0x00;
405#endif 409#endif
406 } else { 410 } else {
407 if (Note->Note >= Note_C && Note->Note <= Note_H) { 411 if (Note->Note >= Note_C && Note->Note <= Note_H) {
408 note = Note->Note/16 + 12 * Note->Scale - 1; 412 note = Note->Note/16 + 12 * Note->Scale - 1;
409 } 413 }
410 414
411 WriteVarLen(midifile,&current,pause); 415 WriteVarLen(midifile,&current,pause);
412 pause=0; 416 pause=0;
413 midifile[current++]=0x90; // note on 417 midifile[current++]=0x90; // note on
414 midifile[current++]=note; 418 midifile[current++]=note;
415 midifile[current++]=0x64; // forte 419 midifile[current++]=0x64; // forte
416 420
417 WriteVarLen(midifile,&current,duration); 421 WriteVarLen(midifile,&current,duration);
418 midifile[current++]=0x80; // note off 422 midifile[current++]=0x80; // note off
419 midifile[current++]=note; 423 midifile[current++]=note;
420 midifile[current++]=0x64; 424 midifile[current++]=0x64;
421 } 425 }
422 } 426 }
423 } 427 }
424 if (pause) { 428 if (pause) {
425 WriteVarLen(midifile,&current,pause); 429 WriteVarLen(midifile,&current,pause);
426 midifile[current++]=0x00; // pause 430 midifile[current++]=0x00; // pause
427 midifile[current++]=0x00; // 431 midifile[current++]=0x00; //
428 } 432 }
429 midifile[current++] = 0x00; 433 midifile[current++] = 0x00;
430 midifile[current++] = 0xFF; // track end 434 midifile[current++] = 0xFF; // track end
431 midifile[current++] = 0x2F; 435 midifile[current++] = 0x2F;
432 midifile[current++] = 0x00; 436 midifile[current++] = 0x00;
433 midifile[length++] = (current-22) >> 8; 437 midifile[length++] = (current-22) >> 8;
434 midifile[length++] = current-22; 438 midifile[length++] = current-22;
435 439
436 fwrite(midifile,1,current,file); 440 fwrite(midifile,1,current,file);
437} 441}
438 442
439#endif 443#endif
440 444
441void saveott(FILE *file, GSM_Ringtone *ringtone) 445void saveott(FILE *file, GSM_Ringtone *ringtone)
442{ 446{
443 char Buffer[2000]; 447 char Buffer[2000];
444 int i=2000; 448 int i=2000;
445 449
446 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i); 450 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i);
447 451
448 fwrite(Buffer, 1, i, file); 452 fwrite(Buffer, 1, i, file);
449} 453}
450 454
451GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone) 455GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
452{ 456{
453 FILE *file; 457 FILE *file;
454 458
455 file = fopen(FileName, "wb"); 459 file = fopen(FileName, "wb");
456 if (file == NULL) return ERR_CANTOPENFILE; 460 if (file == NULL) return ERR_CANTOPENFILE;
457 461
458 switch (ringtone->Format) { 462 switch (ringtone->Format) {
459 case RING_NOTETONE: 463 case RING_NOTETONE:
460 if (strstr(FileName,".ott")) { 464 if (strstr(FileName,".ott")) {
461 saveott(file,ringtone); 465 saveott(file,ringtone);
462#ifndef ENABLE_LGPL 466#ifndef ENABLE_LGPL
463 } else if (strstr(FileName,".mid")) { 467 } else if (strstr(FileName,".mid")) {
464 savemid(file,ringtone); 468 savemid(file,ringtone);
465#endif 469#endif
466 } else if (strstr(FileName,".rng")) { 470 } else if (strstr(FileName,".rng")) {
467 saveott(file,ringtone); 471 saveott(file,ringtone);
468 } else if (strstr(FileName,".imy")) { 472 } else if (strstr(FileName,".imy")) {
469 saveimelody(file,ringtone); 473 saveimelody(file,ringtone);
470 } else if (strstr(FileName,".ime")) { 474 } else if (strstr(FileName,".ime")) {
471 saveimelody(file,ringtone); 475 saveimelody(file,ringtone);
472 } else if (strstr(FileName,".wav")) { 476 } else if (strstr(FileName,".wav")) {
473 savewav(file,ringtone); 477 savewav(file,ringtone);
474 } else { 478 } else {
475 saverttl(file, ringtone); 479 saverttl(file, ringtone);
476 } 480 }
477 break; 481 break;
478 case RING_NOKIABINARY: 482 case RING_NOKIABINARY:
479 savebin(file, ringtone); 483 savebin(file, ringtone);
480 break; 484 break;
481 case RING_MIDI: 485 case RING_MIDI:
482 savepuremidi(file, ringtone); 486 savepuremidi(file, ringtone);
483 break; 487 break;
484 } 488 }
485 489
486 fclose(file); 490 fclose(file);
487 491
488 return ERR_NONE; 492 return ERR_NONE;
489} 493}
490 494
491static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone) 495static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
492{ 496{
493 GSM_RingNoteScale DefNoteScale= Scale_880; 497 GSM_RingNoteScale DefNoteScale= Scale_880;
494 GSM_RingNoteDuration DefNoteDuration= Duration_1_4; 498 GSM_RingNoteDuration DefNoteDuration= Duration_1_4;
495 GSM_RingNoteStyle DefNoteStyle= NaturalStyle; 499 GSM_RingNoteStyle DefNoteStyle= NaturalStyle;
496 int DefNoteTempo= 63, i=0; 500 int DefNoteTempo= 63, i=0;
497 501
498 unsigned char buffer[2000],Name[100]; 502 unsigned char buffer[2000],Name[100];
499 GSM_RingNote *Note; 503 GSM_RingNote *Note;
500 504
501 fread(buffer, 2000, 1, file); 505 fread(buffer, 2000, 1, file);
502 506
503 ringtone->NoteTone.NrCommands = 0; 507 ringtone->NoteTone.NrCommands = 0;
504 508
505 /* -------------- name ---------------- */ 509 /* -------------- name ---------------- */
506 while (buffer[i] != ':') { 510 while (buffer[i] != ':') {
507 if (buffer[i] == 0x00) return ERR_NONE; 511 if (buffer[i] == 0x00) return ERR_NONE;
508 i++; 512 i++;
509 } 513 }
510 if (i == 0) { 514 if (i == 0) {
511 /* This is for RTTL ringtones without name. */ 515 /* This is for RTTL ringtones without name. */
512 EncodeUnicode(ringtone->Name,"Gammu",5); 516 EncodeUnicode(ringtone->Name,"Gammu",5);
513 } else { 517 } else {
514 memcpy(Name,buffer,i); 518 memcpy(Name,buffer,i);
515 Name[i] = 0x00; 519 Name[i] = 0x00;
516 EncodeUnicode(ringtone->Name,Name,strlen(Name)); 520 EncodeUnicode(ringtone->Name,Name,strlen(Name));
517 } 521 }
518 i++; 522 i++;
519 523
520 /* --------- section with default ringtone settings ----------- */ 524 /* --------- section with default ringtone settings ----------- */
521 while(1) { 525 while(1) {
522 switch (buffer[i]) { 526 switch (buffer[i]) {
523 case ':': 527 case ':':
524 break; 528 break;
525 case 0x00: 529 case 0x00:
526 return ERR_NONE; 530 return ERR_NONE;
527 case 'd': case 'D': 531 case 'd': case 'D':
528 switch (atoi(buffer+i+2)) { 532 switch (atoi(buffer+i+2)) {
529 case 1: DefNoteDuration = Duration_Full; break; 533 case 1: DefNoteDuration = Duration_Full; break;
530 case 2: DefNoteDuration = Duration_1_2 ; break; 534 case 2: DefNoteDuration = Duration_1_2 ; break;
531 case 4: DefNoteDuration = Duration_1_4 ; break; 535 case 4: DefNoteDuration = Duration_1_4 ; break;
532 case 8: DefNoteDuration = Duration_1_8 ; break; 536 case 8: DefNoteDuration = Duration_1_8 ; break;
533 case 16: DefNoteDuration = Duration_1_16; break; 537 case 16: DefNoteDuration = Duration_1_16; break;
534 case 32: DefNoteDuration = Duration_1_32; break; 538 case 32: DefNoteDuration = Duration_1_32; break;
535 } 539 }
536 break; 540 break;
537 case 'o': case 'O': 541 case 'o': case 'O':
538 switch (atoi(buffer+i+2)) { 542 switch (atoi(buffer+i+2)) {
539 case 4: DefNoteScale = Scale_440 ; break; 543 case 4: DefNoteScale = Scale_440 ; break;
540 case 5: DefNoteScale = Scale_880 ; break; 544 case 5: DefNoteScale = Scale_880 ; break;
541 case 6: DefNoteScale = Scale_1760; break; 545 case 6: DefNoteScale = Scale_1760; break;
542 case 7: DefNoteScale = Scale_3520; break; 546 case 7: DefNoteScale = Scale_3520; break;
543 } 547 }
544 break; 548 break;
545 case 'b': case 'B': 549 case 'b': case 'B':
546 DefNoteTempo=atoi(buffer+i+2); 550 DefNoteTempo=atoi(buffer+i+2);
547 dbgprintf("Tempo = %i\n",DefNoteTempo); 551 dbgprintf("Tempo = %i\n",DefNoteTempo);
548 break; 552 break;
549 case 's': case 'S': 553 case 's': case 'S':
550 switch (buffer[i+1]) { 554 switch (buffer[i+1]) {
551 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 555 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
552 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 556 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
553 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 557 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
554 } 558 }
555 switch (buffer[i+2]) { 559 switch (buffer[i+2]) {
556 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 560 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
557 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 561 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
558 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 562 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
559 } 563 }
560 break; 564 break;
561 } 565 }
562 while (buffer[i] != ':' && buffer[i] != ',') { 566 while (buffer[i] != ':' && buffer[i] != ',') {
563 if (buffer[i] == 0x00) return ERR_NONE; 567 if (buffer[i] == 0x00) return ERR_NONE;
564 i++; 568 i++;
565 } 569 }
566 if (buffer[i] == ',') i++; 570 if (buffer[i] == ',') i++;
567 if (buffer[i] == ':') break; 571 if (buffer[i] == ':') break;
568 } 572 }
569 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); 573 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
570 dbgprintf("DefNoteScale=%d\n", DefNoteScale); 574 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
571 i++; 575 i++;
572 576
573 /* ------------------------- notes ------------------------------ */ 577 /* ------------------------- notes ------------------------------ */
574 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) { 578 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) {
575 switch(buffer[i]) { 579 switch(buffer[i]) {
576 case 'z': case 'Z': 580 case 'z': case 'Z':
577 switch (buffer[i+1]) { 581 switch (buffer[i+1]) {
578 case 'd': 582 case 'd':
579 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED; 583 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
580 ringtone->NoteTone.NrCommands++; 584 ringtone->NoteTone.NrCommands++;
581 break; 585 break;
582 case 'D': 586 case 'D':
583 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED; 587 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
584 ringtone->NoteTone.NrCommands++; 588 ringtone->NoteTone.NrCommands++;
585 break; 589 break;
586 case 'v': 590 case 'v':
587 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra; 591 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra;
588 ringtone->NoteTone.NrCommands++; 592 ringtone->NoteTone.NrCommands++;
589 break; 593 break;
590 case 'V': 594 case 'V':
591 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra; 595 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
592 ringtone->NoteTone.NrCommands++; 596 ringtone->NoteTone.NrCommands++;
593 break; 597 break;
594 case 'l': 598 case 'l':
595 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight; 599 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight;
596 ringtone->NoteTone.NrCommands++; 600 ringtone->NoteTone.NrCommands++;
597 break; 601 break;
598 case 'L': 602 case 'L':
599 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight; 603 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
600 ringtone->NoteTone.NrCommands++; 604 ringtone->NoteTone.NrCommands++;
601 } 605 }
602 break; 606 break;
603 case 'o': case 'O': 607 case 'o': case 'O':
604 switch (buffer[i+2]) { 608 switch (buffer[i+2]) {
605 case 4: DefNoteScale = Scale_440 ; break; 609 case 4: DefNoteScale = Scale_440 ; break;
606 case 5: DefNoteScale = Scale_880 ; break; 610 case 5: DefNoteScale = Scale_880 ; break;
607 case 6: DefNoteScale = Scale_1760; break; 611 case 6: DefNoteScale = Scale_1760; break;
608 case 7: DefNoteScale = Scale_3520; break; 612 case 7: DefNoteScale = Scale_3520; break;
609 } 613 }
610 break; 614 break;
611 case 's': case 'S': 615 case 's': case 'S':
612 switch (buffer[i+1]) { 616 switch (buffer[i+1]) {
613 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 617 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
614 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 618 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
615 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 619 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
616 } 620 }
617 switch (buffer[i+2]) { 621 switch (buffer[i+2]) {
618 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 622 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
619 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 623 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
620 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 624 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
621 } 625 }
622 break; 626 break;
623 default: 627 default:
624 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; 628 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
625 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; 629 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
626 Note->Style = DefNoteStyle; 630 Note->Style = DefNoteStyle;
627 Note->Tempo = DefNoteTempo; 631 Note->Tempo = DefNoteTempo;
628 Note->Scale = DefNoteScale; 632 Note->Scale = DefNoteScale;
629 Note->Duration = DefNoteDuration; 633 Note->Duration = DefNoteDuration;
630 Note->DurationSpec = NoSpecialDuration; 634 Note->DurationSpec = NoSpecialDuration;
631 Note->Note = Note_Pause; 635 Note->Note = Note_Pause;
632 636
633 /* Duration */ 637 /* Duration */
634 switch (atoi(buffer+i)) { 638 switch (atoi(buffer+i)) {
635 case 1: Note->Duration = Duration_Full ; break; 639 case 1: Note->Duration = Duration_Full ; break;
636 case 2: Note->Duration = Duration_1_2 ; break; 640 case 2: Note->Duration = Duration_1_2 ; break;
637 case 4: Note->Duration = Duration_1_4 ; break; 641 case 4: Note->Duration = Duration_1_4 ; break;
638 case 8: Note->Duration = Duration_1_8 ; break; 642 case 8: Note->Duration = Duration_1_8 ; break;
639 case 16: Note->Duration = Duration_1_16 ; break; 643 case 16: Note->Duration = Duration_1_16 ; break;
640 case 32: Note->Duration = Duration_1_32 ; break; 644 case 32: Note->Duration = Duration_1_32 ; break;
641 } 645 }
642 /* We skip all numbers from duration specification */ 646 /* We skip all numbers from duration specification */
643 while(isdigit(buffer[i])) i++; 647 while(isdigit(buffer[i])) i++;
644 648
645 /* Some files can have special duration here */ 649 /* Some files can have special duration here */
646 if (buffer[i]=='.') { 650 if (buffer[i]=='.') {
647 Note->DurationSpec = DottedNote; 651 Note->DurationSpec = DottedNote;
648 i++; 652 i++;
649 } 653 }
650 654
651 /* Note */ 655 /* Note */
652 /* B or b is not in specs, but I decided to put it, because 656 /* B or b is not in specs, but I decided to put it, because
653 * it's in some RTTL files. It's the same to H note */ 657 * it's in some RTTL files. It's the same to H note */
654 switch (buffer[i]) { 658 switch (buffer[i]) {
655 case 'A': case 'a': Note->Note = Note_A; break; 659 case 'A': case 'a': Note->Note = Note_A; break;
656 case 'B': case 'b': Note->Note = Note_H; break; 660 case 'B': case 'b': Note->Note = Note_H; break;
657 case 'C': case 'c': Note->Note = Note_C; break; 661 case 'C': case 'c': Note->Note = Note_C; break;
658 case 'D': case 'd': Note->Note = Note_D; break; 662 case 'D': case 'd': Note->Note = Note_D; break;
659 case 'E': case 'e': Note->Note = Note_E; break; 663 case 'E': case 'e': Note->Note = Note_E; break;
660 case 'F': case 'f': Note->Note = Note_F; break; 664 case 'F': case 'f': Note->Note = Note_F; break;
661 case 'G': case 'g': Note->Note = Note_G; break; 665 case 'G': case 'g': Note->Note = Note_G; break;
662 case 'H': case 'h': Note->Note = Note_H; break; 666 case 'H': case 'h': Note->Note = Note_H; break;
663 } 667 }
664 i++; 668 i++;
665 669
666 if (buffer[i]=='#') { 670 if (buffer[i]=='#') {
667 switch (Note->Note) { 671 switch (Note->Note) {
668 case Note_A : Note->Note = Note_Ais; break; 672 case Note_A : Note->Note = Note_Ais; break;
669 case Note_C : Note->Note = Note_Cis; break; 673 case Note_C : Note->Note = Note_Cis; break;
670 case Note_D : Note->Note = Note_Dis; break; 674 case Note_D : Note->Note = Note_Dis; break;
671 case Note_F : Note->Note = Note_Fis; break; 675 case Note_F : Note->Note = Note_Fis; break;
672 case Note_G : Note->Note = Note_Gis; break; 676 case Note_G : Note->Note = Note_Gis; break;
673 default : break; 677 default : break;
674 } 678 }
675 i++; 679 i++;
676 } 680 }
677 681
678 /* Some files can have special duration here */ 682 /* Some files can have special duration here */
679 if (buffer[i]=='.') { 683 if (buffer[i]=='.') {
680 Note->DurationSpec = DottedNote; 684 Note->DurationSpec = DottedNote;
681 i++; 685 i++;
682 } 686 }
683 687
684 /* Scale */ 688 /* Scale */
685 if (Note->Note!=Note_Pause && isdigit(buffer[i])) { 689 if (Note->Note!=Note_Pause && isdigit(buffer[i])) {
686 switch (atoi(buffer+i)) { 690 switch (atoi(buffer+i)) {
687 case 4: Note->Scale = Scale_440 ; break; 691 case 4: Note->Scale = Scale_440 ; break;
688 case 5: Note->Scale = Scale_880 ; break; 692 case 5: Note->Scale = Scale_880 ; break;
689 case 6: Note->Scale = Scale_1760; break; 693 case 6: Note->Scale = Scale_1760; break;
690 case 7: Note->Scale = Scale_3520; break; 694 case 7: Note->Scale = Scale_3520; break;
691 } 695 }
692 i++; 696 i++;
693 } 697 }
694 698
695 ringtone->NoteTone.NrCommands++; 699 ringtone->NoteTone.NrCommands++;
696 break; 700 break;
697 } 701 }
698 while (buffer[i] != ',') { 702 while (buffer[i] != ',') {
699 if (buffer[i] == 0x00) return ERR_NONE; 703 if (buffer[i] == 0x00) return ERR_NONE;
700 i++; 704 i++;
701 } 705 }
702 if (buffer[i] == ',') i++; 706 if (buffer[i] == ',') i++;
703 } 707 }
704 708
705 return ERR_NONE; 709 return ERR_NONE;
706} 710}
707 711
708static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone) 712static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
709{ 713{
710 char Buffer[2000]; 714 char Buffer[2000];
711 int i; 715 int i;
712 716
713 i=fread(Buffer, 1, 2000, file); 717 i=fread(Buffer, 1, 2000, file);
714 718
715 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i); 719 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
716} 720}
717 721
718static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone) 722static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
719{ 723{
720 char Buffer[4000]; 724 char Buffer[4000];
721 int i,j; 725 int i,j;
722 726
723 i=fread(Buffer, 1, 4000, file); 727 i=fread(Buffer, 1, 4000, file);
724 728
725 i=0;j=0; 729 i=0;j=0;
726 while (true) { 730 while (true) {
727 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 && 731 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
728 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break; 732 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
729 if (j==i-4) return ERR_UNKNOWN; 733 if (j==i-4) return ERR_UNKNOWN;
730 j++; 734 j++;
731 } 735 }
732 j++; 736 j++;
733 737
734 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j); 738 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j);
735} 739}
736 740
737static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone) 741static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
738{ 742{
739 int i; 743 int i;
740 unsigned charbuffer[2000]; 744 unsigned charbuffer[2000];
741 745
742 dbgprintf("loading binary\n"); 746 dbgprintf("loading binary\n");
743 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); 747 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
744 i=5; 748 i=5;
745 while (buffer[i]!=0x00) i++; 749 while (buffer[i]!=0x00) i++;
746 EncodeUnicode(ringtone->Name,buffer+5,i-5); 750 EncodeUnicode(ringtone->Name,buffer+5,i-5);
747 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) { 751 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
748 i++; 752 i++;
749 } 753 }
750 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i; 754 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
751 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length); 755 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
752 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); 756 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
753 return ERR_NONE; 757 return ERR_NONE;
754} 758}
755 759
756static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone) 760static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
757{ 761{
758 unsigned char buffer[30000]; 762 unsigned char buffer[30000];
759 763
760 dbgprintf("loading midi\n"); 764 dbgprintf("loading midi\n");
761 EncodeUnicode(ringtone->Name,"MIDI",4); 765 EncodeUnicode(ringtone->Name,"MIDI",4);
762 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file); 766 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
763 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length); 767 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
764 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); 768 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
765 return ERR_NONE; 769 return ERR_NONE;
766} 770}
767 771
768static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone) 772static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
769{ 773{
770 unsigned char buffer[2000]; 774 unsigned char buffer[2000];
771 775
772 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); 776 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
773 777
774 if (buffer[18]==0x00 && buffer[21]!=0x02) { 778 if (buffer[18]==0x00 && buffer[21]!=0x02) {
775 /* DCT3, Unicode subformat, 62xx & 7110 */ 779 /* DCT3, Unicode subformat, 62xx & 7110 */
776 CopyUnicodeString(ringtone->Name,buffer+18); 780 CopyUnicodeString(ringtone->Name,buffer+18);
777 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2); 781 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
778 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length); 782 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
779 } else { 783 } else {
780 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */ 784 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
781 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]); 785 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
782 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name)); 786 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
783 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length); 787 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
784 } 788 }
785 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name)); 789 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
786 return ERR_NONE; 790 return ERR_NONE;
787} 791}
788 792
789GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone) 793GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
790{ 794{
791 FILE *file; 795 FILE *file;
792 unsigned charbuffer[300]; 796 unsigned charbuffer[300];
793 GSM_Errorerror = ERR_UNKNOWN; 797 GSM_Errorerror = ERR_UNKNOWN;
794 798
795 dbgprintf("Loading ringtone %s\n",FileName); 799 dbgprintf("Loading ringtone %s\n",FileName);
796 file = fopen(FileName, "rb"); 800 file = fopen(FileName, "rb");
797 if (file == NULL) return ERR_CANTOPENFILE; 801 if (file == NULL) return ERR_CANTOPENFILE;
798 802
799 /* Read the header of the file. */ 803 /* Read the header of the file. */
800 fread(buffer, 1, 4, file); 804 fread(buffer, 1, 4, file);
801 if (ringtone->Format == 0x00) { 805 if (ringtone->Format == 0x00) {
802 ringtone->Format = RING_NOTETONE; 806 ringtone->Format = RING_NOTETONE;
803 if (buffer[0]==0x00 && buffer[1]==0x00 && 807 if (buffer[0]==0x00 && buffer[1]==0x00 &&
804 buffer[2]==0x0C && buffer[3]==0x01) { 808 buffer[2]==0x0C && buffer[3]==0x01) {
805 ringtone->Format = RING_NOKIABINARY; 809 ringtone->Format = RING_NOKIABINARY;
806 } 810 }
807 if (buffer[0]==0x00 && buffer[1]==0x00 && 811 if (buffer[0]==0x00 && buffer[1]==0x00 &&
808 buffer[2]==0x00) { 812 buffer[2]==0x00) {
809 ringtone->Format = RING_NOKIABINARY; 813 ringtone->Format = RING_NOKIABINARY;
810 } 814 }
811 if (buffer[0]==0x4D && buffer[1]==0x54 && 815 if (buffer[0]==0x4D && buffer[1]==0x54 &&
812 buffer[2]==0x68 && buffer[3]==0x64) { 816 buffer[2]==0x68 && buffer[3]==0x64) {
813 ringtone->Format = RING_MIDI; 817 ringtone->Format = RING_MIDI;
814 } 818 }
815 } 819 }
816 rewind(file); 820 rewind(file);
817 switch (ringtone->Format) { 821 switch (ringtone->Format) {
818 case RING_NOTETONE: 822 case RING_NOTETONE:
819 if (buffer[0]==0x02 && buffer[1]==0x4A) { 823 if (buffer[0]==0x02 && buffer[1]==0x4A) {
820 error=loadott(file,ringtone); 824 error=loadott(file,ringtone);
821 } else if (buffer[0]==0xC7 && buffer[1]==0x45) { 825 } else if (buffer[0]==0xC7 && buffer[1]==0x45) {
822 error=loadcommunicator(file,ringtone); 826 error=loadcommunicator(file,ringtone);
823 } else { 827 } else {
824 error=loadrttl(file,ringtone); 828 error=loadrttl(file,ringtone);
825 } 829 }
826 ringtone->NoteTone.AllNotesScale=false; 830 ringtone->NoteTone.AllNotesScale=false;
827 break; 831 break;
828 case RING_NOKIABINARY: 832 case RING_NOKIABINARY:
829 if (buffer[0]==0x00 && buffer[1]==0x00 && 833 if (buffer[0]==0x00 && buffer[1]==0x00 &&
830 buffer[2]==0x0C && buffer[3]==0x01) { 834 buffer[2]==0x0C && buffer[3]==0x01) {
831 error=loadbin(file,ringtone); 835 error=loadbin(file,ringtone);
832 } 836 }
833 if (buffer[0]==0x00 && buffer[1]==0x00 && 837 if (buffer[0]==0x00 && buffer[1]==0x00 &&
834 buffer[2]==0x00) { 838 buffer[2]==0x00) {
835 error=loadre(file,ringtone); 839 error=loadre(file,ringtone);
836 } 840 }
837 break; 841 break;
838 case RING_MIDI: 842 case RING_MIDI:
839 EncodeUnicode(ringtone->Name,FileName,strlen(FileName)); 843 EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
840 error = loadpuremidi(file,ringtone); 844 error = loadpuremidi(file,ringtone);
841 } 845 }
842 fclose(file); 846 fclose(file);
843 return(error); 847 return(error);
844} 848}
845 849
846/* -------------------------- required with Nokia & RTTL ------------------- */ 850/* -------------------------- required with Nokia & RTTL ------------------- */
847 851
848/* Beats per Minute like written in Smart Messaging */ 852/* Beats per Minute like written in Smart Messaging */
849static int SM_BeatsPerMinute[] = { 853static int SM_BeatsPerMinute[] = {
850 25, 28, 31, 35, 40, 45, 50, 56, 63,70, 854 25, 28, 31, 35, 40, 45, 50, 56, 63,70,
851 80, 90, 100, 112, 125, 140, 160, 180, 200,225, 855 80, 90, 100, 112, 125, 140, 160, 180, 200,225,
852 250, 285, 320, 355, 400, 450, 500, 565, 635,715, 856 250, 285, 320, 355, 400, 450, 500, 565, 635,715,
853 800,900 857 800,900
854}; 858};
855 859
856int GSM_RTTLGetTempo(int Beats) 860int GSM_RTTLGetTempo(int Beats)
857{ 861{
858 int i=0; 862 int i=0;
859 863
860 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++; 864 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
861 865
862 return i<<3; 866 return i<<3;
863} 867}
864 868
865/* This function packs the ringtone from the structure "ringtone" to 869/* This function packs the ringtone from the structure "ringtone" to
866 "package", where maxlength means length of package. 870 "package", where maxlength means length of package.
867 Function returns number of packed notes and change maxlength to 871 Function returns number of packed notes and change maxlength to
868 number of used chars in "package" */ 872 number of used chars in "package" */
869unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength) 873unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength)
870{ 874{
871 unsigned char CommandLength = 0x02; 875 unsigned char CommandLength = 0x02;
872 unsigned char Loop = 0x15;/* Infinite */ 876 unsigned char Loop = 0x15;/* Infinite */
873 877
874 unsigned char Buffer[200]; 878 unsigned char Buffer[200];
875 int StartBit=0, OldStartBit; 879 int StartBit=0, OldStartBit;
876 int StartBitHowManyCommands; 880 int StartBitHowManyCommands;
877 int HowManyCommands = 0;/* How many instructions packed */ 881 int HowManyCommands = 0;/* How many instructions packed */
878 int HowManyNotes= 0; 882 int HowManyNotes= 0;
879 int i,j; 883 int i,j;
880 bool started; 884 bool started;
881 GSM_RingNote *Note; 885 GSM_RingNote *Note;
882 886
883 GSM_RingNoteScale DefScale = 255; 887 GSM_RingNoteScale DefScale = 255;
884 GSM_RingNoteStyle DefStyle = 255; 888 GSM_RingNoteStyle DefStyle = 255;
885 int DefTempo = 255; 889 int DefTempo = 255;
886 890
887 AddBufferByte(package, &StartBit, CommandLength, 8); 891 AddBufferByte(package, &StartBit, CommandLength, 8);
888 AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7); 892 AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7);
889 893
890 /* According to specification we need have next part octet-aligned */ 894 /* According to specification we need have next part octet-aligned */
891 BufferAlign(package, &StartBit); 895 BufferAlign(package, &StartBit);
892 896
893 AddBufferByte(package, &StartBit, SM_Command_Sound, 7); 897 AddBufferByte(package, &StartBit, SM_Command_Sound, 7);
894 AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3); 898 AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3);
895 899
896 /* Packing the name of the tune. */ 900 /* Packing the name of the tune. */
897 EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name)); 901 EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name));
898 AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4); 902 AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4);
899 AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer)); 903 AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer));
900 904
901 /* Packing info about song pattern */ 905 /* Packing info about song pattern */
902 AddBufferByte(package, &StartBit, 0x01, 8); //one pattern 906 AddBufferByte(package, &StartBit, 0x01, 8); //one pattern
903 AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3); 907 AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3);
904 AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2); 908 AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2);
905 AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4); 909 AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4);
906 910
907 /* Later here will be HowManyCommands */ 911 /* Later here will be HowManyCommands */
908 StartBitHowManyCommands=StartBit; 912 StartBitHowManyCommands=StartBit;
909 StartBit = StartBit + 8; 913 StartBit = StartBit + 8;
910 914
911 started = false; 915 started = false;
912 for (i=0; i<ringtone.NoteTone.NrCommands; i++) { 916 for (i=0; i<ringtone.NoteTone.NrCommands; i++) {
913 if (ringtone.NoteTone.Commands[i].Type != RING_Note) { 917 if (ringtone.NoteTone.Commands[i].Type != RING_Note) {
914 HowManyNotes++; 918 HowManyNotes++;
915 continue; 919 continue;
916 } 920 }
917 Note = &ringtone.NoteTone.Commands[i].Note; 921 Note = &ringtone.NoteTone.Commands[i].Note;
918 if (!started) { 922 if (!started) {
919 /* First note can't be Pause - it makes problems 923 /* First note can't be Pause - it makes problems
920 * for example with PC Composer 924 * for example with PC Composer
921 */ 925 */
922 if (Note->Note != Note_Pause) started = true; 926 if (Note->Note != Note_Pause) started = true;
923 } 927 }
924 if (!started) { 928 if (!started) {
925 HowManyNotes++; 929 HowManyNotes++;
926 continue; 930 continue;
927 } 931 }
928 OldStartBit = StartBit; 932 OldStartBit = StartBit;
929 /* we don't write Scale & Style info before "Pause" note - it saves place */ 933 /* we don't write Scale & Style info before "Pause" note - it saves place */
930 if (Note->Note!=Note_Pause) { 934 if (Note->Note!=Note_Pause) {
931 if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) { 935 if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) {
932 j = StartBit+5+8; 936 j = StartBit+5+8;
933 BufferAlignNumber(&j); 937 BufferAlignNumber(&j);
934 if ((j/8)>(*maxlength)) { 938 if ((j/8)>(*maxlength)) {
935 StartBit = OldStartBit; 939 StartBit = OldStartBit;
936 break; 940 break;
937 } 941 }
938 DefScale = Note->Scale; 942 DefScale = Note->Scale;
939 AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3); 943 AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3);
940 AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2); 944 AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2);
941 HowManyCommands++; 945 HowManyCommands++;
942 } 946 }
943 if (DefStyle != Note->Style) { 947 if (DefStyle != Note->Style) {
944 j = StartBit+5+8; 948 j = StartBit+5+8;
945 BufferAlignNumber(&j); 949 BufferAlignNumber(&j);
946 if ((j/8)>(*maxlength)) { 950 if ((j/8)>(*maxlength)) {
947 StartBit = OldStartBit; 951 StartBit = OldStartBit;
948 break; 952 break;
949 } 953 }
950 DefStyle = Note->Style; 954 DefStyle = Note->Style;
951 AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3); 955 AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3);
952 AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2); 956 AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2);
953 HowManyCommands++; 957 HowManyCommands++;
954 } 958 }
955 } 959 }
956 /* Beats per minute/tempo of the tune */ 960 /* Beats per minute/tempo of the tune */
957 if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) { 961 if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) {
958 j = StartBit+8+8; 962 j = StartBit+8+8;
959 BufferAlignNumber(&j); 963 BufferAlignNumber(&j);
960 if ((j/8)>(*maxlength)) { 964 if ((j/8)>(*maxlength)) {
961 StartBit = OldStartBit; 965 StartBit = OldStartBit;
962 break; 966 break;
963 } 967 }
964 DefTempo=GSM_RTTLGetTempo(Note->Tempo); 968 DefTempo=GSM_RTTLGetTempo(Note->Tempo);
965 /* Adding beats per minute (tempo) of the tune */ 969 /* Adding beats per minute (tempo) of the tune */
966 AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3); 970 AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3);
967 AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5); 971 AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5);
968 HowManyCommands++; 972 HowManyCommands++;
969 } 973 }
970 j = StartBit+12+8; 974 j = StartBit+12+8;
971 BufferAlignNumber(&j); 975 BufferAlignNumber(&j);
972 if ((j/8)>(*maxlength)) { 976 if ((j/8)>(*maxlength)) {
973 StartBit = OldStartBit; 977 StartBit = OldStartBit;
974 break; 978 break;
975 } 979 }
976 /* Note */ 980 /* Note */
977 AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3); 981 AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3);
978 AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4); 982 AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4);
979 AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3); 983 AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3);
980 AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2); 984 AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2);
981 HowManyCommands++; 985 HowManyCommands++;
982 /* We are sure, we pack it for SMS or setting to phone, not for OTT file */ 986 /* We are sure, we pack it for SMS or setting to phone, not for OTT file */
983 if (*maxlength<1000) { 987 if (*maxlength<1000) {
984 /* Like Pc Composer say - before of phone limitations...*/ 988 /* Like Pc Composer say - before of phone limitations...*/
985 if (HowManyNotes==130-1) break; 989 if (HowManyNotes==130-1) break;
986 } 990 }
987 HowManyNotes++; 991 HowManyNotes++;
988 } 992 }
989 993
990 BufferAlign(package, &StartBit); 994 BufferAlign(package, &StartBit);
991 AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8); 995 AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8);
992 996
993 OldStartBit = StartBit; 997 OldStartBit = StartBit;
994 StartBit = StartBitHowManyCommands; 998 StartBit = StartBitHowManyCommands;
995 /* HowManyCommands */ 999 /* HowManyCommands */
996 AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8); 1000 AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8);
997 StartBit = OldStartBit; 1001 StartBit = OldStartBit;
998 1002
999 *maxlength=StartBit/8; 1003 *maxlength=StartBit/8;
1000 1004
1001 return(i); 1005 return(i);
1002} 1006}
1003 1007
1004GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength) 1008GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength)
1005{ 1009{
1006 int StartBit=0, HowMany, l, q, i, spec; 1010 int StartBit=0, HowMany, l, q, i, spec;
1007 char Buffer[100]; 1011 char Buffer[100];
1008 GSM_RingNote *Note; 1012 GSM_RingNote *Note;
1009 1013
1010 /* Default ringtone parameters */ 1014 /* Default ringtone parameters */
1011 GSM_RingNoteScale DefScale= Scale_880; 1015 GSM_RingNoteScale DefScale= Scale_880;
1012 GSM_RingNoteStyle DefStyle = NaturalStyle; 1016 GSM_RingNoteStyle DefStyle = NaturalStyle;
1013 int DefTempo= 63; 1017 int DefTempo= 63;
1014 1018
1015 ringtone->Format = RING_NOTETONE; 1019 ringtone->Format = RING_NOTETONE;
1016 ringtone->NoteTone.NrCommands = 0; 1020 ringtone->NoteTone.NrCommands = 0;
1017 1021
1018 GetBufferInt(package,&StartBit,&l,8); 1022 GetBufferInt(package,&StartBit,&l,8);
1019 if (l!=0x02) { 1023 if (l!=0x02) {
1020 dbgprintf("Not header\n"); 1024 dbgprintf("Not header\n");
1021 return ERR_NOTSUPPORTED; 1025 return ERR_NOTSUPPORTED;
1022 } 1026 }
1023 1027
1024 GetBufferInt(package,&StartBit,&l,7); 1028 GetBufferInt(package,&StartBit,&l,7);
1025 if (l!=SM_Command_RingingToneProgramming) { 1029 if (l!=SM_Command_RingingToneProgramming) {
1026 dbgprintf("Not RingingToneProgramming\n"); 1030 dbgprintf("Not RingingToneProgramming\n");
1027 return ERR_NOTSUPPORTED; 1031 return ERR_NOTSUPPORTED;
1028 } 1032 }
1029 1033
1030 /* According to specification we need have next part octet-aligned */ 1034 /* According to specification we need have next part octet-aligned */
1031 BufferAlignNumber(&StartBit); 1035 BufferAlignNumber(&StartBit);
1032 1036
1033 GetBufferInt(package,&StartBit,&l,7); 1037 GetBufferInt(package,&StartBit,&l,7);
1034 if (l!=SM_Command_Sound) { 1038 if (l!=SM_Command_Sound) {
1035 dbgprintf("Not Sound\n"); 1039 dbgprintf("Not Sound\n");
1036 return ERR_NOTSUPPORTED; 1040 return ERR_NOTSUPPORTED;
1037 } 1041 }
1038 1042
1039 GetBufferInt(package,&StartBit,&l,3); 1043 GetBufferInt(package,&StartBit,&l,3);
1040 if (l!=SM_Song_BasicSongType) { 1044 if (l!=SM_Song_BasicSongType) {
1041 dbgprintf("Not BasicSongType\n"); 1045 dbgprintf("Not BasicSongType\n");
1042 return ERR_NOTSUPPORTED; 1046 return ERR_NOTSUPPORTED;
1043 } 1047 }
1044 1048
1045 /* Getting length of the tune name */ 1049 /* Getting length of the tune name */
1046 GetBufferInt(package,&StartBit,&l,4); 1050 GetBufferInt(package,&StartBit,&l,4);
1047 l=l>>4; 1051 l=l>>4;
1048 1052
1049 /* Unpacking the name of the tune. */ 1053 /* Unpacking the name of the tune. */
1050 GetBuffer(package, &StartBit, Buffer, 8*l); 1054 GetBuffer(package, &StartBit, Buffer, 8*l);
1051 Buffer[l]=0; 1055 Buffer[l]=0;
1052 EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer)); 1056 EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer));
1053 DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name)); 1057 DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name));
1054 CopyUnicodeString(ringtone->Name,Buffer); 1058 CopyUnicodeString(ringtone->Name,Buffer);
1055 1059
1056 GetBufferInt(package,&StartBit,&l,8); 1060 GetBufferInt(package,&StartBit,&l,8);
1057 dbgprintf("Number of song patterns: %i\n",l); 1061 dbgprintf("Number of song patterns: %i\n",l);
1058 /* we support only one song pattern */ 1062 /* we support only one song pattern */
1059 if (l!=1) return ERR_NOTSUPPORTED; 1063 if (l!=1) return ERR_NOTSUPPORTED;
1060 1064
1061 GetBufferInt(package,&StartBit,&l,3); 1065 GetBufferInt(package,&StartBit,&l,3);
1062 if (l!=SM_InstructionID_PatternHeaderId) { 1066 if (l!=SM_InstructionID_PatternHeaderId) {
1063 dbgprintf("Not PatternHeaderId\n"); 1067 dbgprintf("Not PatternHeaderId\n");
1064 return ERR_NOTSUPPORTED; 1068 return ERR_NOTSUPPORTED;
1065 } 1069 }
1066 1070
1067 /* Pattern ID - we ignore it */ 1071 /* Pattern ID - we ignore it */
1068 StartBit+=2; 1072 StartBit+=2;
1069 1073
1070 GetBufferInt(package,&StartBit,&l,4); 1074 GetBufferInt(package,&StartBit,&l,4);
1071 l=l>>4; 1075 l=l>>4;
1072 dbgprintf("Loop value: %i\n",l); 1076 dbgprintf("Loop value: %i\n",l);
1073 1077
1074 HowMany=0; 1078 HowMany=0;
1075 GetBufferInt(package, &StartBit, &HowMany, 8); 1079 GetBufferInt(package, &StartBit, &HowMany, 8);
1076 1080
1077 for (i=0;i<HowMany;i++) { 1081 for (i=0;i<HowMany;i++) {
1078 GetBufferInt(package,&StartBit,&q,3); 1082 GetBufferInt(package,&StartBit,&q,3);
1079 switch (q) { 1083 switch (q) {
1080 case SM_InstructionID_VolumeInstructionId: 1084 case SM_InstructionID_VolumeInstructionId:
1081 StartBit+=4; 1085 StartBit+=4;
1082 break; 1086 break;
1083 case SM_InstructionID_StyleInstructionId: 1087 case SM_InstructionID_StyleInstructionId:
1084 GetBufferInt(package,&StartBit,&l,2); 1088 GetBufferInt(package,&StartBit,&l,2);
1085 if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l; 1089 if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l;
1086 break; 1090 break;
1087 case SM_InstructionID_TempoInstructionId: 1091 case SM_InstructionID_TempoInstructionId:
1088 GetBufferInt(package,&StartBit,&l,5); 1092 GetBufferInt(package,&StartBit,&l,5);
1089 DefTempo=SM_BeatsPerMinute[l>>3]; 1093 DefTempo=SM_BeatsPerMinute[l>>3];
1090 break; 1094 break;
1091 case SM_InstructionID_ScaleInstructionId: 1095 case SM_InstructionID_ScaleInstructionId:
1092 GetBufferInt(package,&StartBit,&l,2); 1096 GetBufferInt(package,&StartBit,&l,2);
1093 DefScale=(l>>6)+4; 1097 DefScale=(l>>6)+4;
1094 break; 1098 break;
1095 case SM_InstructionID_NoteInstructionId: 1099 case SM_InstructionID_NoteInstructionId:
1096 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; 1100 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
1097 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; 1101 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
1098 1102
1099 GetBufferInt(package,&StartBit,&l,4); 1103 GetBufferInt(package,&StartBit,&l,4);
1100 Note->Note=Note_Pause; 1104 Note->Note=Note_Pause;
1101 if (l >= Note_C && l <= Note_H) Note->Note = l; 1105 if (l >= Note_C && l <= Note_H) Note->Note = l;
1102 1106
1103 GetBufferInt(package,&StartBit,&l,3); 1107 GetBufferInt(package,&StartBit,&l,3);
1104 if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l; 1108 if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l;
1105 1109
1106 GetBufferInt(package,&StartBit,&spec,2); 1110 GetBufferInt(package,&StartBit,&spec,2);
1107 if (spec >= NoSpecialDuration && spec <= Length_2_3) { 1111 if (spec >= NoSpecialDuration && spec <= Length_2_3) {
1108 Note->DurationSpec = spec; 1112 Note->DurationSpec = spec;
1109 } 1113 }
1110 1114
1111 Note->Scale = DefScale; 1115 Note->Scale = DefScale;
1112 Note->Style = DefStyle; 1116 Note->Style = DefStyle;
1113 Note->Tempo = DefTempo; 1117 Note->Tempo = DefTempo;
1114 if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break; 1118 if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break;
1115 ringtone->NoteTone.NrCommands++; 1119 ringtone->NoteTone.NrCommands++;
1116 break; 1120 break;
1117 default: 1121 default:
1118 dbgprintf("Unsupported block %i %i\n",q,i); 1122 dbgprintf("Unsupported block %i %i\n",q,i);
1119 return ERR_NOTSUPPORTED; 1123 return ERR_NOTSUPPORTED;
1120 } 1124 }
1121 } 1125 }
1122 return ERR_NONE; 1126 return ERR_NONE;
1123} 1127}
1124 1128
1125static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src) 1129static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src)
1126{ 1130{
1127 int current = 0, i, note, lastnote = 0, duration; 1131 int current = 0, i, note, lastnote = 0, duration;
1128 GSM_RingNote *Note; 1132 GSM_RingNote *Note;
1129 unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40, 1133 unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
1130 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE, 1134 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
1131 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B}; 1135 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B};
1132 1136